2007年 10月 06日

index_gem_repository.rb memo

http://jp.rubyist.net/magazine/?0010-PackageManagement の generate_yaml_index.rb はいまはこのなまえ。
カレントディレクトリの gems/* を見て、

  • yaml
  • yaml.Z
  • quick/
    • index # 一行ごとに gem のファイル名が書いてある。
    • index.rz
    • name-version.gemspec.rz

を生成する。yaml には gems/* 以下の Gem::Specification をあつめたやつが入ってる。キャッシュらしい。.rz/.Z は zlib で圧縮されたやつだけど gzip ではない。


rubygems

  • remote_installer.rb
      uri = source + "/gems/#{spec.full_name}.gem"
      response = Gem::RemoteFetcher.fetcher.fetch_path uri
  • incremental_fetcher.rb
109:      zipped_yaml = fetch_path("/quick/" + spec_name + ".gemspec.rz")
123:    def get_quick_index
124:      zipped_index = fetch_path("/quick/index.rz")
  • source_index.rb
300:    # Get the quick index needed for incremental updates.
301:    def fetch_quick_index(source_uri)
302:      zipped_index = fetcher.fetch_path source_uri + '/quick/index.rz'
306:            "No quick index found: " + ex.message
355:          spec_uri = source_uri + "/quick/#{spec_name}.gemspec.rz"

なんか似たようなのがふたつ。

よくみる Bulk updating Gem source index for: は yaml.Z/yaml の更新 (source_index.rb)
quick/* を利用した incremental な source index の更新は

use_incremental = missing_gems.size <= INCREMENTAL_THRESHHOLD

で決まってる。INCREMENTAL_THRESHHOLD = 50。missing_gems はサーバの quick/index[.Z] と、ローカルの spec を比べたときにサーバがわにしかない spec。差分 spec が 50 以上のときと、quick index が利用できないときは常に bulk update により yaml[.Z] が取得される。

yaml[.Z] のサイズは rubyforge のもので .Z が 855KB, 圧縮していないのは 11MB (!) もある (単純に http://gems.rubyforge.org/yaml[.Z] にアクセスすればわかる)。リリースごとに spec は増えていくはずだから、あんだけ大きい gem サーバだとすぐ 50 を超えて bulk update になるだろうと思う。というかおれの使いかただと gem install するごとに毎回 bulk update してる感じだ。quick/index は 140KB。1行に1gem だから、rubyforge がホストしている gem の数は

wget http://gems.rubyforge.org/quick/index
wc -l index

すればわかる。現在だと 8555 gems のようだ (バージョン違いの gem を含む)。

quick/index + 1M ぐらいダウンロードしてきて、伸張して YAML.load してるんだからそりゃ遅いよなぁ。gem の名前ごとに gem サーバをわけるとか、あるいはもっと根本的に解決しないとどんどこ遅くなっていくなぁ。なんか昔の RO のパッチクライアントを思い出した。


>