Сообщение Производительность работы со строками. Что я делаю не так? от 21.12.2016 19:08
Изменено 21.12.2016 23:06 Artem Korneev
По мотивам вот этого
Всё почти как в первоисточнике, разница лишь в том, что я делаю конкатенацию/форматирование с несколькими элементами, не с одним. Но результаты у меня получаются совершенно другие:
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, результаты примерно одинаковые.
Что я делаю не так?
Автор: Sinix
Дата: 19.04.16
поста.Дата: 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, результаты примерно одинаковые.
Что я делаю не так?
По мотивам вот этого
Всё почти как в первоисточнике, разница лишь в том, что я делаю конкатенацию/форматирование с несколькими элементами, не с одним. Но результаты у меня получаются совершенно другие:
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, результаты примерно одинаковые.
Что я делаю не так?
Автор: Sinix
Дата: 19.04.16
поста.Дата: 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, результаты примерно одинаковые.
Что я делаю не так?