Stack Overflow のタグから、どのフレームワークについてよく質問されているのかプログラミング言語ごとに分析してみた

Stack Overflow の質問には、その内容を示すタグが付与されています。

このタグ、よく見ると「言語」+ 「フレームワークやライブラリの名称」という構成が多いです。 つまり、これを分析すれば、言語ごとに質問の多い(つまり、よく使われている、人気がある)フレームワークやライブラリが何か分かるのではないでしょうか。

そこで今回は、kaggle で公開されていた Stack Overflow Data ^dataをもとに、質問に付与されたタグの出現回数を言語ごと×1年ごとに集計し、ランキングを算出しました。

より詳細なデータは こちら

解析結果

それぞれの言語ごとに、簡単な概要と解析結果(年度ごとのタグ出現回数ランキング)をまとめました。

Java

  • Spring Boot が登場1と同時に急上昇
  • ORM マッパは依然 Hibernate が上位
  • Swing の順位が低下すると入れ替えに、Java FX が上昇
タグ 2018 2017 2016 2015 2014 2013 2012 2011 2010 2009
android 1 1 1 1 1 1 1 1 1 20
spring 2 2 2 2 3 4 4 4 4 4
spring-boot 3 3 13 33 145 1567 10490 8932 6891 4822
hibernate 4 4 4 6 6 6 5 5 3 2
maven 5 5 7 7 7 12 15 22 87 498
arrays 6 6 5 5 5 5 11 12 24 26
json 7 8 8 8 12 11 18 28 59 174
javafx 8 13 14 19 29 72 160 595 422 295
eclipse 9 9 6 4 4 3 3 3 5 3
swing 10 7 3 3 2 2 2 2 2 1

Go

  • 基本的な言語仕様に関するタグが多い
  • Docker や MongoDB といったモダンな技術の組合わせが多い
  • ORM マッパーは GORM が人気
タグ 2018 2017 2016 2015 2014 2013 2012 2011 2010 2009
json 1 1 1 1 1 2 7 20 19 16
struct 2 2 3 3 3 9 4 45 9 92
http 3 3 2 4 4 3 7 2 44 92
goroutine 4 4 6 6 5 4 14 3 2 1
docker 5 6 16 33 48 173 567 283 130 92
mongodb 6 7 5 7 8 23 23 82 130 92
slice 7 5 7 5 19 7 18 10 19 92
concurrency 8 9 10 10 7 5 2 5 44 7
arrays 9 9 8 7 16 17 23 13 2 92
go-gorm 10 19 27 47 163 858 567 283 130 92

Python

  • 2016 年に Python3.x が Python-2.7 を上回った
    • Python 3.0 が2008年登場ということを考えるとかなり遅い
  • 機械学習や計算ライブラリの質問が多言語に比べ多い
  • Django (Webアプリケーションライブラリ) が一貫して上位にいる
タグ 2018 2017 2016 2015 2014 2013 2012 2011 2010 2009
python-3.x 1 1 3 4 5 4 6 7 18 21
pandas 2 2 2 3 4 6 20 1055 4807 3368
django 3 3 1 1 1 1 1 1 1 1
numpy 4 5 5 5 3 3 2 4 6 16
tensorflow 5 9 18 251 9023 5310 7081 6103 4807 3368
dataframe 6 6 9 23 55 93 251 2258 2827 3368
python-2.7 7 4 4 2 2 2 4 78 314 850
matplotlib 8 7 7 7 7 8 8 8 21 54
list 9 8 6 6 6 5 3 3 4 3
flask 10 14 11 10 11 13 12 74 259 3368

PHP

  • Laravel タグが急上昇
  • 全体的に Web 関連のタグがとても多い
  • Codeigniter が10年間安定した順位を保っている
タグ 2018 2017 2016 2015 2014 2013 2012 2011 2010 2009
laravel 1 2 4 6 9 19 195 3248 5129 3341
mysql 2 1 1 1 1 1 1 1 1 1
javascript 3 3 2 2 2 2 2 2 2 2
wordpress 4 6 6 5 7 8 9 11 10 19
html 5 4 3 3 3 3 4 4 3 3
jquery 6 5 5 4 4 4 3 3 4 6
ajax 7 8 8 8 8 6 6 6 8 8
arrays 8 7 7 7 6 5 5 5 5 7
codeigniter 9 9 9 9 10 9 7 7 9 16
sql 10 13 12 12 5 7 8 9 11 9

Ruby

タグ 2018 2017 2016 2015 2014 2013 2012 2011 2010 2009
ruby-on-rails 1 1 1 1 1 1 1 1 1 1
ruby-on-rails-5 2 3 13 635 3910 3822 3612 3206 2469 1702
rubygems 3 6 5 15 16 11 8 3 2 3
ruby-on-rails-4 4 2 2 2 2 3 1218 1307 1284 908
activerecord 5 5 4 5 6 5 3 4 3 2
rspec 6 7 3 6 4 4 5 7 9 15
arrays 7 4 6 4 5 7 10 9 7 5
javascript 8 9 8 8 9 16 16 14 15 25
postgresql 9 11 12 13 15 24 34 63 88 132
ruby-on-rails-3 10 8 7 3 3 2 2 2 4 588

JavaScript

  • ライブラリは jQuery, React.js, Angurlar の順にランクイン
  • Node.js は毎年順位が上がってきている
  • Ajax が下がってきている(当たり前に使えるようになった?)
タグ 2018 2017 2016 2015 2014 2013 2012 2011 2010 2009
jquery 1 1 1 1 1 1 1 1 1 1
html 2 2 2 2 2 2 2 2 2 2
reactjs 3 6 9 15 111 942 7551 6176 4367 2899
node.js 4 4 5 6 7 9 9 15 48 491
css 5 3 4 4 3 3 4 4 5 5
angular 6 11 13 239 6645 8935 7551 6176 4367 2899
php 7 7 6 5 5 4 3 3 3 6
arrays 8 9 10 10 10 12 17 17 19 21
ajax 9 8 7 7 6 5 5 5 4 3
typescript 10 12 17 71 134 158 256 6176 4367 2899

SQL

  • SQL Server が予想外の1位
    • T-SQL 3も7位につけているところを見ると、意外と使われているっぽい
  • Oracle も安定して上位
  • 言語仕様に関するものでは Join がランクイン
タグ 2018 2017 2016 2015 2014 2013 2012 2011 2010 2009
sql-server 1 1 1 1 2 2 2 2 1 1
mysql 2 2 2 2 1 1 1 1 2 2
oracle 3 3 3 3 4 4 5 7 6 5
postgresql 4 4 6 6 8 9 9 11 10 17
php 5 5 4 4 3 3 4 4 9 8
database 6 6 5 5 6 6 6 6 5 6
tsql 7 7 7 8 9 8 7 5 3 3
c# 8 8 8 7 5 7 8 8 7 7
java 9 11 10 10 10 10 11 13 17 20
join 10 10 11 11 11 11 10 12 12 13

おわりに

当然の結果にだったものもあれば意外な結果だったものも多数あるのではないでしょうか。 元データの方では、上位30位まで見れますので興味があれば合わせてご覧ください。 Tag trends by language for Stack Overflow | Kaggle


  1. 2014年4月1日にバージョン 1.0 が GA

  2. バージョンアップしないの…?

  3. SQL Server で使用する、SQLを手続型に拡張した言語

Java のバージョンを上げるだけで、プログラムは速くなるのか

よく Java の実行バージョンを上げるだけで速くなるという話を聞きます。 でも、本当にそうなのでしょうか。また、本当だとしたらどれぐらい速くなるのでしょうか。

そこで、簡単なプログラムで実験してみました。

実験概要

実験用に、数独を解く Java のプログラムを作成しました。 このプログラムは単純な演算を繰り返し行ってるだけなので、Webアプリケーションのような複雑なプログラムとはおそらく傾向が違いますが、参考程度にはなるかなと思います。

これをJava 1.1 でコンパイルし、Java 1.1 ~ 12 の各 Oracle JDK (32bit/64bit) で数独100万問のデータセットを読み込んで解き終わるまでの時間を測定しました。1

細かい測定条件は以下の通り。

  • 実行環境
    • Windwos 10 Home 1809 (64bit)
    • Intel Core i7-7500 CPU @ 2.70GHz
  • Java の実行オプション
    • -mx512m -ms512mを付与2
    • Java 1.3.1 以降は、-server を付与3
  • 測定方法
    • 各バージョンごとに5回測定し、中央値を取得

実験結果

処理は二つのパートに分かれているので、その処理ごとグラフ軸を分けました。

  • 数独100万問のデータセットを読み込む処理 (下図の青い部分)
    • この部分は、主に GC の性能に左右される
  • 数独を解く処理 (下図の赤い部分)
    • この部分は、主に JIT 最適化の性能に左右される

その実験結果がこちら。 処理時間(ms)

グラフの元データ...

|Java|Version|データ読み込み(ms)|数独解析(ms)|合計(ms)| |--:|--:|--:|--:|--:| |Java 1.1 (32bit)|1.1.8|8,313|4,231|12,544| |Java 1.2 (32bit)|1.2.2_017|6,647|4,360|11,006| |Java 1.3 (32bit)|1.3.0_05|10,747|6,905|17,652| |Java 1.3.1 (32bit)|1.3.1_28|7,647|5,093|12,740| |Java 1.4 (32bit)|1.4.0_04|8,061|4,741|12,802| |Java 1.4.1 (32bit)|1.4.1_07|7,810|4,796|12,606| |Java 1.4.2 (32bit)|1.4.2_19|3,437|3,281|6,717| |Java 5 (32bit)|1.5.0_22|3,050|3,289|6,338| |Java 6 (32bit)|1.6.0_45|3,530|4,077|7,607| |Java 7 (32bit)|1.7.0_80|3,411|3,211|6,622| |Java 8 (32bit)|1.8.0_202|3,239|3,257|6,496| |Java 6 (64bit)|1.6.0_45|5,029|3,312|8,341| |Java 7 (64bit)|1.7.0_80|7,019|3,148|10,167| |Java 8 (64bit)|1.8.0_202|5,050|3,054|8,104| |Java 9 (64bit)|9.0.4|2,101|2,961|5,061| |Java 10 (64bit)|10.0.2|2,056|3,054|5,110| |Java 11 (64bit)|11.0.3|1,922|3,343|5,265| |Java 12 (64bit)|12.0.1|1,934|3,422|5,356|

考察

「今回のプログラムでは」という前提が付きますが、データから以下のことが見て取れます。

  • Java 1.1 に比べて、最近の Java は2倍以上速くなっている
  • Java 1.3 で急激に遅くなっている。まだ、HotSpot が成熟していなかった?
  • Java 1.4.1 までは遅かったが、Java 1.4.2 でぐっと速くなっている
  • Java 6 ~ 8は、64bit VM より 32bit の方がデータ読み込みが速い
  • Java 9 でぐっと速くなっている

まとめ

Java のバージョンを上げるだけで、プログラムは速くなる。


  1. 後方互換性があるので、Java 1.1 でコンパイルしたクラスファイルは、以降のバージョンでもそのまま動きます。

  2. 「あれ -Xmx -Xms じゃないの?」って思うかもしれませんが、Java 1.1 ではこのオプションは -mx -ms になっています。Java 1.2 で VM オプションの -Xmx -Xms に変更になったのですが、いまだに -mx -ms も使えます。

  3. このオプションがないと HotSpot Client VM が使われてしまい、倍ぐらい遅くなります…。

  4. Concurrent Mark Sweep Garbage Collector。このGCについての詳細は、KUBOTA Yuji さんの資料を参照。

  5. https://twitter.com/skrb/status/1161642952420016130

strptime は環境によって挙動が違う

PHP には、日付文字列をパースするための strptime という関数があります。 これを使って、Sun, 19 Apr 2015 11:43:30 GMT という文字列を %a, %d %b %Y %H:%M:%S %Z というフォーマットでパースした結果、以下の通り環境によって異なる結果になりました。 strptime は環境によって挙動が違うんですね。

OS tm_year tm_mon tm_mday tm_hour tm_min tm_sec unparsed
Linux 115 3 19 11 43 30 "GMT"
Mac 115 3 19 20 43 30 ""

Linux の場合は GMT で返ってきましたが、Mac の場合は JST で返ってきました。 (どちらも、OS のタイムゾーン設定は JST です)

どうしてこのような違いが起きたのか、ドキュメントを確認してみました。

PHP のドキュメント

ちゃんとOSにより挙動が異なることが明記されています。

注意: 内部では、 この関数はシステムの C ライブラリ関数 strptime() をコールしています。 このライブラリ関数は、OS によって挙動が異なることがあります。 PHP: strptime - Manual

ただ、どのように挙動が異なるかは記載されていません。そのため、次に各OSのドキュメントを確認してみました。

Linux の場合

フォーマットの指定として %Z (タイムゾーン) を指定することはできるが、無視すると書かれています。

原文: For reasons of symmetry, glibc tries to support for strptime() the same format characters as for strftime(3). (In most cases the corresponding fields are parsed, but no field in tm is changed.) This leads to %Z The timezone name.

日本語: 対象性のために、glibc では strptime() に strftime(3) と同じフォーマット文字をサポートさせようとしている。多くの場合、対応するフィールドが解釈されるが、tm フィールドは変更されない。使用可能なフォーマット文字を以下に示す。 %Z タイムゾーン

そのため、文字列中のタイムゾーンの指定が GMT だろうが JST だろうが、以下のように同じ結果が返ってきます。「11時って書いてあるんだから11時だろ」という解釈です。

入力 tm_year tm_mon tm_mday tm_hour tm_min tm_sec unparsed
Sun, 19 Apr 2015 11:43:30 GMT 115 3 19 11 43 30 "GMT"
Sun, 19 Apr 2015 11:43:30 JST 115 3 19 11 43 30 "JST"

Mac (BSDUNIX) の場合

現地のタイムゾーンに変換してくれるそうです。

原文: The strptime() function parses the string in the buffer buf, according to the string pointed to by format, and fills in the elements of the struc-ture structure ture pointed to by tm. The resulting values will be relative to the local time zone.

日本語: strptime() 関数は、formatが指す文字列に従ってバッファbuf内の文字列を解析し、timeptr が指す構造体の要素にあてはめます。 結果の値は現地のタイムゾーンを基準にしたものになります。

Mac OS X Manual Page For strptime(3)

ただし、文字列中のタイムゾーンとして指定できるのは GMT かローカルタイムゾーン (今回の場合は JST) のみだそうです。

原文: The %Z format specifier only accepts time zone abbreviations of the local time zone, or the value "GMT". This limitation is because of ambiguity due to of the over loading of time zone abbreviations. One such example is EST which is both Eastern Standard Time and Eastern Australia Summer Time.

日本語: %Z フォーマット指定子は、ローカルタイムゾーンタイムゾーンの省略形、または値 "GMT"のみを受け入れます。 この制限は、タイムゾーンの略語のオーバーロードによるあいまいさのためです。 そのような例の1つは、東部標準時と東オーストラリアの夏時間の両方であるESTです。

やってみると、こうなりました。「GMT の11時って書いてあるんだから、現地時間の20時だろ」という解釈です。

入力 tm_year tm_mon tm_mday tm_hour tm_min tm_sec unparsed
Sun, 19 Apr 2015 11:43:30 GMT 115 3 19 20 43 30 ""
Sun, 19 Apr 2015 11:43:30 JST 115 3 19 20 43 30 ""

OSによらず、同じ結果になるようにしたい場合は?

マニュアルに書いてありました。date_parse_from_format 関数を使いましょう。

date_parse_from_format() はこの問題の影響を受けないので、PHP 5.3.0 以降ではこちらの関数を使うことを推奨します。 PHP: strptime - Manual

まとめ

PHP は Write once, Run anywhere じゃなかった。

パラメータ設定が不適切だと、ruby-oci8 より go-oci8 の方が遅くなることもあるので要注意

こんな感じの単純な SQLRuby と Go それぞれで流したら、なぜか Go の方が遅くなりました。 特に text が長いと遅い…。

SELECT
  id
  , text
FROM
  example

使っているライブラリは、ruby-oci8, go-oci8

原因

原因は、それぞれのライブラリのパラメータのデフォルト値が異なるためでした。

ライブラリ prefetch_rows prefetch_memory
ruby-oci8 100 0
go-oci8 0 4,096

ruby-oci8 だと、メモリ使用量に関係なく 100 行をプリフェッチ。 go-oci8 だと、行数に関係なく 4,096 bytes をプリフェッチ。

なので、go-oci8 の方はメモリ使用量は安定して低いのですが、取ってくるデータが多いと何度も細かくフェッチするので遅くなります。

対策

ruby-oci8 と同じ値を接続文字列 (DSN) で設定すれば大丈夫です。 scott/tiger@localhost?prefetch_rows=100&prefetch_memory=0

もしくは、下記のドキュメントを読んでチューニングしてみるといいかも。 プリフェッチ・カウントの設定について - Oracle® Call Interfaceプログラマーズ・ガイド

JJUG CCC 2019 Spring ( #jjug_ccc ) - セッション資料の一覧

JJUG CCC 2019 Spring に行ってきました!


今回はレガシーコード改善のヒントになるネタがないかなーといろいろ話を聞いてきました。弊社の Java、古くなっているものがいくつかあって、それを少しでも楽にしたいというのがモチベーションです。
毎回思うのですが、自分が聞きたい!と思うセッションが必ずある JJUG CCC という場はすごいですね…。


あと、今回は前回よりもさらに海外勢の方が多くいらっしゃっていて、その方と懇親会でコミュニケーション取ろうとして、撃沈しまくったというのも強く印象に残っています。英語を勉強しなきゃ…!っていう強い刺激になりました。
この辺のこと、@yusuke さんがきれいにまとめていました。


今回はボランティアスタッフやったり 時間帯別セッション一覧(タイムテーブル)を勝手に作ったり*1と、少し貢献もできたかなーと思っています。
次は、登壇するぞ!? まずは Call for paper 出すところから!


さて、最後にいつものを。

今回、残念ながら満席だったり時間がかぶってしまって参加できなかったセッションもあった*2ので、あとで読むために現時点で発表者の方が公開されている資料一覧をまとめしました。*3
(あとで JJUG CCC 2019 Spring のページにもリンクが載るかもしれませんが、とりあえず自分の方で調べました)
追記:JJUGGitHub ページで公式な資料一覧が公開されました!
jjug-ccc/slides-articles-2019Spring: JJUG CCC 2019 Spring 登壇資料まとめ

10:00-10:45

12:00-12:45 (ランチセッション)

15:45-16:30

アンカンファレンス

*1:聞いてみたら、有志の方でだれかやってくれないかなー|д゚) とのことでしたw

*2:あと、今回はボランティアスタッフやっていたので、その間のセッションでも気になったのがありました。

*3:発表者のお名前は敬称略とさせていただきました。

JJUG CCC 2019 Spring のスマートフォン用タイムテーブルを作りました

5月18日(土) に開催される JJUG CCC 2019 Spring 、そのスマートフォン用タイムテーブル(セッション一覧)が欲しかったので、作りました!

JJUG CCC 2019 Spring タイムテーブル

http://yujisoftware.github.io/jjug-ccc/2019spring/#/timetable

公式ページのビルドして圧縮された Vue ファイルを手作業でハックして作ったので、本家と同じデザインになっています。 もし怒られたら消します(><)

ぜひご利用ください!!

JavaScript の String.prototype.split() の第二引数 limit は、ほかの言語と意味が違う

JavaScript の split メソッドを使ったら「あれ?」となったのでメモ。

一般的な spilt メソッド

Java, C#, Ruby, Perlsplit メソッドは、第二引数に limit を指定できます。 これを指定すると分割回数が制限されます。
(下記の例だと、文字列を2つに分割しています)

Java
"aaa,bbb,ccc".split(",", 2)
// ==> String[2] { "aaa", "bbb,ccc" }
C#
"aaa,bbb,ccc".Split(new char[]{','}, 2)
// ==> String[2]{ "aaa", "bbb,ccc" }
Ruby
"aaa,bbb,ccc".split(",", 2)
# ==> ["aaa", "bbb,ccc"]
Perl
split(/,/, "aaa,bbb,ccc", 2)
# ==> ("aaa", "bbb,ccc")

JavaScript の spilt メソッド

JavaScriptsplit メソッドも、第二引数に limit を指定できます。 ただ、ほかの言語と意味が違っていて、これを指定すると戻り値の要素数が制限されます。
(下記の例だと、文字列を分割して最初の2つを返しています)

JavaScript
"aaa,bbb,ccc".split(",", 2)
// ==> Array [ "aaa", "bbb" ]

MDN には「見つかった分割結果の数の制限を指定する整数です。」と書かれています。
パッと読んだ感じほかの言語と同じかなっと思ったんですが、よく考えると違ったという…。

お気を付けください!