Test1
ниже на 10% быстрее, чем Test2
, хотя я всегда вызываю метод с аргументом 0
, поэтому материал, который внутри случая коммутатора - единственная разница, никогда не выполняется.
Btw после копирования и вставки кода в совершенно новый проект, только сменив имя тестовой функции на Main
, результаты будут отменены. Каждый раз, когда я запускаю этот проект, Test2
работает быстрее.
Итак, каковы факторы, связанные с тем, чтобы сделать это медленнее и быстрее? И: Могу ли я влиять на производительность сознательно в .net в свою пользу?
Эти методы, конечно, почти ничего не делают, поэтому разница в производительности на 10% для теста, которая включает в себя в основном идентичные вызовы виртуальных методов (которые, как правило, CLR не способны встраивать - вводная часть к ВС btw для реализации этого в JVM ) кажется огромным.
N.B. На самом деле это минимальная версия реальной программы, в которой несколько вложенных операторов switch приводят к огромной разнице в производительности не только 10%, но и 100% и более, по-видимому, благодаря наличию кода внутри вложенных ветвей коммутатора, которые испытывают никогда не входите. (Поэтому, возможно, эта минимальная версия опускает некоторые другие аспекты реальной программы, которые могут быть задействованы, но она реплицирует значительную и последовательную разницу в производительности)
Изменить. В реальной программе, что может быть важнее, чем явление в этом вопросе, заключается в том, соответствуют ли фактические утверждения case в заявлении коммутатора посредством таблица ветвей или нет - (что зависит от пробелов в значениях case - что-то, что я мог бы проверить, посмотрев на сгенерированный код IL)
Тестирование на
- .net 4.5.1
- Выполнить сборку, выполнить с помощью Ctrl-F5
- Intel i7 CPU
Код:
using System;
using System.Diagnostics;
class Test1 : ITest
{
public int Test(int a)
{
switch (a)
{
case 1: return a + a + a == 1234 ? 1 : 2;
case 2: return 2;
}
return 0;
}
}
class Test2 : ITest
{
public int Test(int a)
{
switch (a)
{
case 1: return 1;
case 2: return 2;
}
return 0;
}
}
class Program
{
static void Main(string[] args)
{
const long iterations = 200000000;
var test1 = new Test1();
var test2 = new Test2();
while (true)
{
var sw1 = Stopwatch.StartNew();
for (long i = 0; i < iterations; i++)
test1.Test(0);
sw1.Stop();
var sw2 = Stopwatch.StartNew();
for (long i = 0; i < iterations; i++)
test2.Test(0);
sw2.Stop();
var iterPerUsec1 = iterations / sw1.Elapsed.TotalMilliseconds / 1000;
var iterPerUsec2 = iterations / sw2.Elapsed.TotalMilliseconds / 1000;
Console.WriteLine("iterations per usec: " + (int) iterPerUsec1 + " / " + (int) iterPerUsec2 + " ratio: " + iterPerUsec1/iterPerUsec2);
}
}
}
interface ITest
{
int Test(int a);
}
Здесь вывод типичного прогона, где Test1 последовательно на самом деле более чем на 12% быстрее:
iterations per usec: 369 / 342 ratio: 1.07656329512607
iterations per usec: 367 / 314 ratio: 1.16820632522335
iterations per usec: 372 / 337 ratio: 1.10255744679504
iterations per usec: 374 / 342 ratio: 1.09248387354978
iterations per usec: 367 / 329 ratio: 1.11451205881061
iterations per usec: 375 / 340 ratio: 1.10041698470293
iterations per usec: 373 / 314 ratio: 1.19033461920118
iterations per usec: 366 / 334 ratio: 1.09808424282708
iterations per usec: 372 / 314 ratio: 1.18497411681768
iterations per usec: 377 / 342 ratio: 1.10482425370152
iterations per usec: 380 / 346 ratio: 1.09794853154766
iterations per usec: 385 / 342 ratio: 1.12737583603649
iterations per usec: 376 / 327 ratio: 1.15024393718844
iterations per usec: 374 / 332 ratio: 1.12400483908544
iterations per usec: 383 / 341 ratio: 1.12106159857722
iterations per usec: 380 / 345 ratio: 1.10267634674555
iterations per usec: 375 / 344 ratio: 1.09211401775982
iterations per usec: 384 / 334 ratio: 1.14958454236246
iterations per usec: 368 / 321 ratio: 1.14575850263002
iterations per usec: 378 / 335 ratio: 1.12732301818235
iterations per usec: 380 / 338 ratio: 1.12375853123099
iterations per usec: 386 / 344 ratio: 1.12213818994067
iterations per usec: 385 / 336 ratio: 1.14346447712043
iterations per usec: 374 / 345 ratio: 1.08448615249764
...