Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

あなたのJavaコードをスッキリさせる、地味に便利な新API 10選(前編)

こんにちは!
アキバです。

...T3ブログは初登場かもしれません。ハジメマシテ。
以後お見知りおきを。

いよいよ、2014年3月、Java8が正式公開されますね。
f:id:acro-engineer:20140311021635j:plain

なんと言っても、Java8の注目機能はラムダ式ですので、ラムダ式型推論に関する記事は多いです。
世の中で「Java8」と検索すると、皆さんいろいろと記事を書かれているので、おおよその事はこれで分かっちゃうような気がします。

が、

実は地味に便利なAPIが追加されていたりすることを最近知りました。

これはあまり触れられていないぞ、と。

というわけで、このエントリでは、あまり日本語で情報の無い、しかし地味に便利なAPIに実際に触れてみます。

大事なところなので2回強調して書いてみました。


今回は、前編として4つ紹介します。

APIの紹介と言いつつ、コードにはラムダ式を使ったコードが普通に出てるので、ご了承ください。
 (むしろ、こういったコードを見ながらラムダ式の実際を理解するのもイイかも?)

1. 文字列結合編

これまでのコード

これまでの文字列結合は、おおよそ以下のような感じだと思います。
ここでは、Stringの配列からカンマ区切りの文字列を作る例を考えてみましょう。
(この例は配列ですが、通常はList<String>を使うことが多いと思います)

String[] strArray = { "abc", "def", "123", "456", "xyz" };
String separator = ",";

StringBuilder sb = new StringBuilder();
for (String str : strArrayt) {
    if (sb.length() > 0) {
        sb.append(separator);
    }
    sb.append(str);
}

System.out.println(sb.toString());
// → abc,def,123,456,xyz という文字列が表示される

こんな処理を簡単に書くためのAPIがJava8で追加されました。
(もっと昔からあっても良かったようなものですよね…)

主なものは次の2つです。

(1) String#join(CharSequence, Iterable)

1つ目の新APIは、Stringクラスに追加されたjoinメソッド
文字列を直接並べることもできますが、メインとなるのは配列やListなどのIterableを使う方でしょう。
String#join()を使うと、先ほどのコードは以下のように書き換えることが出来ます。

String[] strArray = { "abc", "def", "123", "456", "xyz" };
String separator = ",";

System.out.println(String.join(separator, strArray));
// → abc,def,123,456,xyz という文字列が表示される

なんと、ループもStringBuilderもなく一行で書けてしまいました。スッキリ。

(2) StringJoiner

2つ目の新APIは、StringJoinerというクラスです。
目的はString#join()とほぼ同じです。
というか、このクラスは、String#joinの中からも呼び出されていたりします

早速、同じように書き換えてみましょう。

String[] strArray = { "abc", "def", "123", "456", "xyz" };
String separator = ",";

StringJoiner sj = new StringJoiner(separator);
for (String str : strArray) {
    sj.add(str);
}

System.out.println(sj.toString());
// → abc,def,123,456,xyz という文字列が表示される

…ループもあるし、意外とスッキリしてませんね(笑)

使い方もStringBuilderと似ていますが、主な違いは以下の3点くらいですね。

  1. 区切り文字を自分で追加しなくなった
  2. 接頭辞と接尾辞を指定できる(CSV全体をカッコで囲むみたいなことができます)
  3. 要素を追加していない時の文字列を指定できる

れっつ、ベンチマーク

ところで、いつのバージョンでも「文字列結合の性能ネタ」はありますが、上記の新APIは、パフォーマンス的にはどうなんでしょうか?

ここでは、以前に @cero-t も紹介していた マイクロベンチマークツール「JMH」を使って、10000個の5バイト文字列("abcde")をカンマ区切りで連結する処理の実行時間を測定してみました。
(※正式リリース前のJava8で実施しているため、参考情報としてご覧ください)

パターンは以下の5つ。
(カッコ内は、マイクロベンチマーク用に記述したメソッド名になります)

  1. StringBufferを使って結合する (bufferJoin)
  2. StringBuilderを使って結合する (builderJoin)
  3. String#joinを使って結合する (joinJoin)
  4. StringJoinerを使って結合する (joinerJoin)
  5. 「+」で文字列を結合する(※いわゆるアンチパターン)(plusJoin)

※2014/03/18 ソースコードは、GitHubからどうぞ。
https://github.com/otomac/StringJoinBenchmark



実行条件:

java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b127)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b69, mixed mode)

JMH実行時のコマンドラインは「-wi 5 -i 10 -f 10」です。
つまり、以下のようになります。
  (A) ウォームアップ実行 5回
  (B) 計測のための実行 10回
  (C) 上記(A)+(B)の繰り返し 10回

計測のための実行は、各パターン100回ずつということになります。

さて、結果は以下のようになりました。

Result : 0.005 ±(99.9%) 0.001 ops/ms
  Statistics: (min, avg, max) = (0.003, 0.005, 0.005), stdev = 0.001
  Confidence interval (99.9%): [0.004, 0.006]


Benchmark                             Mode   Samples         Mean   Mean error    Units
s.j.b.StringJoinStudy.bufferJoin     thrpt       100        5.134        0.033   ops/ms
s.j.b.StringJoinStudy.builderJoin    thrpt       100        5.386        0.023   ops/ms
s.j.b.StringJoinStudy.joinJoin       thrpt       100        5.350        0.019   ops/ms
s.j.b.StringJoinStudy.joinerJoin     thrpt       100        5.357        0.044   ops/ms
s.j.b.StringJoinStudy.plusJoin       thrpt       100        0.005        0.000   ops/ms

この結果から、String#joinを使うパターン(joinJoin)とStringJoinerを使うパターン(joinerJoin)は、StringBuilderを使うパターン(builderJoin)とほぼ同等の速度が出せることがわかります。
StringBufferを使うパターン(bufferJoin)は、想定通り若干遅いくらいの結果になりました。
「+」を使うパターン(plusJoin)も、予想通り論外の性能でしたね(笑

このように、配列やリストのように、既に連結する文字列の要素が揃っている場合はString#joinやStringJoinerを使っても性能に遜色はないことがわかりました。
ぜひ使っていきたいところですね。

2. ファイル読み込み編

これまでのコード

これまでのテキストファイル読み込みは、おおよそ以下のような感じだと思います。
ただ読み込むだけだとつまらないので、XMLファイルの"<" と ">"を丸括弧 "(" と ")" に置換するサンプルを考えてみます。

※2014/03/18追記:うらがみ (id:backpaper0) さんからご指摘いただいて、Pathオブジェクトの生成コードを修正しました。コメントありがとうございます。

List<String> lines = new ArrayList<String>();

Path path = Paths.get("data.xml");
String line;
try (BufferedReader br = Files.newBufferedReader(path)) {
    while ((line = br.readLine()) != null) {
        String replaced = line.replaceAll("<", "(").replaceAll(">", ")");
        lines.add(replaced);
    }
} catch(IOException ex) {
    // 省略
}

whileの条件文に行読み込みの呼び出しがネストしていたりして、若干ややこしい感じがします。
かといって以下のように書くのも間延びする感じがしますね。

List<String> lines = new ArrayList<String>();

Path path = Paths.get("data.xml");
try (BufferedReader br = Files.newBufferedReader(path)) {
    while (true) {
        String line = br.readLine();
        if (line == null) {
            break;
        }
        String replaced = line.replaceAll("<", "(").replaceAll(">", ")");
        lines.add(replaced);
    }
} catch(IOException ex) {
    // 省略
}

さて、Java8ではそんなテキストファイル読み込みも便利にしてくれるAPIが追加されています。
ここでも、2種類見てみましょう。

(1) BufferedReader#lines()

InputStreamやReaderがあらかじめある場合は、こちらの方を使うことになるでしょう。
先ほどのコードは以下のようになります。
(書き換えた結果、結局Pathを作ってBufferedReaderを作っていますが、そのくらいなら良いのかなと)

List<String> lines = new ArrayList<String>();

Path path = Paths.get("data.xml");
try (BufferedReader br = Files.newBufferedReader(path, Charset.forName("UTF-8"))) {
    br.lines()
       .forEach(l -> { strList.add(l.replaceAll("<", "(").replaceAll(">", ")")); });
} catch(IOException ex) {
    // 省略
}

先ほどのコードに比べて、whileループが無いのでスッキリ。

ちなみに、上の例に書いたように、Filesクラスの多くのメソッドでは、Charsetで文字コードを指定することができます。
これも、今まではFileReaderでは文字コードを指定できず、InputStreamReaderを介して指定しなければならなかったのですが、Filesクラスで指定できるようになって、非常に便利になったところですね。
(※追記: UTF-8のような標準的な文字コードは、StandardCharsets.UTF_8でも可です)


読み込んだデータの加工をすることを考えると、ラムダ式やStream APIに慣れておかないといけませんが、単にリストに格納するだけなら以下のようにするのが簡単です(※これはJava7からある書き方です)。

※2014/03/13追記: id:nowokay さんから指摘をいただき、ファイル読み込みを Files#readAllLines() に変更しました。コメントありがとうございます。

Path path = Paths.get("data.xml");
List<String> allLines = Files.readAllLines(path, Charset.forName("UTF-8"));

ただし、メモリを大量に消費する危険性がありますので、大きいファイルを読み込む処理で使ってはいけません。

(2) Files#lines()

ファイルのパスが分かっているだけの場合や、Files#find()を使う場合などは、こちらの方を使うことになるでしょう。

先ほどのコードは以下のようになります。

 List<String> lines = new ArrayList<String>();
 
  Path path = Paths.get("data.xml");
 try (Stream<String> stream = Files.lines(path, Charset.forName("UTF-8"))) {
     stream.forEach(l -> { strList.add(l.replaceAll("<", "(").replaceAll(">", ")")); });
 } catch(IOException ex) {
     // 省略
 }

わざわざファイルからInputStreamやReaderを作らなくてよいので、非常にスッキリしてますね。

…なんとなく予想付いちゃってる方もいらっしゃるかと思いますが、こちらも、内部でFiles.newBufferedReader()を使っているので、ほとんど同じです。



f:id:acro-engineer:20140311021635j:plain:small

ここまで、前半として、文字列操作とファイルからのテキスト読み込みについての追加APIを紹介しました。
なんで、今までこんなメソッドが無かったのか?というくらい普通に使いたくなるものじゃないでしょうか?

ある意味、経験を積んだJavaコーダーさんなら、イディオムとして手が勝手に動くようなコードもあるかと思います。
でも、これからは自分の手じゃなくてコンパイラに仕事をさせて、短くなったコードでもうちょっと違うアイデアを考えていきたいものですね。

次回(後編)は、Map操作とConcurrent系のちょっとしたAPIの追加について、です。

では。


Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

Apache 初回リリースのStorm0.9.1のリリース内容は?

こんにちは。kimukimuです。

徐々に暖かくなってきていますね。春は目前です。

さて、つい先日Apache Stormとして初リリースとなる「0.9.1-incubating」がリリースされました!
#ちなみに前回リリースは「0.9.0.1」です。

今回リリース内容は大きく分けて、Apache Incubatorに移行したため発生したものと、
機能追加/不具合対応によるものの2つがあります。

節目のリリースですので両方についてリリースノートより主要な項目を紹介しますね。

1. Apache Incubatorとしてのリリース内容

ライセンスの変更

ライセンスが「Eclipse Public License - v 1.0」から「Apache License Version 2.0」に変更になってます。
今回の変更で今まで使っていた方が使えなくなる・・・ということはないのですが、
きちんとライセンスは確認した上で使うようにしましょう。

ビルドツールの変更

ビルドツールがLeiningen > Mavenに変更になりました。
これも使う上で何かが変わるというわけではありませんが、
Mavenになったことによって、JavaをやっているエンジニアがStormのソースを修正してビルドを行う・・・
ということがやりやすくなったとは思います。
ただ、Stormのコア部分がClojureで記述されていることには変わりありませんので、あしからず。

Mavenリポジトリ上のGroupIdの修正

今回のリリースによって、GroupIdが「storm」 > 「org.apache.storm」に変更になっています。
バージョンアップを行う時には気をつけましょう。

2. 機能追加/不具合対応によるリリース内容

通信モジュールのデフォルトがZeroMQからNettyに変更

今回のバージョンから通信モジュールのデフォルトがZeroMQからNettyに変更されました。
Making Storm fly with Netty | Yahoo Engineeringを見るに、パフォーマンス自体もNettyの方が高いようです。
加えて、依存性も少なくなるため、デフォルトになったのは納得がいく結果ではありますね。

Storm-UIの各項目にツールチップで解説を表示

Storm-UIで表示される各種項目に対してマウスオーバーした際にツールチップで解説が表示されるようになりました。
Storm-UIの動きはこれまでは実際にしばらく使ってみないといまいちわからないことも多かったため、
これは有難い機能追加ですね。

NimbusにTopologyをSubmitする際、設定に対するバリデーションが追記

NimbusにTopologyをSubmitする際に設定値に対する定型的なバリデーションが行われるようになりました。
TopologyにSubmitする際にはじかれない場合、クラスタ上でTopologyが走り出してからWorkerプロセスが
エラーで落ちて、復活してを繰り返す・・・ということが発生するため、意図しない動作を防止してくれますね。

「storm jar」コマンドによるTopology起動がWindows上で動作しない問題に対応

Stormは0.9.0の時点でZeroMQが必須では無くなったことによってWindows上でも動作するようになっていました。
ですが、一部のコマンドが動作しない個所があったため、問題が対応され、Windows上でもStormのフル機能が使用できるようになりました。
主流では無いとは思いますが、Windows上でもそれなりに使われているようですね。

3.今回のリリースのまとめ

今回のリリースはApacheに移行したことによるメンテナンスと、後は使い勝手に関わる箇所のリリースで、
何か大きな新機能が追加されたということはありませんでした。

ですが、今回のリリースでApacheへの移行が正式に完了したということにはなります。
以後はApacheとしてのリリースが続いていくはずですので、この先に期待、ですね。
それでは。
f:id:acro-engineer:20140305072059j:plain

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

Elasticsearchソースコードリーディング~内部構造把握の第一歩~

こんにちは! ツカノ(@)です。

ElasticsearchKibanaを使うとログなどを簡単に可視化できるため、利用者が急速に増えてきています(私もそのひとりです)。様々なブログで紹介されているKibana画面はとても素敵で、積極的に使いたくなります。
ただ、それなりの規模でElasticsearchを利用するには、中身を知ったり、データ設計や運用面なども考える必要がありますが、そのあたりの情報はまだ十分ではないように思います。そこで、Elasticsearchの中身をもっと知るために、ひとりでひっそりソースコードリーディングをしてみました。
f:id:acro-engineer:20140131080117p:plain

今回利用したElasticsearchのバージョンは1.0.0.RC2です。以下の場所から実行媒体とソースコードをダウンロードして確認しています。また、確認はWindowsで行っています。

1.ElasticsearchはどんなJVM引数で起動するのか?

まずは、実行媒体(zip)を展開します。ひとまずデフォルト設定のままで、elasticsearch.batを実行して起動します。

以下のようなログがコンソールに表示されて、起動完了です。

[2014-02-07 06:35:10,225][INFO ][node                     ] [Blind Faith] version[1.0.0.RC2], pid[9052], build[a9d736e/2014-02-03T15:02:11Z]
[2014-02-07 06:35:10,225][INFO ][node                     ] [Blind Faith] initializing ...
[2014-02-07 06:35:10,229][INFO ][plugins                  ] [Blind Faith] loaded [], sites []
[2014-02-07 06:35:13,525][INFO ][node                     ] [Blind Faith] initialized
[2014-02-07 06:35:13,526][INFO ][node                     ] [Blind Faith] starting ...
[2014-02-07 06:35:13,743][INFO ][transport                ] [Blind Faith] bound_address {inet[/0:0:0:0:0:0:0:0:9300]}, publish_address {inet[/172.20.10.4:9300]}
[2014-02-07 06:35:16,971][INFO ][cluster.service          ] [Blind Faith] new_master [Blind Faith][NYDlh_0TRJeafDu2KZxB1A][Poincare][inet[/172.20.10.4:9300]], reason: zen-disco-join (elected_as_master)
[2014-02-07 06:35:17,007][INFO ][discovery                ] [Blind Faith] elasticsearch/NYDlh_0TRJeafDu2KZxB1A
[2014-02-07 06:35:17,039][INFO ][gateway                  ] [Blind Faith] recovered [0] indices into cluster_state
[2014-02-07 06:35:17,140][INFO ][http                     ] [Blind Faith] bound_address {inet[/0:0:0:0:0:0:0:0:9200]}, publish_address {inet[/172.20.10.4:9200]}
[2014-02-07 06:35:17,141][INFO ][node                     ] [Blind Faith] started


さて、VisualVMを起動して、Elasticsearchに接続してみましょう。以下の図の赤枠で囲った部分にElasticsearchが見えていますね。
f:id:acro-engineer:20140207084727p:plain


「概要」タブをクリックして、JVM引数を確認してみると、以下のようになっています。
(es.path.homeは実行媒体を展開したディレクトリによって異なります)

-Xms256m
-Xmx1g
-Xss256k
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
-XX:+HeapDumpOnOutOfMemoryError
-Delasticsearch
-Des-foreground=yes
-Des.path.home=C:\elasticsearch-1.0.0.RC2

これら設定値はelasticsearch.batの中に記載されているため、JVM引数を変更する場合はこのファイルを修正してください。Linux版の場合はelasticsearchelasticsearch.in.shにまたがってJVM引数の設定が記載されています。

2.Elasticsearchのスレッド構成は?

引き続き、VisualVMを操作します。「スレッド」タブから「スレッドダンプ」ボタンを押して、スレッドダンプを取得してみましょう。ちょっと長いですが、取得したスレッド一覧は以下の通りになりました。(見やすいように並び替えています)

Attach Listener
C2 CompilerThread0
C2 CompilerThread1
Concurrent Mark-Sweep GC Thread
DestroyJavaVM
elasticsearch[Blind Faith][[timer]]
elasticsearch[Blind Faith][[ttl_expire]]
elasticsearch[Blind Faith][clusterService#updateTask][T#1]
elasticsearch[Blind Faith][discovery#multicast#receiver][T#1]
elasticsearch[Blind Faith][generic][T#1]
elasticsearch[Blind Faith][http_server_boss][T#1]{New I/O server boss #51}
elasticsearch[Blind Faith][http_server_worker][T#1]{New I/O worker #35}
elasticsearch[Blind Faith][http_server_worker][T#2]{New I/O worker #36}
elasticsearch[Blind Faith][http_server_worker][T#3]{New I/O worker #37}
elasticsearch[Blind Faith][http_server_worker][T#4]{New I/O worker #38}
elasticsearch[Blind Faith][http_server_worker][T#5]{New I/O worker #39}
elasticsearch[Blind Faith][http_server_worker][T#6]{New I/O worker #40}
elasticsearch[Blind Faith][http_server_worker][T#7]{New I/O worker #41}
elasticsearch[Blind Faith][http_server_worker][T#8]{New I/O worker #42}
elasticsearch[Blind Faith][http_server_worker][T#9]{New I/O worker #43}
elasticsearch[Blind Faith][http_server_worker][T#10]{New I/O worker #44}
elasticsearch[Blind Faith][http_server_worker][T#11]{New I/O worker #45}
elasticsearch[Blind Faith][http_server_worker][T#12]{New I/O worker #46}
elasticsearch[Blind Faith][http_server_worker][T#13]{New I/O worker #47}
elasticsearch[Blind Faith][http_server_worker][T#14]{New I/O worker #48}
elasticsearch[Blind Faith][http_server_worker][T#15]{New I/O worker #49}
elasticsearch[Blind Faith][http_server_worker][T#16]{New I/O worker #50}
elasticsearch[Blind Faith][management][T#1]
elasticsearch[Blind Faith][management][T#2]
elasticsearch[Blind Faith][riverClusterService#updateTask][T#1]
elasticsearch[Blind Faith][scheduler][T#1]
elasticsearch[Blind Faith][transport_client_boss][T#1]{New I/O boss #17}
elasticsearch[Blind Faith][transport_client_timer][T#1]{Hashed wheel timer #1}
elasticsearch[Blind Faith][transport_client_worker][T#1]{New I/O worker #1}
elasticsearch[Blind Faith][transport_client_worker][T#2]{New I/O worker #2}
elasticsearch[Blind Faith][transport_client_worker][T#3]{New I/O worker #3}
elasticsearch[Blind Faith][transport_client_worker][T#4]{New I/O worker #4}
elasticsearch[Blind Faith][transport_client_worker][T#5]{New I/O worker #5}
elasticsearch[Blind Faith][transport_client_worker][T#6]{New I/O worker #6}
elasticsearch[Blind Faith][transport_client_worker][T#7]{New I/O worker #7}
elasticsearch[Blind Faith][transport_client_worker][T#8]{New I/O worker #8}
elasticsearch[Blind Faith][transport_client_worker][T#9]{New I/O worker #9}
elasticsearch[Blind Faith][transport_client_worker][T#10]{New I/O worker #10}
elasticsearch[Blind Faith][transport_client_worker][T#11]{New I/O worker #11}
elasticsearch[Blind Faith][transport_client_worker][T#12]{New I/O worker #12}
elasticsearch[Blind Faith][transport_client_worker][T#13]{New I/O worker #13}
elasticsearch[Blind Faith][transport_client_worker][T#14]{New I/O worker #14}
elasticsearch[Blind Faith][transport_client_worker][T#15]{New I/O worker #15}
elasticsearch[Blind Faith][transport_client_worker][T#16]{New I/O worker #16}
elasticsearch[Blind Faith][transport_server_boss][T#1]{New I/O server boss #34}
elasticsearch[Blind Faith][transport_server_worker][T#1]{New I/O worker #18}
elasticsearch[Blind Faith][transport_server_worker][T#2]{New I/O worker #19}
elasticsearch[Blind Faith][transport_server_worker][T#3]{New I/O worker #20}
elasticsearch[Blind Faith][transport_server_worker][T#4]{New I/O worker #21}
elasticsearch[Blind Faith][transport_server_worker][T#5]{New I/O worker #22}
elasticsearch[Blind Faith][transport_server_worker][T#6]{New I/O worker #23}
elasticsearch[Blind Faith][transport_server_worker][T#7]{New I/O worker #24}
elasticsearch[Blind Faith][transport_server_worker][T#8]{New I/O worker #25}
elasticsearch[Blind Faith][transport_server_worker][T#9]{New I/O worker #26}
elasticsearch[Blind Faith][transport_server_worker][T#10]{New I/O worker #27}
elasticsearch[Blind Faith][transport_server_worker][T#11]{New I/O worker #28}
elasticsearch[Blind Faith][transport_server_worker][T#12]{New I/O worker #29}
elasticsearch[Blind Faith][transport_server_worker][T#13]{New I/O worker #30}
elasticsearch[Blind Faith][transport_server_worker][T#14]{New I/O worker #31}
elasticsearch[Blind Faith][transport_server_worker][T#15]{New I/O worker #32}
elasticsearch[Blind Faith][transport_server_worker][T#16]{New I/O worker #33}
elasticsearch[keepAlive/1.0.0.RC2]
Finalizer
Gang worker#0 (Parallel CMS Threads)
Gang worker#1 (Parallel CMS Threads)
Gang worker#0 (Parallel GC Threads)
Gang worker#1 (Parallel GC Threads)
Gang worker#2 (Parallel GC Threads)
Gang worker#3 (Parallel GC Threads)
Gang worker#4 (Parallel GC Threads)
Gang worker#5 (Parallel GC Threads)
Gang worker#6 (Parallel GC Threads)
Gang worker#7 (Parallel GC Threads)
JMX server connection timeout 80
Reference Handler
RMI Scheduler(0)
RMI TCP Accept-0
RMI TCP Connection(12)-172.20.10.4
Service Thread
Signal Dispatcher
Surrogate Locker Thread (Concurrent GC)
VM Periodic Task Thread
VM Thread

スレッド名が「elasticsearch」で始まるスレッドは62個あり、これがElasticsearchのアプリケーションに関連するスレッドになっています。これは、分かりやすいですね。
この一覧を眺めてみると、「http_server」「transport_client」「transport_server」という名称を含むスレッドが多いのが目立ちます。これは何でしょうか? Elasticsearchは通信周りのライブラリに、以前このブログでも紹介したNetty(ver.3)を利用しています。これらはNetty関連の通信スレッドになります。

「http_server」を含むスレッド

Elasticsearchに対するオペレーションは主にhttpで行います。Elasticsearchにアクセスするのにcurlを使った例をよく見ますが、その処理を行う箇所です。http通信周りのスレッドになります。

「transport_client」を含むスレッド

Elasticsearchがクラスタ間通信を行う際のクライアント側スレッドです。サーバ側と違い、こちらにはtimerスレッドがあります。

「transport_server」を含むスレッド

Elasticsearchがクラスタ間通信を行う際のサーバ側スレッドです。

3.Elasticsearchの入口

何か問題があったときには、ソースを読んだり、リモートデバッグすることもあると思います。そのための、入口になる箇所を探してみましよう。他のプロセスと通信処理を行っている箇所が分かれば、そこが入口になります。
Elasticsearchは通信処理にNettyを利用しています。Nettyの初期化は、org.jboss.netty.channel.ChannelPipelineFactoryを継承したクラスのgetPipelineメソッドで行います。このメソッドを実装している箇所を探してみましょう。
すると、以下のクラスが見つかりました。通信周りの設定を知りたい場合は、これらのソースコードを読むのが良いと思います。

org.elasticsearch.benchmark.transport.netty.NettyEchoBenchmark

これはElasticsearchのテストコードに入っているベンチマーク用クラスです。Elasticsearch本体とは関係ないですね。

org.elasticsearch.bulk.udp.BulkUdpService

bulk udp apiで利用される通信処理を初期化しているクラスです。この機能はデフォルトではdisabledとなっているため、先ほどのスレッド一覧にも登場していません。
リモートデバッグしたい場合は、BulkUdpServiceクラスの内部クラスHandlerのmessageReceivedメソッドにブレークポイントを設定してください。

org.elasticsearch.http.netty.NettyHttpServerTransport

Elasticsearchのhttp通信を初期化しているクラスです。内部クラスMyChannelPipelineFactoryで初期化しています。
リモートデバッグしたい場合は、org.elasticsearch.http.netty.HttpRequestHandlerのmessageReceivedメソッドにブレークポイントを設定してください。

org.elasticsearch.transport.netty.NettyTransport

Elasticsearchのクラスタ間通信を初期化しているクラスです。doStartメソッドの中でクライアント側、サーバ側の順に初期化しています。
リモートデバッグしたい場合は、org.elasticsearch.transport.netty.MessageChannelHandlerのmessageReceivedメソッドにブレークポイントを設定してください。クライアント側、サーバ側共に同じクラスを利用しますが、スレッド名が違うので区別できます。

4.Elasticsearchにリモートデバッグする方法

Windows版だとelasticsearch.batLinux版だとelasticsearch.in.shに、JVM引数を指定する変数JAVA_OPTSがあるので、ここにリモートデバッグに必要なオプションを追加しましょう。
例えばWindows版は、デフォルトで以下の設定になっています。

set JAVA_OPTS=%JAVA_OPTS% -XX:+HeapDumpOnOutOfMemoryError

次のようにデバッグオプションを追加しましょう。

set JAVA_OPTS=%JAVA_OPTS% -XX:+HeapDumpOnOutOfMemoryError -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8765

その後、以下の手順を実行します。

  • 「3.Elasticsearchの入口」に記載したブレークポイントを設定します。
  • Elasticsearchを起動します。
  • リモートデバッグで8765番ポートに接続します。

これで準備ができました。
例えば、curlでhttpリクエストを送信すると、HttpRequestHandlerのmessageReceivedメソッドに設定したブレークポイントで停止します。
 

さて、いかがだったでしょうか?
これをベースに、Elasticsearchのアクションやプラグインあたりの処理を追うと面白そうですね。
今回はElasticsearchの入口部分だけですが、理解やデバッグの参考になればと思います。

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

Kibanaの画面をPDF出力しよう!

こんにちは! ツカノ(@)です。

最近、STAP細胞のニュースで賑わっていますね。iPS細胞と比較する記事が多いですが、たまにはES細胞のことも思い出してあげてください(ES細胞だってノーベル賞を取っているんですよ~)。まぁ、IT業界的にESと言えば、Elasticsearchのことを指す訳ですが、こちらはトレンドなプロダクトで、Marvelが登場したりと、まだまだ広がっていく感じがします。
f:id:acro-engineer:20140131080117p:plain

Elasticsearch+Kibanaは本当に便利で、様々な方が取り組まれており、情報量も急速に増えています。ログをElasticsearchに簡単に入れておくことができ、Kibanaを使って簡単に可視化できるのは良いですよね。
f:id:acro-engineer:20140131085246p:plain

さて、可視化したら、それを後から見ることができるようにファイル化したくなるのが人の心。Kibanaで表示した画面もファイルに落としたいしたいですよね。特に「PDFでレポート出力して報告」なんてケースもあるかと思います。

そこで、今回はKibanaのissue#509を参考に、Kibanaの画面をPDFに出力する方法を紹介します。

実行時の流れは、以下のようになります。

  • KibanaのURLを指定して、PNG形式に出力する。
  • PNG形式をPDF形式に変換する。

では、インストールから順に説明します。以下の内容は、Linux系OSで利用できます。cygwin等を利用することで、Windows系でも利用できるかもしれませんが、未確認です。

1.PhantomJSをインストール

WebKitを使ってスクリーンショット等ができるライブラリPhantomJSをインストールします。
これでスクリーンショットPNG形式で出力することができます。
f:id:acro-engineer:20140131080307p:plain

以下のページからダウンロードしてください。
 Download | PhantomJS

ここでは、phantomjs-1.9.7-linux-x86_64.tar.bz2をダウンロードして使います。

tar jxvf phantomjs-1.9.7-linux-x86_64.tar.bz2
sudo cp -p phantomjs-1.9.7-linux-x86_64/bin/phantomjs /usr/bin

また、以下のページに記載されているrasterize.jsを、PDF化するためのコマンドを実行するディレクトリに置きます。(Webから貼り付け、というのはイケてないですが)
 Utilize phantomjs to render screenshots (schedule email of dashboards) · Issue #509 · elasticsearch/kibana · GitHub
ただし、環境などによっては、rasterize.js内の変数waitTimeでページをオープンしてからファイル出力するまでの待ち時間(デフォルトは10,000ミリ秒)を調整した方が良いかもしれません。

2.sam2pをインストール

ラスターイメージをPDF形式に変換するためのライブラリsam2pをインストールします。
これで、PNG形式のファイルをPDF形式に変換することができます。

以下のページからダウンロードしてください。
 Downloads - sam2p - convert raster (bitmap) images to PostScript, PDF and other formats - Google Project Hosting

ここでは、以下の2つのファイルをダウンロードして使います。

  • sam2p-0.49-linux-static.tar.gz
  • tif22pnm-0.14.tar.gz
tar xvfz sam2p-0.49-linux-static.tar.gz
cd sam2p-0.49-linux-static
sudo cp -p sam2p /usr/local/bin
tar xvfz tif22pnm-0.14.tar.gz
cd tif22pnm-0.14
./configure
./do.sh compile
sudo cp -p png22pnm /usr/local/bin

3.Kibanaの背景設定

Kibanaのスタイルはデフォルトでdark(黒背景)のため、そのままPDFに出力するとあまりキレイではありません。Kibanaの設定画面からスタイルをlight(白背景)に設定した方が見やすいです。

Kibanaの画面の右上から設定画面を表示する。
f:id:acro-engineer:20140131084641p:plain

スタイルを「light」に変更する。
f:id:acro-engineer:20140131084657p:plain

4.PDF化の実行

以下のコマンドを実行することで、Kibanaの画面をPDF化することができます。直接PDF出力でなく、PNGファイルに出力してそこからPDFに出力しています。

phantomjs rasterize.js <PDF化するKibanaのURLを指定> sample.png "A4"
sam2p sample.png <PDFファイル名を指定>

これで、PDF出力できました。

OSについているスクリーンキャプチャ機能と違って、スクロールが必要な箇所もちゃんと出力されるのは良いですね。
Elasticsearch+Kibanaの組み合わせは可視化するには良いですが、レポート出力がまだ弱い感じがします。しっかりしたレポート機能が出て欲しいですが、現状は、このような工夫が必要ですね。
 

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

Storm上で動作するオンライン機械学習ライブラリをOSSとして公開しました!

id:KenichiroMurata (@muraken720)です。

昨日、AcroquestはStorm上で動作するオンライン機械学習ライブラリをOSSとして公開しました!
ここでも簡単に紹介させて頂きます。

AcroMUSASHI Stream-ML(Machine Learning Library)

「AcroMUSASHI Stream-ML」はStorm上で動作し、連続的に発生し続けるストリームデータに対して、動的に学習データを更新しながら、リアルタイムの分析をすることができるライブラリです。

https://github.com/acromusashi/acromusashi-stream-ml

Storm をベースとした、ストリームデータの分散処理プラットフォームである「AcroMUSASHI Stream」と組み合わせることで、「データの収集~分析~結果の出力」までをシームレスに結合することができ、機械学習を行うためのシステム開発を迅速に行うことができます。

現在は以下のアルゴリズムが利用できます。

今後もニーズに合わせて、順次対応を広げていく予定です。
ぜひ、興味を持たれた方はご覧になってください。

参考


f:id:acro-engineer:20131211084154j:plain:w200

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

日経ソフトウエアのJava8連載の第3回は「新しい日付API」です!

みなさん、こんにちは!
インフルエンザやノロウィルスが猛威を振るっていますが、みなさん、いかがお過ごしでしょうか。
周りで感染者が増える中、風邪ひとつ引かない、無駄に丈夫なオカダです。
無事是名馬、いい言葉ですね。

■先取り! Java SE 8

Java8の新機能についてAcroquest社員が紹介する短期集中連載
「先取り! Java SE 8」
の第三回が掲載された、「日経ソフトウエア2014年3月号」が出版されました。

http://itpro.nikkeibp.co.jp/NSW
http://itpro.nikkeibp.co.jp/NSW

■第三回は「新しい日時API

日経ソフトウエア2014年1月号」からスタートした本連載。
1月号は「ラムダ式」2月号は「ストリームAPI」について紹介してきました。

今月は、Java8になって大きく変更が入った「日時APIについて紹介します。
題して、「これまでがいかに面倒だったか・・・「日時API」の改良が喜ばしい」です。

これまでのJavaの日時APIは、処理に制約があったり、直感的でなかったりと、色々と「残念なところ」がありました。
Java8では日時APIが完全に作り直されており、既存の問題を解消した非常に利用しやすいAPIになっています。
既存のコードと対比する形で、新しいAPIを利用した場合の利点を紹介していますので、ぜひ、ご一読下さい!

なお、Acroquestのサイトから最初の1ページ分のPDFを閲覧できますので、こちらも参考にしてくださいね。
http://www.acroquest.co.jp/company/press/2014/0124p1.html

■「先取り! Java SE 8」は今回が最終回

3回に渡って連載してきた「先取り! Java SE 8」は、今回が最終回です。
Java8の正式リリースは3月に予定されており、まもなく手元で動かせるようになるでしょう。
一歩進んだJavaプログラミングを身につけるために、今回の連載が助けになれば幸いです。

それでは!

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

Couchbase Tokyo 2014と、Couchbase情報のまとめ

こんちには! ツカノ(@)です。

なんだかんだで1月末。寒い日があるのは良いとしても、忙しい日も多くなってきました。一緒にいろいろな事に取り組む人がもっと多くなって欲しい、との感じる今日この頃です。そんな訳で、当社では人材募集中です!
 →Javaエンジニア緊急募集/キャリア採用


さて、そんな感じの宣伝から入りましたが、本題です。
ここ数年、NoSQLプロダクトは急速に増えましたね。しかも、KVS、ドキュメント指向、グラフ指向など、プロダクトの特徴も様々です。例えばこういう比較ページを見ると、いろんな特徴のNoSQLがあることが分かります。

これらNoSQLプロダクトの中でも、Couchbaseドキュメント指向型(JSON)KVS型(memcached互換)の両方に対応したNoSQLで、インメモリで高速動作するのがウリです(ディスクに永続化できますが、基本はインメモリ)。また、システムを止めないことを重要視しており、障害が発生しても自動でフェイルオーバーしたり、コンパクション時に他のオペレーションが停止しないそうです。

f:id:acro-engineer:20140124151034p:plain

公式ページをチェックしてみると、以下のような特徴が記述されています。

  • 容易なスケーラビリティー
  • 安定したハイパフォーマンス
  • 365日稼動
  • 柔軟なデータモデル

そんなCouchbase入門者の私ですが、Couchbaseを勉強すべくCouchbase Tokyo 2014というイベントに参加してきました。
 →このイベントのEventifierはこちらです。

Couchbase Tokyoは毎年開催されているイベントで、今年で3回目。Couchbase社の方によるCouchbaseの解説と、ユーザによる事例紹介が行われます。朝から夕方まで丸一日のイベントで、最初は製品の概要説明から入り、段々と濃いセッションになっていき、Couchbaseについてよく勉強することができました。ちゃんちゃん♪・・・では面白くないので、中でも気になった「Couchbase Console」「Couchbase Lite」を紹介します。

Couchbase Console

「Couchbase Console」(管理用Webコンソール)は、Couchbase社のMatt Ingenthronさんのセッションで紹介されていた機能で、ノードの設定ができるのはもちろん、秒間のオペレーション数やメモリ・ディスクの利用状況をリアルタイムでグラフ表示できたり、ノード毎のコンパクションの状況を進捗バーで表示することができます。クラスタ化されたシステムを管理する側からすると、素晴らしい機能ですね。こういうところがちゃんとしているNoSQLプロダクトって、なかなか無いと思います。
グラフ表示している画面は、こういう感じです。デザインも良いですね。
f:id:acro-engineer:20140124114108p:plain

Couchbase Lite

要するに、モバイル向けの組み込みCouchbaseです。今のところ、iPhone/Androidに対応しています。Couchbase社のJessica Liuさんのセッションで紹介されていました。
Couchbase Liteを使うと、クラウド上のCouchbaseサーバとデータ同期したり、特定のクエリ結果が更新された際に通知を受信したり(Live Query)Facebook認証するAPIが用意されていたり、モバイル向け機能がいろいろと用意されているようです。また、PhoneGapプラグインも用意されています。
「モバイル向けの機能がいろいろ揃ったNoSQL」といったところでしょうか。多くの人がモバイル端末を持つ時代になってはいますが、OSSのNoSQLプロダクトでモバイル向けの機能があるのはCouchbaseだけ、との事でした。


このイベントで、実際に開発しているCouchbase社の方々に質問できたのは良かったです。また、Couchbase社の方々と話してみると、陽気な方が多く、好印象でした。Matt Ingenthronさんとか、変な質問でも、ちゃんと回答してくれましたし、懇親会も非常に盛り上がっていました。翌日仕事があったため私は二次会までしか参加しませんでしたが、その後、何時まで飲んでたんだろう。。。

Couchbase情報まとめ

Couchbaseの情報が載っているサイトや本について、まとめました。他にもオススメがあれば、ぜひお知らせください。

英語、日本語、韓国語、中国語で情報公開されてます。

couchbase-jp、日本のCouchbaseコミュニティです。meet upなどのイベントも開催されています。

couchbase-jpの方々が作成してくださった日本語版のマニュアルです。バージョンは2.0ですので、利用の際はご注意ください。

Getting Started With Couchbase Server

Getting Started With Couchbase Server

90ページとコンパクトな本で、まずは始めてみましょう、という入門的な内容です。

f:id:acro-engineer:20140124093141g:plain
「Getting Started With Couchbase Server」の日本語訳です。Ebookのみ販売されています。

Developing With Couchbase Server

Developing With Couchbase Server

こちらも88ページとコンパクトな本ですね。Couchbaseは公式のドキュメントが充実してるし、「何百ページもの本を読まないと使えないプロダクトじゃない」と言っている方もいましたし、コンパクトな本が多いですね。

この2つのサイトはCouchbaseに関する記事が豊富です。参考にさせていただきます。

  • 小冊子
    • Couchbase LiteによるiOSアプリケーション開発
    • FluentdとNoSQLデータベースCouchbase Serverで始めるログ解析~それでもやっぱり、SQLが好き~

コミケやCouchbase関係のイベント会場で、couchbase-jpにより販売されているようです。
↓こういう本です。


さて、いかがだったでしょうか?
Couchbaseの良い面ばかり書いた気がするので、「それなりにメモリを使う」「Enterprise Editionが最新版で、Community Editionは1つ前の版」という面があることも書いておきます。それでも、魅力的なプロダクトに見えますが。
Couchbaseに興味を持たれた方は、ぜひ触ってみてはいかがでしょう。

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ