コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】ループ構文の処理速度の検証結果

はじめに

// for 文
for (int i = 0; i < array.Length; i++)
{
    Debug.Log(array[i]);
}

// for 文(ループ回数を変数にキャッシュ)
int max = array.Length;
for (int i = 0; i < max; i++)
{
    Debug.Log(array[i]);
}

// foreach 文
foreach (var n in array)
{
    Debug.Log(n);
}

// Array クラスの ForEach 関数
Array.ForEach(array, c => Debug.Log(c));

C#のループ構文で一番処理速度が高速なのはどの書き方なのか気になったので
Unityでいろいろなループ構文でDebug.Logを実行して処理速度を比較してみました

※Unityのバージョンは4.3.4です

検証結果

配列の場合

ループ方法 要素数 100 要素数 1,000 要素数 10,000
for (int i = 0; i < array.Length; i++) {} 0.05620767 秒 0.5522295 秒 5.4827800 秒
for (int i = 0; i < num; i++) {} 0.05693574 秒 0.5462796 秒 5.4543830 秒
foreach (var n in array) {} 0.05319814 秒 0.5503743 秒 5.4594120 秒
Array.ForEach(array, c => {}); 0.11020360 秒 1.1172990 秒 11.182310 秒

List の場合

ループ方法 要素数 100 要素数 1,000 要素数 10,000
for (int i = 0; i < list.Count; i++) {} 0.05819568 秒 0.5498013 秒 5.4457230 秒
for (int i = 0; i < num; i++) {} 0.05440858 秒 0.5452724 秒 5.4431950 秒
foreach (var n in list) {} 0.05427125 秒 0.5507185 秒 5.4520870 秒
list.ForEach(c => {}); 0.11904870 秒 1.1715450 秒 11.893260 秒

感想

for 文を使用した場合と foreach 文を使用した場合で速度は変わらなかったので
ソースコードを簡潔に書くためにも foreach 文を使用できる場合は
foreach 文を使用したほうが良さそうです

また、for 文を使用するときにループ回数(配列やリストの要素数)を
変数にキャッシュする場合としない場合でも速度は変わらなかったです

Array.ForEach 関数や List.ForEach 関数は for 文や foreach 文と比べて 2 倍ほど遅くなりました

検証用スクリプト

using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
public class for_test : MonoBehaviour
{
    public int m_element_num = 1000;
    public float m_array_for1_time = 0.0f;
    public float m_array_for2_time = 0.0f;
    public float m_array_foreach_time = 0.0f;
    public float m_array_ArrayForEach_time = 0.0f;
    public float m_list_for1_time = 0.0f;
    public float m_list_for2_time = 0.0f;
    public float m_list_foreach_time = 0.0f;
    public float m_list_ListForEach_time = 0.0f;
 
    void Start()
    {
        var array = new int[m_element_num];
 
        var list = new List<int>();
        
        for (int i = 0; i < m_element_num; i++)
        {
            list.Add(0);
        }
 
        m_array_for1_time = Time.realtimeSinceStartup;
        for (int i = 0; i < array.Length; i++)
        {
            Debug.Log(array[i]);
        }
        m_array_for1_time = Time.realtimeSinceStartup - m_array_for1_time;
 
        var max = array.Length;
        m_array_for2_time = Time.realtimeSinceStartup;
        for (int i = 0; i < max; i++)
        {
            Debug.Log(array[i]);
        }
        m_array_for2_time = Time.realtimeSinceStartup - m_array_for2_time;
 
        m_array_foreach_time = Time.realtimeSinceStartup;
        foreach (var n in array)
        {
            Debug.Log(n);
        }
        m_array_foreach_time = Time.realtimeSinceStartup - m_array_foreach_time;
 
        m_array_ArrayForEach_time = Time.realtimeSinceStartup;
        Array.ForEach(array, c => Debug.Log(c));
        m_array_ArrayForEach_time = Time.realtimeSinceStartup - m_array_ArrayForEach_time;
 
        m_list_for1_time = Time.realtimeSinceStartup;
        for (int i = 0; i < list.Count; i++)
        {
            Debug.Log(list[i]);
        }
        m_list_for1_time = Time.realtimeSinceStartup - m_list_for1_time;
 
        max = list.Count;
        m_list_for2_time = Time.realtimeSinceStartup;
        for (int i = 0; i < max; i++)
        {
            Debug.Log(list[i]);
        }
        m_list_for2_time = Time.realtimeSinceStartup - m_list_for2_time;
 
        m_list_foreach_time = Time.realtimeSinceStartup;
        foreach (var n in list)
        {
            Debug.Log(n);
        }
        m_list_foreach_time = Time.realtimeSinceStartup - m_list_foreach_time;
 
        m_list_ListForEach_time = Time.realtimeSinceStartup;
        list.ForEach(c => Debug.Log(c));
        m_list_ListForEach_time = Time.realtimeSinceStartup - m_list_ListForEach_time;
 
        Debug.Log("a_for1   " + m_array_for1_time);
        Debug.Log("a_for2   " + m_array_for2_time);
        Debug.Log("a_fore   " + m_array_foreach_time);
        Debug.Log("a_afore  " + m_array_ArrayForEach_time);
        Debug.Log("l_for1   " + m_list_for1_time);
        Debug.Log("l_for2   " + m_list_for2_time);
        Debug.Log("l_fore   " + m_list_foreach_time);
        Debug.Log("l_lfore  " + m_list_ListForEach_time);
    }
}

関連記事