По мотивам вот
этогоАвтор: Sinix
Дата: 19.04.16
поста.
| Код. |
| static void AssertState(bool condition, string message)
{
if (!condition)
{
throw new InvalidOperationException(message);
}
}
static void AssertState(bool condition, IFormattable message)
{
if (!condition)
{
throw new InvalidOperationException(message.ToString());
}
}
static void AssertStateMessage(bool condition, string message)
{
if (!condition)
{
throw new ArgumentException(message);
}
}
static void AssertStateMessage(bool condition, string messageFormat, params object[] args)
{
if (!condition)
{
throw new ArgumentException(string.Format(messageFormat, args));
}
}
static void AssertStateFunc(bool condition, Func<string> messageCallback)
{
if (!condition)
{
throw new InvalidOperationException(messageCallback());
}
}
static void Main(string[] args)
{
const int Count = 10 * 1000 * 1000;
Measure("Concatenation", () =>
{
for (int i = 0; i < Count; i++)
{
AssertState(true, "Message '" + i + "': " + i + "." + i + "!");
}
return Count;
});
Measure("Interpolation", () =>
{
for (int i = 0; i < Count; i++)
{
AssertState(true, $"Message '{i}':{i}.{i}!");
}
return Count;
});
Measure("String", () =>
{
for (int i = 0; i < Count; i++)
{
AssertState(true, "Message #0");
}
return Count;
});
Measure("String.Format", () =>
{
for (int i = 0; i < Count; i++)
{
AssertStateMessage(true, "Message '{0}':{0}.{0}!", i);
}
return Count;
});
Console.WriteLine();
Console.WriteLine("Done.");
}
static void Measure(string name, Func<long> callback)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
var mem = GC.GetTotalMemory(true);
var gc00 = GC.CollectionCount(0);
var gc01 = GC.CollectionCount(1);
var gc02 = GC.CollectionCount(2);
var sw = System.Diagnostics.Stopwatch.StartNew();
var result = callback();
sw.Stop();
var mem2 = GC.GetTotalMemory(false);
var gc10 = GC.CollectionCount(0);
var gc11 = GC.CollectionCount(1);
var gc12 = GC.CollectionCount(2);
var memDelta = (mem2 - mem) / 1024.0;
var gcDelta0 = gc10 - gc00;
var gcDelta1 = gc11 - gc01;
var gcDelta2 = gc12 - gc02;
Console.WriteLine(
"{0,20}: {1,5}ms, ips: {2,22:N} | Mem: {3,9:N2} kb, GC 0/1/2: {4}/{5}/{6} => {7,6}",
name, sw.ElapsedMilliseconds, result / sw.Elapsed.TotalSeconds, memDelta, gcDelta0, gcDelta1, gcDelta2, result);
}
|
| |
Всё почти как в первоисточнике, разница лишь в том, что я делаю конкатенацию/форматирование с несколькими элементами, не с одним. Но результаты у меня получаются совершенно другие:
Concatenation: 7545ms, ips: 1,325,367.80 | Mem: 955.69 kb, GC 0/1/2: 1351/0/0 => 10000000
Interpolation: 7907ms, ips: 1,264,567.77 | Mem: 265.71 kb, GC 0/1/2: 968/0/0 => 10000000
String: 58ms, ips: 170,960,920.04 | Mem: 8.00 kb, GC 0/1/2: 0/0/0 => 10000000
String.Format: 303ms, ips: 32,982,759.58 | Mem: 1,058.69 kb, GC 0/1/2: 133/0/0 => 10000000
Интерполяция, получается, медленнее даже простой конкатенации.
Проверял, собирая под разные фреймворки, от 4.0 до 4.6.2, плюс dotnet core, результаты примерно одинаковые.
Что я делаю не так?