Maven central repo の artifact を PageRank でランキングする / #渋谷java 発表メモ

第二十回 #渋谷java で、Maven central repository 上の artifact に対して依存関係の有向グラフを作り PageRank でランキングしてみる、というお話をしてきたメモです。

はじめに

Java や Scala などでそれなりの規模のアプリケーションコードを書いていると、少なからず Maven central repository に登録されている何かしらのライブラリやフレームワーク、すなわち artifact を利用することになるかと思います。

普段使い慣れているライブラリならいざ知らず、初めて利用を試みる、同等の機能を提供する複数のライブラリがあった場合にどの artifact を使うべきか、その判断が概ね定性的なもの (日本語での解説記事の有無やその質など) に頼らざるを得ないことが多いように思います。

そのような場合において、例えば rubygems.org であれば (役に立つかは別として)「gem のダウンロード回数」という定量的なメトリクスを判断材料として利用することもできますが、Maven central ではそのような統計情報は提供されていません。1

今回は、この「複数の選択肢があった場合に、どの artifact を利用するのがいいのか?」の意思決定を手助けすることを目的に、artifact の依存関係に基づく有向グラフを作って PageRank を計算し、artifact 同士をスコアで比較可能にしてみた、という発表をしてきました。

(発表資料は当ブログエントリの最後に掲載しています)

Maven central repository のデータを収集する

Artifact の依存関係に基づく有向グラフを作るためには、その依存関係の情報を何らかの方法で収集する必要があります。

Maven においては、依存関係は pom.xml にすべて記述されているため、依存関係を取得することはすなわち各 artifact の pom.xml をクロールすることに相当します。

では、手当たり次第に artifact の pom.xml をダウンロードすればよいのか? というとそういうわけにもいきません。バージョン違いを含めた artifact は Maven central に 200 万以上登録されており、それらをすべてダウンロードするのは時間的にも容量的にも非効率です。2

そのため「各 artifact の最新バージョンの pom.xml だけを入手する」といったルールを設けて効率よくダウンロードしたいところですが、次はその「Artifact の最新バージョンをどのように把握すればよいのか?」という問題が生じます。

これを解決するには、Maven central の index を利用する方法があります。同 index には、artifact の基本的な情報 (Group ID, Artifact ID, Version, Classifier) や artifact とともに ファイルの最終更新日時 が各レコードに記録されているので、artifact ごとにこの最終更新日時が最も新しいレコードを探しだすことで、最新バージョンを容易に特定できます。3

PageRank を計算する

Maven central repository の各 artifact について pom.xml を入手できたら、後は依存関係を抽出し、有向グラフで表現したのちに PageRank を計算… となります。

PageRank の計算は、Apache Spark の GraphX を利用するのが手っ取り早いでしょう。GraphX での PageRank 計算はとても簡単で、PageRank の例 にあるように、

  1. エッジを張る 2 点のノードの ID を半角スペース区切りで並べて記述して 1 行を構成し、それをエッジの数だけ列挙したファイルを用意する
  2. GraphLoader.edgeListFile(sc, "path/go/graph.txt") でそのファイルを読み込む
  3. Graph#pageRank(tol, resetProb) で PageRank を計算する

という手順を踏むだけです。

PageRank によるランキング結果

今回の実験では、依存関係のスコープの組み合わせとして「すべて」「compile のみ」「test のみ」「すべて (エッジの向きが逆)」それぞれについて有向グラフを作り、別々に PageRank を計算してみました。

それぞれのパターンでのランキング結果 Top 100 の artifact 一覧を以下の Google スプレッドシートにまとめてみました。

http://bit.ly/PackageRank

当然のことながら、様々な artifact から参照されうるテスト関連やロギング関連の artifact が Top 100 の多くを占めている感じがしますが、この結果は直感と照らし合わせてもまあまあ妥当なんじゃないかな、と思います。

まとめ

「Artifact 同士の依存関係の情報」を入手するのがちょっと面倒ではありますが、PageRank で artifact の重要性を測る、という試みはそこそこ上手くいくように思いました。

ただ、Maven central repository は、古くから存在する artifact ほどたくさんの参照を集めやすく、従ってそれらの PageRank のスコアも高めに出る、という傾向があるのではないかと推測しています。そのため「ここ最近よく参照されてる新しめのイケてる artifact はどれだろう?」といったトレンドを把握する目的で PageRank スコアを求める場合は、ちょっと工夫が必要そうに思えたのでした。

発表資料


  1. mvnrepository.com では非公式ながら、他の artifact で参照されている回数を提供していたりします。 

  2. そもそも、robots.txt 的に User-agent: *\nDisallow: / なので、さすがに / から再帰的に漏れなく徘徊するのはまずかろうと… 

  3. 具体的に、どうやって index ファイルを走査すればいいのか、という話題はまた別のブログエントリにまとめる予定です。