GitHubで各言語がどの程度利用されているのか集計するサービスを公開しました。
namari
http://namaristats.com
サービスの概要
1日1回(UTCの0時1分から)各言語の利用状況を、GitHub API v3で取得したデータを元に算出しています。
ほぼ全てがSearch APIを利用しているため、公開リポジトリのみが対象です。
言語ごとに、リポジトリ数やユーザー数などAPIから標準で取得可能な値と、増加率や更新率など算出した値、スターの多いリポジトリやフォロワーの多いユーザーなどをまとめています。
他に、今のところ以下の機能を用意しています。
- Rankings わかりやすそうな幾つかの基準で、Top20までのランキングを掲載
- Top100 Map リポジトリのスター数トップ100の、言語の割合をツリーマップで表示
- Top3 Repos 各言語のトップ3リポジトリの一覧
- DataTable その日の全データをソート可能なテーブルと、CSVのダウンロード
対応言語
GitHubのAdvanced Code Searchで選択できる言語を元にしました。ただし、該当するリポジトリが無いものや、少数且つ活動も停止しているようなものを省いて、現時点で158言語です。
なおプログラミング言語と言っても、CSSやHTML、XML、XSLTなども含んだ、プログラミングに関連する特定の言語という程度の基準にしています。
- JavaScript
- Java
- Ruby
- Python
- PHP
- CSS
- C++
- C
- C#
- Objective-C
- Shell
- Perl
- R
- VimL
- Go
- CoffeeScript
- Scala
- Haskell
- HTML
- TeX
- Lua
- Clojure
- Swift
- Emacs Lisp
- Matlab
- Arduino
- Groovy
- ActionScript
- Puppet
- Erlang
- Visual Basic
- Processing
- Assembly
- PowerShell
- Common Lisp
- XML
- ASP
- D
- Scheme
- Rust
- Dart
- OCaml
- TypeScript
- Pascal
- XSLT
- FORTRAN
- Prolog
- Racket
- F#
- Haxe
- VHDL
- Verilog
- Elixir
- Julia
- ColdFusion
- Tcl
- Apex
- AutoHotkey
- IDL
- AppleScript
- Vala
- Standard ML
- Mathematica
- Objective-C++
- Pure Data
- Cuda
- OpenEdge ABL
- LiveScript
- SuperCollider
- Ada
- Coq
- Max
- Smalltalk
- SQL
- Game Maker Language
- Gosu
- AutoIt
- XQuery
- Perl6
- Objective-J
- Elm
- Kotlin
- Awk
- SourcePawn
- Nimrod
- Io
- Scilab
- BlitzBasic
- Eiffel
- Stata
- nesC
- PureScript
- Agda
- NetLogo
- Squirrel
- Xtend
- Forth
- SAS
- DM
- ooc
- SystemVerilog
- UnrealScript
- Mercury
- Rebol
- Idris
- Nix
- Gnuplot
- AspectJ
- Nemerle
- PAWN
- XC
- xBase
- Boo
- CLIPS
- GAP
- MoonScript
- Ceylon
- ANTLR
- VCL
- Monkey
- Arc
- Dylan
- Slash
- Bro
- Factor
- COBOL
- Inform 7
- Propeller Spin
- Oxygene
- Lasso
- Brightscript
- Nu
- Pike
- Opa
- Hy
- Mirah
- J
- KRL
- Parrot
- Component Pascal
- Xojo
- ABAP
- Crystal
- Alloy
- Bluespec
- Frege
- Isabelle
- RobotFramework
- Fantom
- PogoScript
- Augeas
- Clean
- XProc
- Fancy
- Volt
- Red
- ATS
- wisp
経緯
プログラミング言語の利用状況やシェア、影響力などをまとめて定期的に配信しているものでは、以下が有名です。
TIOBE、PYPL、RedMonkの3つは、幾つかの指標を組み合わせて独自のランキングを出すものです。GithutはGitHub ArchiveをGoogle BigQueryで解析しています。
それぞれ個性があって面白いですが、マイナーな言語の扱いが小さく、個々の言語も大きな推移としてまとめられてしまうため、もう少し具体的な利用などが見えると良いのに、と感じていました。
その頃、Goの勉強用で作った http://go-gopher.appspot.com/go-on-github で、GitHub APIを使ってGo限定の利用状況を集めた所、想像より面白く、これをなるべく多くの言語に対応させようと始めました。
GitHub API
namariは、GitHub APIありきのサービスです。GitHubがリポジトリやユーザーの公開情報をAPIとして提供し、しかもそれが無料で手軽に使えることで成り立っています。
制限とアクセストークン
無料のAPIですが、当然リミットが設けられています。APIの種類によってリミットは異なりますが、Search APIの場合、未認証のアクセスでは1分間あたり5アクセスまでとなっています。OAuth等で認証を受けたアクセスの場合、これが1分間あたり20アクセスまで増えます。
※ドキュメントのRate limitによる。ただし実際にリミット確認用のAPIで確認すると、未認証で10、認証で30となっている。ドキュメントが古い?
APIへのアクセスにはOAuthによる認証が標準とされていますが、今回のようにサーバーサイドで単独でAPIを利用するだけなら、"Personal access token"が簡単です。GitHubのユーザー設定のAuthorized applicationsから、"Personal access tokens"の"Generate new token"でトークンを生成できます。
このトークンはその名の通り、個人が自身のリポジトリ等にAPI経由でアクセスするためのものですが、今回の用途であるSearch APIでも有効です。
GitHub APIの問題点
無償で手軽、制限も緩いGitHub APIですが、今回の目的にとっては幾つか問題があります。
なお、今回のサービスでは全くでたらめな結果が変えるわけではないため、これといって対処をしていませんが、GitHub APIを利用する場合は注意した方が良いです。
言語の誤判定
GitHubでは、ホストしているコードの言語を自動で判定しています。判定にはgithub/linguistが使用されていますが、しばしば誤判定が起こります。.gitattributesを使って判定を制御できますが、多くのリポジトリでは全自動です。
Search APIが返す言語
Search APIでリポジトリを検索した場合、結果に含まれる言語は、そのリポジトリで最も分量の多いもの1つになってしまいます。複数の言語が近い分量で使われていても1つですし、付随的なコードの分量が多ければ、そちらが返されてしまいます。
例えばyahoo/pureの場合、CSSのUIフレームワークなので言語もCSSとして判定してほしいのですが、テスト用のHTMLがCSSより多く含まれるため、Search APIでは使用言語がHTMLとなってしまいます。
ユーザーの言語
Search APIでは言語によるユーザーの検索も可能ですが、これにも問題があります。リポジトリなどから、ある言語を明らかに使っているユーザーが、その言語で該当しない場合があります。
Google App Engine / Go
サーバー側のプラットフォームには、GoogleのPaaS、Google App Engineを使っています。クセも強いですが、慣れてしまうと他での開発が面倒でしょうがない、素晴らしいプラットフォームです。
Google App EngineではずっとPythonを使ってきましたが、このサービスから全面的にGoに切り替えました。
サービスの性質やCloudFlareを使っていることなどで、GAE/Goのメリットを充分活かせてはいません。ただ、トータルでとても低コスト且つ、Managed VMなど拡張性も揃ってきています。
今回のサービスの場合、定期更新の動的コンテンツ主体で、コードのほとんどがGitHub API及び取得したJSONの処理です。しかも規模も小さいため、以下のパッケージを使っている程度です。
- mjibson/goon : Datastoreのラッパ
- gorilla/mux : ルーティング
- flosch/pongo2 : テンプレートエンジン
goonもgorilla/muxもシンプルでそう迷いませんが、Twigやjinja2などDjangoライクなテンプレートエンジンに慣れている分、細かい点でpongo2には時々引っかかりました。そこで覚え書きとしてpongo2のひっかかった点。
pongo2のひっかかった点
テンプレートでのプロパティアクセス
DjangoやJinja2では forloop.counter
などと書いて、forのカウントを取得したりします。しかしGoの制限により forloop.Counter
と、プロパティ名の先頭を大文字にする必要があります。
カスタムフィルターの登録
カスタムフィルターの登録はテンプレートエンジンごとで色々作法がありますが、pongo2はこの部分のドキュメントが微妙に分かりにくく、mattnのmattn/goji-wikiなど参考にしました。
package main
import (
"fmt"
"github.com/flosch/pongo2"
_ "github.com/flosch/pongo2-addons"
)
func setPongoFilters() {
pongo2.RegisterFilter("filterName", func(in *pongo2.Value, param *pongo2.Value) (out *pongo2.Value, err *pongo2.Error) {
s, ok := in.Interface().(string)
if !ok {
return nil, &pongo2.Error{
Sender: "filterName",
ErrorMsg: fmt.Sprintf("some error %T ('%v')", in, in),
}
}
return pongo2.AsValue(MyFunc(s)), nil
})
}
- github.com/flosch/pongo2-addons を _ でimport
- pongo2.RegisterFilter()に、フィルター名と無名関数による処理内容を渡す
- Interface()でテンプレートからの入力を受け取る
- pongo2.AsValue()で値を返す
という感じでした。
今後
次は週や月、年単位でのデータ提供と視覚化が目標です。