おれんじりりぃぶろぐ

きっと何者にもなれないエンジニアのブログ

Unity2018での文字列の扱い方

概略

Unityで文字列の連結を行う方法として以下の3つのパフォーマンスを比較してみました。1000回ループし文字列を連結させた時の処理時間とGC回数を計測しました。

ソースコード

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

public class LinkStringSample : MonoBehaviour
{
    private const int N = 10000;

    public void StingTest()
    {
        
        int starttime = DateTime.Now.Hour * 60 *60 * 1000 + DateTime.Now.Minute * 60 * 1000 + 
                        DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
        string str = string.Empty;

        for (int i = 0; i < N; i++)
        {
            str += "aaa";
        }
        
        int now = DateTime.Now.Hour * 60 * 60 * 1000 + DateTime.Now.Minute * 60 * 1000 + 
                  DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;

        Debug.Log($"StingTest()実行時間: {now - starttime}ms");
        // GC.CollectionCountはプロスを起動してからのGC回数を返す
        // https://msdn.microsoft.com/ja-jp/library/system.gc.collectioncount(v=vs.110).aspx
        Debug.Log($"GC回数: {GC.CollectionCount(0)}回");

    }

    public void StringBuilderTest()
    {
        int starttime = DateTime.Now.Hour * 60 *60 * 1000 + DateTime.Now.Minute * 60 * 1000 + 
                        DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
        
        StringBuilder strBuilder = new StringBuilder();

        for (int i = 0; i < N; i++)
        {
            strBuilder.Append("aaa");
        }
        
        int now = DateTime.Now.Hour * 60 * 60 * 1000 + DateTime.Now.Minute * 60 * 1000 + 
                  DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
        
        Debug.Log($"StringBuilderTest()実行時間: {now - starttime}ms");
        Debug.Log($"GC回数: {GC.CollectionCount(0)}回");
    }

    public void BuildInStringTest()
    {
        int starttime = DateTime.Now.Hour * 60 *60 * 1000 + DateTime.Now.Minute * 60 * 1000 + 
                        DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
        
        string str = String.Empty;

        for (int i = 0; i < N; i++)
        {
            str = $"{str}aaa";
        }
        
        int now = DateTime.Now.Hour * 60 * 60 * 1000 + DateTime.Now.Minute * 60 * 1000 + 
                  DateTime.Now.Second * 1000 + DateTime.Now.Millisecond;
        
        Debug.Log($"BuildInStringTest()実行時間: {now - starttime}ms");
        Debug.Log($"GC回数: {GC.CollectionCount(0)}回");
    }
}

検証環境

  • Unity2018.3b13
    • .NET4.x
    • il2cpp
  • ios
    • iPhone7Plus
  • android
    • s8

結果

StingTest StringBuilderTest BuildInStringTest
Editor 511/168 0.6/56 1248/288
ios 234/1577 0.6/6 542/3885
android 708/2015 1.0/6 1613/5656
  • 処理時間(ミリsec)/GC回数(回)
  • 5回の平均値
  • EditorのGC回数は参考値

まとめ

  • 文字列の連結には基本的にはStringBuilderを使うのがよい
  • 特にインライン形式での埋め込みは高コストなのでDebugログなどの限定的な使用に留めるべきである

参考