読者です 読者をやめる 読者になる 読者になる

$shibayu36->blog;

プログラミングの話や自分の考えを色々と書いています。特にperl、emacsや読んだ本の話が多いです。

git gcの自動実行はいつ行われるのか

gitを使ってるとたまにgit gcが走る。これがどういうタイミングで実行されているか調べたので軽くメモしておく。

Gitでは時々auto gcが走る

Git - メインテナンスとデータリカバリ を見ると、以下のように書かれている。

Git は時々 "auto gc" と呼ばれるコマンドを自動的に実行します。大抵の場合、このコマンドは何もしません。もし沢山の緩いオブジェクト(パックファイルの中にないオブジェクト)があったり、あまりに多くのパックファイルがあると、Git は完全な(full-fledged)git gc コマンドを開始します。

さらに、auto gcは普段は何もせず、特定の条件を満たすと実際にgcするとも書かれている。

繰り返しますが、これは通常は何も行いません。約 7,000個もの緩いオブジェクトがあるか、または50以上のパックファイルがないと、Gitは実際に gc コマンドを開始しません。これらのリミットは設定ファイルの gc.auto と gc.autopacklimit によってそれぞれ変更することができます。

では緩いオブジェクトとパックファイルとはなんだろうか。

緩いオブジェクトとパックファイル

緩いオブジェクトとパックファイルについて知るには Git - パックファイル を見るのが良い。gitは保存した内容やcommit情報などをすべてファイルで管理している。これは.git/objects/以下に存在している。ここを見るとわかるが、2文字ディレクトリの下にsha1で名前付けられたファイルがたくさんある。また、packというディレクトリ以下にもファイルが存在する。この中で、2文字ディレクトリ以下にあるものが緩いオブジェクトで、packディレクトリ以下にあるものがパックファイルである。

このため、緩いオブジェクトとパックファイルはこの下のファイルを数えることで知ることができる。これはcount-objectsというコマンドでも調べることができる。ファイル数とcount-objectsで表示されたものを比べると確かに一致していることも分かる。

$ git count-objects -v
count: 457
size: 2336
in-pack: 327127
packs: 1
size-pack: 268511
prune-packable: 0
garbage: 0
size-garbage: 0

ここで出ているcountというのが緩いオブジェクトの数で、packsというのがパックファイルの数である。この数がしきい値を超えた時にgit gcが実際に走るようだ。

さらにgitの内部構造を知ろうと思ったら、以下のドキュメントが非常に参考になるのでおすすめ。

koseki.hatenablog.com

時々、とはいつか

上では「Git は時々 "auto gc" と呼ばれるコマンドを自動的に実行します」と書いた。では時々とはいつか。

調べてみるとgit help configのgc.autoの項目に少し情報が載っていた。https://www.kernel.org/pub/software/scm/git/docs/git-config.html

When there are approximately more than this many loose objects in the repository, git gc --auto will pack them. Some Porcelain commands use this command to perform a light-weight garbage collection from time to time. The default value is 6700. Setting this to 0 disables it.

つまりいくつかの「Porcelain commands」でgit gc --autoが実行されるようだ。


「Porcelain commands」というのが何か分からなかったので、さらに調べてみると http://schacon.github.io/git/git.html に情報が載っていた。これによるとgitではhigh levelコマンドのことをPorcelain commands、low levelコマンドのことをPlumbing commandsと呼んでいるらしい。gitは内部でやっているようなこともコマンドで提供してくれていたりするので、このように命名を分けているのかもしれない。代表的なPorcelain commandsはgit addやgit commit、代表的なPlumbing commandsにはgit ls-remoteやgit for-each-refなどがある。


以上からgitでよく使う上位コマンドのいくつかでgit gc --autoが実行されるということが分かった。

上位コマンドのいくつかとはどれか

どのコマンドで実行されているのか調べてみたか、情報を見つけること出来なかった。ここまで来るとコードを読まないと分からないのかもしれない。gitの内部コードを読んでみたらいまいち分からなかったが、twitterで教えてもらえた。


https://github.com/git/git/search?utf8=%E2%9C%93&q=argv_gc_auto
確かにこの検索方法で100%正しいかわからないが、おそらくfetchやmergeのタイミングで呼ばれているように見える。

まとめ

今回調べたことから、gitはPorcelain commandsの一種のfetchやmergeなどのタイミング(これは本当かどうか曖昧)で、git gc --autoを実行し、その時に約7,000個の緩いオブジェクトがあるか、または50以上のパックファイルがあると、実際にgit gcを走らせるということが分かった。

これ以上のことや、さらに正確な情報を調べようとするとコードを読むしかないだろう。読んでみようとしたけど、いまいち理解は出来なかった。たまにGitやMySQLなどの挙動を知りたくなるけどコード読もうとして失敗するということがあるので、どこかのタイミングでC言語C++辺りをきちんと勉強したい。

池上彰の「日本の教育」がよくわかる本を読んだ

 教育については前から少し興味があったけど、そういえば全くそれに関する本を読んだことがないなと思ったので、とりあえずざっくり学ぶために簡単でわかりやすそうな本から読んだ。

 この本は池上彰が、戦後日本の教育の歴史や現在の教育制度の仕組み、海外ではどうなっているのかをかいつまんで解説してくれる本。全体的にこれまでの教育改革や、今後の教育についての変更に関して批判的に解説しているのが面白かった。


 この本を読んで、教育の歴史や教育委員会とは何か、ゆとり教育とはなんだったのかなどについてざっくり学べた。一番面白かったなあと思うのは、教育の改革が思い込みや印象論で語られることが多いという部分。


 この本の最初の方に

  • 教育制度は変えてからその結果が出るまでに時間がかかる
  • また成果が数値化できないものも多い
  • その結果教育に関する改革は、得てして思い込みや印象論で語られることが多い

ということが書かれていた。

 例えば、脱ゆとり教育についてもそういう面があっただろうと思う。ゆとり教育が始まった後すぐにPISAという学力テストが行われた際、世界における日本の順位が下がったと大きく報道されたことがあった。その時、2002年に行われたゆとり教育実施から2年ほどしか経っていないのにかかわらず、このテストの結果だけを見てゆとり教育は失敗だといったようなことが報道され、最終的に最近は脱ゆとり教育の方向に進んでいるように見える。この数値が本当にゆとり教育のせいか正しく検証されないままにである。このことは報道などの思い込みからまた教育制度が変えられていくという一つの例なのかなと思った。

 またこのことからやはりメディアの情報に対しては正しく接する必要があると思った。メディアは珍しいことを報道する傾向が強いとこの本に書かれていたが、確かにそのとおりだと思う。メディアで大きく報道されたからと言ってそれが正しいと思い込まないように気をつけていきたい。これまでも気をつけてきたつもりだったけど、この本を読んで、何か自分の考えがあり、それを補強するような報道がなされた時に、無意識にそれを正しいと思い込んでいたかもしれないと改めて反省した。


 教育についてはまた興味が出てきたら面白そうな本を読んでみようと思う。良い本があったら知りたい。

elasticsearchにwikipediaのデータをインデックスする

elasticsearchの機能を試すように何かしらデータを入れてみたかったので、wikipediaのデータをelasticsearchに適当にインデックスしてみた。

wikipediaのデータセット

wikipediaのデータセットWikipedia:データベースダウンロード - Wikipedia 辺りからダウンロードできる。いろんなデータがあるが、今回はhttp://dumps.wikimedia.org/jawiki/latest/ の中にあるpages-article1.xml.bz2辺りを利用する。

wikipediaデータのインデックス

https://github.com/shibayu36/wikipedia-elasticsearch にサンプルを置いてある。

perlで適当に書いているので、最初にcarton installだけしておいてください。

elasticsearchのセットアップ

elasticsearch自体のセットアップをするためにscript/setupを呼ぶとそのディレクトリのelasticsearch/以下にセットアップしてくれるようにしてみた。内部的にはelasticsearchのtarを取ってきて展開しているのと、pluginを入れてみているだけ。

carton exec -- perl script/setup

elasticsearchの起動

elasticsearch以下に置いてあるので、以下のコマンドで起動。

$ elasticsearch/bin/elasticsearch

wikipedia用のmappingsを作成

今回はそれぞれのページのidとタイトルと本文をインデックスするようにしてみる。

$es->indices->create(
    index => 'wikipedia',
    body  => {
        settings => {
            index => {
                analysis => {
                    tokenizer => {
                        text_ja_tokenizer => {
                            type => 'kuromoji_tokenizer',
                            mode => 'search',
                        },
                    },
                    analyzer => {
                        text_ja_analyzer => {
                            tokenizer => 'text_ja_tokenizer',
                            type => 'custom',
                            filter => [
                                'kuromoji_part_of_speech',
                                'icu_normalizer',
                            ],
                            char_filter => [
                                'html_strip'
                            ],
                        },
                    },
                },
            },
        },
        mappings => {
            page => {
                properties => {
                    id    => +{ type => 'long', index => 'not_analyzed' },
                    title => +{ type => 'string', index => 'analyzed', analyzer => 'text_ja_analyzer' },
                    text  => +{ type => 'string', index => 'analyzed', analyzer => 'text_ja_analyzer' },
                },
            },
        },
    },
);

上はjsonAPI叩く部分をperlのインターフェースでやっているだけ。elasticsearchを起動した上で、このスクリプトを叩く。

$ carton exec -- perl script/create-elasticsearch-index.pl

wikipediaのデータをインポート

あとはダウンロードして展開したデータをインポートしてみる。

carton exec -- perl script/import-wikipedia.pl jawiki-latest-pages-articles1.xml

ファイル全部読み込んでツリー構造を構築し、全部メモリに持っているので、あんまり良くない。実際にはもうちょっと工夫とかしたほうが良さそう。

まとめ

今回はwikipediaのデータをelasticsearchにインデックスしてみたメモを書いた。本当は https://github.com/takumakanari/embulk-parser-xml こういうのを使えるともっと良かったのだけど、少し複雑なxmlをうまく扱えなかったので、perlスクリプトを書いてみた。