3行で要約
- 本番運用しているSalesforceアプリケーションにて、「Apex CPU time limit exceeded」というエラーが発生するようになりました。
- どうやらデータ量が増えてガバナ制限内に処理が完了しなくなってしまったらしい。
- Apexコードの文字列結合がボトルネックになっていたため、それを解消して問題を解決しました。
背景
- ある日のこと、日次の注文データを、CSVファイルに書き込んでエクスポートする機能でエラーが発生。
- エラー内容は「Apex CPU time limit exceeded」とのこと。
- これはガバナ制限により、1つのApexトランザクションの実行時間を10秒以内にしなければならないために起こるエラーだそう(データベース操作やコールアウトの待ち時間は含みません)
- ちなみに10秒ちょうどでエラーになるのではなく、15秒前後まではギリギリ大丈夫みたいです
原因
- Limits.getCpuTimeout()メソッドを使ってトランザクション内の各処理の時間を測定します。
- CSVファイル生成のための文字列結合部分に「+」演算子を使っており、この処理が非常に遅くボトルネックになっていることが判明しました。
String csvBody = A + ',';
csvBody = csvBody + B + ',';
csvBody = csvBody + C + ',';
.
.
.
解決
- JavaであればStringBufferもしくはStringBuilderを用いることが推奨されているかと思いますが、残念ながらApexにはそのようなものは用意されていません。
- Stringクラスにあるjoinメソッドを使うことで文字列結合がだいぶ速くなりました。
List<String> csvItems = new List<String>();
csvItems.add(A);
csvItems.add(B);
csvItems.add(C);
.
.
.
String csvBody = String.join(csvItems, ',');
- 結果、ガバナ制限に引っかからなくなりました。
- ついつい文字列結合に「+」を使いたくなりますが、データ量が多くなりそうならなるべく使わないよう気をつけましょう