Java: 2008年4月アーカイブ

概要

大量にオブジェクトを生成しなければならないケースにおいて、オブジェクト生成方法による性能差について調査した。
特に、Java のリフレクションは遅いと聞くが、どのくらい性能がでるのかが気になっていた。

調査に使った Java のバージョン: Sun JDK 1.6.0_05

結論

  • new Foo() の形で生成する方法は、リフレクションを使った他の方法より圧倒的に高速に動作する。
  • リフレクションを使うケースの中では、static な newInstance() をリフレクションで呼ぶ方法が最も高速に動作した。

調査内容

次の3つの生成方法で実行時間を計測した。
  • test-1 - new Foo()
  • test-2 - Class.newInstance()
  • test-3 - Constructor.newInstance()
  • test-4 - Foo の static メソッド newInstance() をリフレクション経由で実行
また test-2 以外のテストケースでは、コンストラクタの引数が無しのケースと int を引数とするケースを調査した。

test-1: new Foo() で生成 (引数なし)
test-1-2: new Foo(int)
test-2: Class.newInstance() で生成
test-3: Constructor.newInstance() で生成
test-3-2: Constructor.newInstance(int) で生成
test-4: Foo.newInstance() をリフレクションで実行
test-4-2: Foo.newInstance(int)

実行結果

テストケース 引数なし [msec] 引数あり [msec]
test-1 125 172
test-2 3344
test-3 3281 3891
test-4 1984 2625

結論

java.text.SimpleDateFormat の使用にはいくつかの注意が必要である。
  • SimpleDateFormat はスレッド・セーフではない。複数のスレッドで同時に使用してはならない。
  • SimpleDateFormat はシリアライズ可能であるが、シリアライズすべきではない。
  • 利用ケースによるが、おそらくほとんどのケースにおいて SimpleDateFormat を毎回生成せず、static で一度だけ生成し、同期を取りながら使用したほうが高速である。
調査に使った Java のバージョン: Sun JDK 1.6.0_05

SimpleDateFormat はシリアライズできてしまうが...

SimpleDateFormat の親クラスが java.io.Serializable を実装しているため、シリアライズできてしまう。
しかし、シリアライズしてみると、出力データサイズが 37 kB とかなり大きなサイズになってしまう。

テストプログラム これは、SimpleDateFormat の中で java.text.DateFormatSymbols インスタンスを保持している。このクラスは月、曜日、タイムゾーンデータなど、地域対応が可能な日付/時刻フォーマットデータを保持しているため、かなり大きなデータ量となる。

自分で明示的に SimpleDateFormat に格納しているならともかく、通常のケースでこれをシリアライズする必要はない。

オブジェクト生成コスト vs 同期コスト

次の2つのプログラムを考えてみる。どちらが高速に動作するだろうか?

code-1: 実行のたびに SimpleDateFormat オブジェクトを生成して利用するケース。

実行するたびに オブジェクト生成コストがかかっている。

code-2: static で一度だけ SimpleDateFormat オブジェクトを生成するケース

利用する際に synchronized で同期をとって利用する。
同期コストがかかっている。

性能測定結果

いずれのケースでも code-2 の方が高速に動作した。
なお、テストで利用したマシンは CPU が Core2duo であるため、2 スレッドで実行できる分、複数スレッドで実行した場合、 code-1 は高速化している。
スレッド数 code-1 code-2
プログラム 実行時間
[msec]
プログラム 実行時間
[msec]
1 Test1_1 5656 Test2_1 796
10 Test1_2 3359 Test2_2 937
100 Test1_3 3625 Test2_3 1204

static に生成して利用するのはガベージ・コレクションの観点からも優位である。
SimpleDateFormat オブジェクトを毎回生成するということは、生存時間の短いオブジェクトをより多く発生することになり、GC 頻度を高めることになる。

サンプルコード

test-SimpleDateFormat.zip

javaでping送信

| | コメント(0) | トラックバック(0)

概要

web サイトを更新した時に、Google などの検索サイトに ping 送信を行うことにより、より早く検索結果に反映してもらえる。
Google だと 5~10分くらい?結構早い。

MovableType や MTOS などの CMS を利用していれば、記事掲載時に自動的に ping を送信してくれるが、CMS を使わずに作成したサイトの場合、自分で ping 送信を行う必要がある。

SEO対策を考えるなら、是非自分たちが作成したサイトも ping で更新通知を行いたい。
そこで、Java から ping 送信するプログラムについて調査した。

仕組みの概要

XML-RPC§更新pingの送信 by isnot.jp が非常に分かりやすい。

どうやら、単に ping 送信を送れば OK という訳ではないらしい。
ping 送信は次の手順で行うことになる。

1. 更新データを含む rss ファイルを作成し、web サイト上に置く

rss ファイルの書き方は、いろんな web サイトの rss を参考にする。
そして、html で次のように記述する。

2. ping を各検索サイトなどに送信する

すると、各サイトのクローラーが巡回してくれ、 rss ファイルから更新データを入手する。
ping 送信から巡回までの時間は、ping 送信先サイトによって異なる。
blog360 や はてな は結構早い。

概要

Eclipse 3.3.2 を新たにインストールし、Software Update 機能を使って TPTP プラグインをインストールしたところ、プロファイリング機能が動作しなかった。

原因は、ダウンロードしたプラグインの中に Agent Controller (acserver.exe) など一式が含まれていないこと。
例えば、次のディレクトリが存在しない。
  • C:\usr\eclipse\plugins\
      org.eclipse.tptp.platform.ac.win_ia32_4.4.1.v200802050100\
        agent_controller
そして、プロファイルを実行すると、次のようなエラーが表示される。
org.eclipse.core.runtime.CoreException
The process launcher seems to be inactive.  Restart the Agent Controller and try again.

org.eclipse.core.runtime.CoreException: The process launcher seems to be inactive.  Restart the Agent Controller and try again.
  at org.eclipse.tptp.trace.ui.internal.launcher.core.LauncherUtility.createCoreException(LauncherUtility.java:123)
  at org.eclipse.tptp.trace.ui.internal.launcher.core.LauncherUtility.createCoreException(LauncherUtility.java:131)
  at org.eclipse.tptp.platform.jvmti.client.internal.launcher.TIDelegateHelper.handleError(TIDelegateHelper.java:597)
  at org.eclipse.tptp.platform.jvmti.client.internal.launcher.TIDelegateHelper.launchProcess(TIDelegateHelper.java:509)
  at org.eclipse.tptp.platform.jvmti.client.internal.launcher.TIDelegateHelper.launch(TIDelegateHelper.java:313)
  at org.eclipse.tptp.platform.jvmti.client.internal.launcher.TIJavaLauncherDelegate.launch(TIJavaLauncherDelegate.java:37)
  at org.eclipse.tptp.trace.ui.internal.launcher.core.LauncherUtility.delegateInit(LauncherUtility.java:1163)
  at org.eclipse.tptp.trace.ui.provisional.launcher.PrimaryLaunchDelegate.run(PrimaryLaunchDelegate.java:196)
  at java.lang.Thread.run(Unknown Source)

次の手順で Java プロファイリング環境を構築できた。

ゼロから環境を構築する

次の手順で、ゼロから環境を構築できる。

Eclipse 本体をダウンロード、インストール

http://www.eclipse.org/downloads/ にアクセスし、「Eclipse IDE for Java EE Developers 」のところの Windows をクリックする。

そして 「Download from: ...」をクリックして eclipse-jee-europa-winter-win32.zip をダウンロードする。

この zip を展開し、eclipse フォルダを適当な場所に置く。
以降では c:\usr\eclipse に置いたと仮定して話を進める。

TPTPプラグインをダウンロード

Eclipse TPTP のページにアクセスし、右側の Download をクリックする。

そして、「TPTP Plugins for Eclipse」と書かれているところから、次のプラグインの zip ファイルをダウンロードする。

  • Platform
  • Monitoring Tools
  • Tracing and Profiling Tools
  • Testing Tools   ※これは無くても動作するかも
それぞれの zip ファイルの中身を C:\usr\eclipse に重ねて展開する。

これで TPTP が利用可能になる。

トラブルシューティング

eclipse フォルダの名前を変えると動作しない

C:\usr\eclipseC:\usr\eclipse-tptp のように名前を変えると、動作しなかった。
Preference に設定箇所があるのかもしれないが、見つけることができなかった。

日本語Eclipse Pleiades All in One で TPTPを使う

日本語Eclipse Pleiades All in One 日本語化や便利なプラグインが最初から含まれている便利なディストリビューション。

この eclipse で TPTP を使うには、次の手順を実行する。

Ultimate をインストール

上記 Web サイトにアクセスし、「Ultimate (JREなし)」をインストールする。

それを C:\usr\eclipse に展開する。

なお、4/3 にダウンロードした 3.3.2 版では TPTP は動作したが、以前にダウンロードした 3.3.1.1 版では動作しなかった。

TPTP プラグインをインストール

「ソフトウェア更新」機能を使ってインストールせず、さきほどと同じように Eclipse TPTP プロジェクトページから次のファイルをダウンロードし、インストールする。
  • tptp.monitoring.runtime-TPTP-4.4.1.zip
  • tptp.platform.runtime-TPTP-4.4.1.zip
  • tptp.trace.runtime-TPTP-4.4.1.zip

clean 実行

C:\usr\eclipse\ ディレクトリの中にある eclipse.exe -clean.cmd を実行する。

これで、TPTP が利用できるようになる。

TPTP でプログラム実行時間を計測するテスト

TPTP 実行環境を構築できたら、早速テストを行う。

テストプログラム作成

次のようなテストプログラム Test.java を作成する。

プロファイル実行

  1. [実行] メニュー → [プロファイル] → [Java アプリケーション] を実行する。
  2. ダイアログ上で 「実行時間分析」 を選択し、[OK] ボタンを押す。
  3. 実行完了後、左側のペイン上の「実行時間分析」をダブルクリックすると、実行時間が表示される。

2010年12月

      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31