たまにfor文で次のような処理を書くことがあります。
for (Integer i = 0; i < accounts.size(); i++) { // 処理・・・ }
ここのaccounts.size()はループのたびに実行されるので一度変数にセットしてから処理した方が効率的ですよねということを教えてもらいました。
イメージ的にはこんな感じです。
Integer listCnt = accounts.size(); for (Integer i = 0; i < listCnt ; i++) { // 処理・・・ }
全然意識していなかった箇所だったので、ほんとうにループのたび実行されるのか次の処理をつくって検証してみました。
開発者コンソールから次の処理で実行します。
このときのログがこんな感じです。
ループのたびにバッチリ実行されました。
もしかしたらaccount.size()のように書いた時には毎回実行されないのかもしれませんが、ひとまずこのような処理だと実行されるみたいです。
せっかくなので実際に変数にセットした場合としていない場合でパフォーマンスに変化があるか、以下の手順で検証してみました。
1. 変数にセットしないケース
結果に差が出やすいように2000件のリストで検証しました。
実行①
実行②
実行③
実行④
実行⑤
実行⑥
実行⑦
実行⑧
実行⑨
実行⑩
Durationが実行時間とのことなのでdoClickのDuration部分で確認できると思います。
※時間の単位は秒ではなく、ミリ秒ぐらいだったと思います。
Durationなどの詳細についてはこちらに詳しい説明があります。
ログインスペクタ
https://na9.salesforce.com/help/doc/ja/code_dev_console_view_system_log.htm
ログインスペクタの使用例
https://na9.salesforce.com/help/doc/ja/code_dev_console_solving_problems_using_system_log.htm#using_evaluate_vf_pages
実行時間をまとめると次のとおりです。
01回目:69.28
02回目:77.89
03回目:59.75
04回目:70.94
05回目:65.69
06回目:68.45
07回目:75.64
08回目:65.84
09回目:63.88
10回目:105.89
多少の誤差は出ましたが、平均すると72.325の時間がかかっています。
2. 変数にセットするケース
実行①
実行②
実行③
実行④
実行⑤
実行⑥
実行⑦
実行⑧
実行⑨
実行⑩
実行結果は次のとおりです。
01回目:26.77
02回目:37.21
03回目:75.25
04回目:30.58
05回目:27.02
06回目:68.02
07回目:34.82
08回目:30.06
09回目:30.24
10回目:30.80
平均すると39.077になりました。
処理時間がだいぶ短縮されました。
実際には大量件数のリストをループさせることはそんなにないと思うので、ここまで大きな差にはならないと思いますが、リスト件数は一度変数にセットして使用した方が効率の良い処理になるみたいです。
補足
もしかすると検証方法が間違ってたり、ただの誤差かもしれないです。
ちなみにApexのループ処理は次のような書き方もできます。
for (Account a : this.accounts) { // LOOP処理 }
特別な理由がない場合はこの書き方でループ処理を行う方が、コードも読みやすくなって良いと思います。
ついでなのでこの処理でのパフォーマンスも確認してみました。
実行①
実行②
実行③
・・・思ってたより時間かかるみたいです。
ただ実際にはそれほど気になるレベルではないと思います。大量件数のループ処理をやっていて、パフォーマンスの問題が発生したらちょっと実装方法を検討してみるぐらいじゃないかな・・・と思いました。