Unityのバージョン:2019.1.0f2
前回の記事で(「文字列連結処理を比較してみた」)定数だと最適化されるよ、連結数が違うと結果が変わるよ、とコメントを頂いたので、条件を変えて再度比較してみました。
比べた文字連結方法は以下の通りです。
string s = "a" + "b";
StringBuilder builder = new StringBuilder();
for(int i = 0; i < n; ++i) {
builder.Clear();
builder.Append(”a”).Append("b");
string s = builder.ToString();
}
string s = string.Concat("a", "b");
string s = string.Format("{0}{1}", "a", "b");
string a = "a", b = "b";
string s = $"{a}{b}";
string str = StrOpe.i +"a" + "b";
※参考
【Unity】string の連結を StringBuilder に置き換えてパフォーマンスを改善できる「StringBuilderTemporary」紹介
FastString fast = new FastString(64);
for(int i = 0; i < n; ++i) {
fast.Clear();
fast.Append(”a”).Append("b");
string s = fast.ToString();
}
※参考
【Unity】string や StringBuilder よりもメモリ割り当てが少なく高速な文字列クラス「FastString」紹介
string str = StringUtils.Format("{0}{1}", "a", "b");
※参考
【Unity】ボックス化をなるべく回避して GC の発生を抑える string.Format「StringUtils」
using System;
using System.Text;
using UnityEngine;
using UnityEngine.Profiling;
using StrOpe = StringOperationUtil.OptimizedStringOperation;
public class Test : MonoBehaviour
{
const int repeat = 100000; // N
string tmp1 = "a";
string tmp2 = "b";
string tmp3 = "c";
string tmp4 = "d";
string tmp5 = "e";
StringBuilder _builder;
FastString _fast = new FastString(64);
void Start()
{
_builder = new StringBuilder();
PlayTest(Plus, "+");
PlayTest(StringBuilder, "StringBuilder");
PlayTest(Concat, "Concat");
PlayTest(Format, "Format");
PlayTest(Interpolation, "$\"\"");
PlayTest(StringBuilderTemporary, "StringBuilderTemporary");
PlayTest(FastString, "FastString");
PlayTest(UtilsFormat, "UtilsFormat");
}
void PlayTest(Func<string> func, string title)
{
Profiler.BeginSample(title);
string s = string.Empty;
for (int i = 0; i < repeat; ++i)
{
s = func();
}
Profiler.EndSample();
}
string Plus()
{
string str = tmp1 + tmp2 + tmp3 + tmp4 + tmp5;
return str;
}
string StringBuilder()
{
_builder.Clear();
_builder.Append(tmp1).Append(tmp2).Append(tmp3).Append(tmp4).Append(tmp5);
string str = _builder.ToString();
return str;
}
string Concat()
{
string str = string.Concat(tmp1, tmp2, tmp3, tmp4, tmp5);
return str;
}
string Format()
{
string str = string.Format("{0}{1}{2}{3}{4}", tmp1, tmp2, tmp3, tmp4, tmp5);
return str;
}
string Interpolation()
{
string str = $"{tmp1}{tmp2}{tmp3}{tmp4}{tmp5}";
return str;
}
string StringBuilderTemporary()
{
string str = StrOpe.i + tmp1 + tmp2 + tmp3 + tmp4 + tmp5;
return str;
}
string FastString()
{
_fast.Clear();
_fast.Append(tmp1).Append(tmp2).Append(tmp3).Append(tmp4).Append(tmp5);
string str = _fast.ToString();
return str;
}
string UtilsFormat()
{
string str = StringUtils.Format("{0}{1}{2}{3}{4}", tmp1, tmp2, tmp3, tmp4, tmp5);
return str;
}
}
using System;
using System.Text;
using UnityEngine;
using UnityEngine.Profiling;
using StrOpe = StringOperationUtil.OptimizedStringOperation;
public class Test : MonoBehaviour
{
const int repeat = 100000; // N
string tmp = "a";
StringBuilder _builder;
FastString _fast = new FastString(repeat + 1);
void Start()
{
_builder = new StringBuilder();
PlayTest(Plus, "+");
PlayTest(StringBuilder, "StringBuilder");
PlayTest(Concat, "Concat");
PlayTest(Format, "Format");
PlayTest(Interpolation, "$\"\"");
PlayTest(StringBuilderTemporary, "StringBuilderTemporary");
PlayTest(FastString, "FastString");
PlayTest(UtilsFormat, "UtilsFormat");
}
void PlayTest(Func<string> func, string title)
{
Profiler.BeginSample(title);
string s = func();
Profiler.EndSample();
}
string Plus()
{
string str = string.Empty;
for (int i = 0; i < repeat; ++i)
str += tmp;
return str;
}
string StringBuilder()
{
_builder.Clear();
for (int i = 0; i < repeat; ++i)
_builder.Append(tmp);
string str = _builder.ToString();
return str;
}
string Concat()
{
string str = string.Empty;
for (int i = 0; i < repeat; ++i)
str = string.Concat(str, tmp);
return str;
}
string Format()
{
string str = string.Empty;
for (int i = 0; i < repeat; ++i)
str = string.Format("{0}{1}", str, tmp);
return str;
}
string Interpolation()
{
string str = string.Empty;
for (int i = 0; i < repeat; ++i)
str = $"{str}{tmp}";
return str;
}
string StringBuilderTemporary()
{
string str = string.Empty;
for (int i = 0; i < repeat; ++i)
str = StrOpe.i + str + tmp;
return str;
}
string FastString()
{
for (int i = 0; i < repeat; ++i)
_fast.Append(tmp);
string str = _fast.ToString();
return str;
}
string UtilsFormat()
{
string str = string.Empty;
for (int i = 0; i < repeat; ++i)
str = StringUtils.Format("{0}{1}", str, tmp);
return str;
}
}
正確なしきい値は出していませんが、数が少ない連結(50個くらいまで)は「$""」、それ以上はStringBuilderを使えばいいのかな。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント