Go to list of users who liked
Share on X(Twitter)
Share on Facebook
More than 5 years have passed since last update.
for,while,foreachの速度差を検証してみる
[2016/02/20 追記]
全部まとめて書いてしまったので単品で書いたものとILが異なっている可能性有り
個々で検証を行うとまた結果が違うかも・・・
【検証環境】
・Unity5.2.4f1(Personal Edition)
・Nexus7(Android 5.0.2)
・100万回ループした際にかかった時間を比較
【比較項目】
①forの前置インクリメント
②for
③while
④do-while
⑤foreach
⑥forのLengthチェック
⑦forのList<T>参照
⑧forのList<T>参照のCountチェック
⑨foreachのList<T>参照
⑩whileのLinkedList<T>参照
⑪foreachのLinkedList<T>参照
【テストコード】
using UnityEngine;using System.Collections.Generic;public class Test : MonoBehaviour {void Start() {int count = 1000000;int[] array = new int[count];List<int> list = new List<int>(count);LinkedList<int> link = new LinkedList<int>();float prevTime, nowTime;int hoge;// 適当なデータを格納for (int i = 0; i < count; i++) {hoge = UnityEngine.Random.Range(0, 65535);array[i] = hoge;list.Add(hoge);link.AddLast(hoge);}// ① for前置prevTime = Time.realtimeSinceStartup;for (int i = 0; i < count; ++i) {hoge = array[i];}nowTime = Time.realtimeSinceStartup;Debug.LogError("① for前置 : " + (nowTime-prevTime));// ③ for後置prevTime = Time.realtimeSinceStartup;for (int i = 0; i < count; i++) {hoge = array[i];}nowTime = Time.realtimeSinceStartup;Debug.LogError("② for後置 : " + (nowTime-prevTime));// ③ whileprevTime = Time.realtimeSinceStartup;int indexWhile = 0;while (indexWhile < count) {hoge = array[indexWhile];indexWhile++;}nowTime = Time.realtimeSinceStartup;Debug.LogError("③ while : " + (nowTime-prevTime));// ④ do-whileprevTime = Time.realtimeSinceStartup;int indexDo = 0;do {hoge = array[indexDo];indexDo++;} while (indexDo < count); nowTime = Time.realtimeSinceStartup;Debug.LogError("④ do-while : " + (nowTime-prevTime));// ⑤ foreachprevTime = Time.realtimeSinceStartup;foreach (int val in array) {hoge = val;} nowTime = Time.realtimeSinceStartup;Debug.LogError("⑤ foreach : " + (nowTime-prevTime));// ⑥ for-lengthprevTime = Time.realtimeSinceStartup;for (int i = 0; i < array.Length; i++) {hoge = array[i];} nowTime = Time.realtimeSinceStartup;Debug.LogError("⑥ for-length : " + (nowTime-prevTime));// ⑦ for-listprevTime = Time.realtimeSinceStartup;for (int i = 0; i < count; i++) {hoge = list[i];} nowTime = Time.realtimeSinceStartup;Debug.LogError("⑦ for-list : " + (nowTime-prevTime));// ⑧ for-list-.CountprevTime = Time.realtimeSinceStartup;for (int i = 0; i < list.Count; i++) {hoge = list[i];} nowTime = Time.realtimeSinceStartup;Debug.LogError("⑧ for-list.Count : " + (nowTime-prevTime));// ⑨ foreach-listprevTime = Time.realtimeSinceStartup;foreach (int val in list) {hoge = val;} nowTime = Time.realtimeSinceStartup;Debug.LogError("⑨ foreach-list : " + (nowTime-prevTime));// ⑩ while-linkprevTime = Time.realtimeSinceStartup;LinkedListNode<int> node = link.First;while (node != null) {hoge = node.Value;node = node.Next;} nowTime = Time.realtimeSinceStartup;Debug.LogError("⑩ while-link : " + (nowTime-prevTime));// ⑪ foreach-linkprevTime = Time.realtimeSinceStartup;foreach (int val in link) {hoge = val;} nowTime = Time.realtimeSinceStartup;Debug.LogError("⑪ foreach-link : " + (nowTime-prevTime));}}【結果】
① for前置 : 0.01135254
② for後置 : 0.01126099
③ while : 0.01022339
④ do-while : 0.01327515
⑤ foreach : 0.01751709
⑥ for-length : 0.01556396
⑦ for-list : 0.02728271
⑧ for-list.Count : 0.03369141
⑨ foreach-list : 0.03857422
⑩ while-link : 0.01895142
⑪ foreach-link : 0.03387451
【総評】
①~④については誤差レベル
試行回数を増やして平均値とれば差もなくなりそうな感じ
Unity/C#ではインクリメントも前置が後置より必ず早いということは見受けられなかった
(そもそもILレベルで差分が出てるのだろうか・・・)
また固定配列の.Lengthは思ったよりコストが高くなかった
神経質に配列長をキャッシュする必要は必ずしもないのかもしれない
foreachは速度の問題よりイテレータのインスタンスでヒープを食うのでランタイムでは使うべきでない
Editor拡張スクリプト等で使うべきだろう
List<T>については基本的に固定配列より参照が遅い
CapacityオーバーやInsert等のコストは当然高くメモリも余剰に食うので
特にListである必要がなければ固定配列にしたい
ただSortなど色々容易なのでランタイムでも使いたくなる場面はままある
おまけのLinkedListだがwhileで始端から終端をなめる分には速度は問題ない
しかしAddの際にノードのインスタンスを作るのでヒープを食ってしまう
GCが容認しづらい環境下での重用は難しい
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme