String.StartsWithを使用して奇妙なパフォーマンスの「アーティファクト」が発生しました。StringComparison.OrdinalIgnoreCaseを使用したString.Startsのパフォーマンス
OrdinalIgnoreCaseを使用しているString.Startsが、String.Componentを指定せずにString.StartsWithを使用するよりも高速であるようです。 (2-4倍高速)
ただし、OrdinalIgnoreCaseを使用する場合よりもStringComparisonを使用しないString.Equalsを使用する方が、等価性の検査が高速になります。 (すべてがほぼ同じスピードですが)
質問はなぜですか?なぜ彼らは2つのケースで異なった動作をしますか?ここで
は私が使っていたコードです。
public static void Test()
{
var options = new[] { "asd/klfe", "qer/jlkfe", "p33/ji", "fkjlfe", "asd/23", "bleash", "quazim", "ujv/3", "jvd/kfl" };
Random r;
const int trialSize = 100000;
const int trials = 1000;
Stopwatch swEqOp = new Stopwatch();
Stopwatch swEq = new Stopwatch();
Stopwatch swEqOrdinal = new Stopwatch();
Stopwatch swStartsWith = new Stopwatch();
Stopwatch swStartsWithOrdinal = new Stopwatch();
for (int i = 0; i < trials; i++)
{
{
r = new Random(1);
swEqOp.Start();
for (int j = 0; j < trialSize; j++)
{
bool result = options[r.Next(options.Length)] == "asd/klfe";
}
swEqOp.Stop();
}
{
r = new Random(1);
swEq.Start();
for (int j = 0; j < trialSize; j++)
{
bool result = string.Equals(options[r.Next(options.Length)], "asd/klfe");
}
swEq.Stop();
}
{
r = new Random(1);
swEqOrdinal.Start();
for (int j = 0; j < trialSize; j++)
{
bool result = string.Equals(options[r.Next(options.Length)], "asd/klfe", StringComparison.OrdinalIgnoreCase);
}
swEqOrdinal.Stop();
}
{
r = new Random(1);
swStartsWith.Start();
for (int j = 0; j < trialSize; j++)
{
bool result = options[r.Next(options.Length)].StartsWith("asd/");
}
swStartsWith.Stop();
}
{
r = new Random(1);
swStartsWithOrdinal.Start();
for (int j = 0; j < trialSize; j++)
{
bool result = options[r.Next(options.Length)].StartsWith("asd/",StringComparison.OrdinalIgnoreCase);
}
swStartsWithOrdinal.Stop();
}
}
//DEBUG with debugger attached. Release without debugger attached. AnyCPU both cases.
//DEBUG : 1.54 RELEASE : 1.359
Console.WriteLine("Equals Operator: " + swEqOp.ElapsedMilliseconds/1000d);
//DEBUG : 1.498 RELEASE : 1.349 <======= FASTEST EQUALS
Console.WriteLine("String.Equals: " + swEq.ElapsedMilliseconds/1000d);
//DEBUG : 1.572 RELEASE : 1.405
Console.WriteLine("String.Equals OrdinalIgnoreCase: " + swEqOrdinal.ElapsedMilliseconds/1000d);
//DEBUG : 14.234 RELEASE : 9.914
Console.WriteLine("String.StartsWith: " + swStartsWith.ElapsedMilliseconds/1000d);
//DEBUG : 7.956 RELEASE : 3.953 <======= FASTEST StartsWith
Console.WriteLine("String.StartsWith OrdinalIgnoreCase: " + swStartsWithOrdinal.ElapsedMilliseconds/1000d);
}
序数を使うとなぜ速くなるのか分かりません - なぜString.Equalsの動作が違うのか分かりません... – MineR
String.Equalsを見ると、String.Equalsを見ても実際にStringComparisonは使用されません。指定された代わりに特定の実装を使用します。 – MineR