Javaパフォーマンス最適化:コードを遅くする8つのアンチパターン

アンチパターン修正によるパフォーマンス改善
Jonathan Vogelが構築したJava注文処理アプリケーションは、当初1,198msの経過時間、1秒あたり85,000件の注文処理、1GB強のヒープ使用量、19回のGCポーズでした。アーキテクチャ変更やJDKアップデートなしで8つのアンチパターンを修正した後、パフォーマンスは239msの経過時間、1秒あたり419,000件の注文処理、139MBのヒープ使用量、4回のGCポーズに改善しました。これは、5倍のスループット、87%のヒープ使用量削減、79%のGCポーズ削減を表しています。
修正すべき8つのJavaパフォーマンスアンチパターン
- ループ内での文字列連結 - 不変性によるO(n²)のコピー
- ループ内でのO(n²)ストリーム反復 - 要素ごとに全リストをストリーミング
- ホットパスでのString.format() - 最も遅い文字列ビルダー、呼び出しごとにフォーマットを解析
- ホットパスでのオートボクシング - 数百万の使い捨てラッパーオブジェクト
- 制御フローのための例外 - fillInStackTrace()がコールスタック全体を走査
- 範囲が広すぎる同期 - 1つのロックがボトルネックになる
- 再利用可能なオブジェクトの再作成 - 呼び出しごとのObjectMapper、DateTimeFormatter、Gson
- 仮想スレッドのピン止め(JDK 21-23) - synchronized + ブロッキングI/Oがキャリアをピン止め
詳細な例と修正方法
1. ループ内での文字列連結
問題のあるコード:
String report = "";
for (String line : logLines) {
report = report + line + "\n";
}これは文字列の不変性によりO(n²)のコピーを生成します。BellSoft JMHベンチマークでは、nが4倍になると、ループ連結は7倍以上遅くなることが示されています。
修正:
StringBuilder sb = new StringBuilder();
for (String line : logLines) {
sb.append(line).append("\n");
}
String report = sb.toString();注: JDK 9以降、コンパイラは「Order: " + id + " total: " + amountのような単一行の連結を最適化しますが、この最適化はループ内には適用されません。
2. ループ内でのストリームによる偶発的なO(n²)
問題のあるコード:
for (Order order : orders) {
int hour = order.timestamp().atZone(ZoneId.systemDefault()).getHour();
long countForHour = orders.stream()
.filter(o -> o.timestamp().atZone(ZoneId.systemDefault()).getHour() == hour)
.count();
ordersByHour.put(hour, countForHour);
}このパターンは、JFR記録のCPUスタックサンプルの約71%を占めていました。10,000件の注文では、単一パスではなく1億回の比較を実行します。
修正:
for (Order order : orders) {
int hour = order.timestamp().atZone(ZoneId.systemDefault()).getHour();
ordersByHour.merge(hour, 1L, Long::sum);
}これは1パスでO(n)のパフォーマンスを提供します。単一のストリームパイプラインでCollectors.groupingBy(... Collectors.counting())を使用することもできます。
この記事は3部構成のJavaパフォーマンス最適化シリーズの第1部であり、第2部と第3部は近日公開予定です。第2部では、フレームグラフや実際にホットだったメソッドを含む、これらの数値の背後にあるプロファイリングデータを詳しく見ていきます。
📖 完全なソースを読む: HN AI Agents
👀 See Also

コミュニティソースから編集されたOpenClawリソースリスト
GitHubリポジトリには、セットアップ、構成、メモリシステム、セキュリティ、スキル、モデル互換性、コミュニティリンクをカバーする実用的なOpenClawリソースが集められており、開発者が一般的な情報ギャップを回避するのに役立ちます。

リバースエンジニアリングされたソースからのClaude Codeのプロダクションエンジニアリングパターンの分析
開発者が、Claude CodeのTypeScriptソースコード約50万行をリバースエンジニアリングし、実際の負荷、実際の資金、実際の攻撃者という条件下で現れるプロダクションエンジニアリングパターンを記録した19章からなる技術ハンドブックを作成しました。

オープンクロー・メモリージャーニー:組み込み検索 vs MemPalace によるリアルタイムセッション想起
開発者がIntel Mac上で組み込みmemorySearch、QMD、MemPalaceをベンチマーク。リアルタイムセッションインデックスに問題があり、cronによる再インデックスを用いた分割戦略に落ち着く。

OpenClawメモリプラグインのテスト結果と推奨スタック
RedditユーザーがすべてのOpenClawメモリプラグインをテストした結果、デフォルトのマークダウン設定がトークンの肥大化と指示の圧縮を引き起こすことが判明しました。推奨される設定は、人間が読みやすいノート用にObsidian、トークンフリー検索用にQMD、構造化データ用にSQLiteを組み合わせたものです。