文字列の繰り返し
パフォーマンス関連の小ネタ。IronPythonのソースを読んでいてこんなのを発見。
public static string Multiply(string s, int count) { int sz = s.Length; if (sz == 1) return new string(s[0], count); StringBuilder ret = new StringBuilder(sz*count); ret.Insert(0, s, count); // the above code is MUCH faster than the simple loop //for (int i=0; i < count; i++) ret.Append(s); return ret.ToString(); }
Insertメソッドに繰り返し回数を取るオーバーロードがあったんですね。気づいてませんでした。(^^; で、どれくらいパフォーマンスが違うかというと、
using System; using System.Text; class Program { const int LOOP = 100000; // こんなコードはあり得ない(^^; public static string MultiplyString(string s, int count) { string ret = s; for (int i = 0; i < count - 1; ++i) ret += s; return ret; } // 単純追加 public static string MultiplyStringBuilder1(string s, int count) { StringBuilder sb = new StringBuilder(s.Length * count); for (int i = 0; i < count; ++i) sb.Append(s); return sb.ToString(); } // Insertメソッド public static string MultiplyStringBuilder2(string s, int count) { StringBuilder sb = new StringBuilder(s.Length * count); sb.Insert(0, s, count); return sb.ToString(); } static void Main(string[] args) { string s1 = "IronPython"; string s2 = ""; DateTime t; t = DateTime.Now; for (int i = 0; i < LOOP; ++i) { s2 = MultiplyString(s1, 100); } Console.WriteLine(DateTime.Now.Subtract(t)); t = DateTime.Now; for (int i = 0; i < LOOP; ++i) { s2 = MultiplyStringBuilder1(s1, 100); } Console.WriteLine(DateTime.Now.Subtract(t)); t = DateTime.Now; for (int i = 0; i < LOOP; ++i) { s2 = MultiplyStringBuilder2(s1, 100); } Console.WriteLine(DateTime.Now.Subtract(t)); } } /* 結果 00:00:09.6718750 00:00:00.7968750 00:00:00.3125000 */
このように2倍以上違います。(Stringは論外)
ところで、StringBuilderのAppendに
Append(string value, int repeatCount);
というオーバーロードが無いのは何故なんだろうか。charの繰り返しはあるのになぁ。