Java

【性能】Javaの処理が遅いと感じたら確認すべきこと

2020年12月13日

はじめに

WebサービスやAndroidスマートフォンのアプリ開発で何かと使うJava言語。Java VMで動作する中間言語にコンパイルされるものの、なんか動作が遅いと感じることがあります。

 

Native(C言語やC++言語)に比べると、VM上で動作するので多少パフォーマンス理論値は劣りますが、

パフォーマンスの問題は、Java言語や実行環境にあるのではなく、プログラムの書き方にある。

 

こんな方におすすめ

  • Javaを使ったソフトウェアのパフォーマンスを改善したい
  • 要求されている性能を満たせず、何から始めればよいか分からない

 

今回は、パフォーマンスを大幅に向上させることが期待できる優れたコーディング習慣が紹介されている以下の著書を参考に、実際にJavaのプログラミングでよくある事例を紹介いたします。

Effective Java 第3版

Java初心者が読むには少々難解です。Javaの基礎をしっかり抑え、オブジェクト指向を理解していることが前提となっています。Javaを扱うノウハウがたくさん詰まっており、エンジニアとしての能力をもう一段階上げてくれる書籍です。

Amazonで購入楽天で購入

 

ループの条件式は変数を使用する

例えば、以下のような for ループを記述している場合、条件式の無駄な計算が発生しています。

 

ループの条件式に複雑な式を使用してはいけません。(上記例の「list.size()」が該当)
ループでは、ループの条件式が繰り返し評価・計算されます。

複雑な式を使用せず、条件式を変数にすることでプログラムがより速く実行されるようになります。

 

パフォーマンスを改善する記述例



SANACHAN
SANACHAN
ループ回数が多い場合、顕著にパフォーマンスに影響します。

 

乗算・除算にはシフト演算子を使用する

2、4、8、などで乗算・除算する計算式は、シフト演算子を使用すると計算が早くなります

SANACHAN
SANACHAN
これは他の言語でも同じことが言えます。C言語やC++言語では有名な話ですね。

 

乗算・除算の悪い例



 

乗算・除算の記述改善例



 

final 修飾子をできるだけ使用する

final 修飾子をつけたクラスやメソッドは、継承してオーバーライドできなくなります。クラスに final 修飾子をつけた場合は、そのクラスの全てのメソッドが final になり派生することができなくなります。

 

なぜ final 修飾子をつけるとパフォーマンスが改善するのか?

ここはコンパイラの気持ちになって考えるとイメージしやすいです。

 

final がない場合は「オーバーライドされる可能性」があるため、常にどのクラスのメソッドを呼び出すべきかを考える必要があります。つまり、インライン化することができずメソッドとしてコンパイルされます

対して、final が付いている場合は、常にインライン化する機会を探しながらコンパイルされるため、効率の良いバイトコードが生成されるわけです。

SANACHAN
SANACHAN
コードの規模によりますが、50%程度パフォーマンスが改善したデータもあります。

 

文字列結合には StringBuilder を使う

文字列を結合する場合、Javaでは以下の方法があります。

  • 文字列結合演算子(
  • String.concat() による結合
  • StringBuilder による結合
  • StringBuffer による結合

 

たいていの場合、数個の文字列を一つの文字列に結合できる演算子()を使用していると思います。
しかし、演算子を使用する場合は、内部でオブジェクト生成が発生するため遅くなります

 

文字列結合の悪い例



演算子による文字列結合では、文字列を結合させる度に新しい文字列オブジェクトを作ります。
String型のオブジェクトはイミュータブル(immutable:変更不可)なので、コピーを行うためです。

注意ポイント

オブジェクトの生成にはコストがかかってパフォーマンスを悪化させますし、生成したオブジェクトの残骸が増えるとGC(ガベージコレクション)が動作してさらに性能を悪化させます。

 

StringBuilderを使用した改善例



注意ポイント

パフォーマンスを向上させるためには、自動的にバッファサイズを伸長させないよう、結合結果を保持できる十分なサイズの StringBuilder を使用前に割り当てておく必要があります

SANACHAN
SANACHAN
紹介した著書では5.5倍、Qiita記事の実測よると3000倍以上の性能改善ができるようです。

 

おわりに

いかがでしたでしょうか。

理解はしているものの、普段のプログラミングで意識してコーディングすることは難しいです。
性能が悪いと感じたら、先ずはプログラムを見直してみましょう。

たいていは、Java VMやフレームワークではなく、Javaのプログラム自体に問題があります。

 

こちらの記事もよく読まれています

  • この記事を書いた人
  • 最新記事
SANACHAN

SANACHAN

「生涯一エンジニア」を掲げ、大手グローバル企業でSE/PGとして8年勤め、キャリアアップ転職した現役のエンジニアです。世にあるメジャーな全プログラム言語(コボル除く)を自由に扱えます。一児の父。自分のため、家族のため、日々勉強してます。システムエンジニア、プログラミングに関する情報を蓄積している雑記帳です。

-Java
-, , ,