Блоки попытки/выгоды повреждают производительность, когда исключения не выдаются?

Я когда-то скопировал эти файлы в папку устройства хранения данных базы данных для mysql базы данных, которая работала, запустила дб и ожидала его для "восстанавливания" файлов, затем извлекла их с mysqldump.

258
задан user247702 19 November 2018 в 05:46
поделиться

9 ответов

Проверить это.

static public void Main(string[] args)
{
    Stopwatch w = new Stopwatch();
    double d = 0;

    w.Start();

    for (int i = 0; i < 10000000; i++)
    {
        try
        {
            d = Math.Sin(1);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }
    }

    w.Stop();
    Console.WriteLine(w.Elapsed);
    w.Reset();
    w.Start();

    for (int i = 0; i < 10000000; i++)
    {
        d = Math.Sin(1);
    }

    w.Stop();
    Console.WriteLine(w.Elapsed);
}

Вывод:

00:00:00.4269033  // with try/catch
00:00:00.4260383  // without.

В миллисекундах:

449
416

Новый код:

for (int j = 0; j < 10; j++)
{
    Stopwatch w = new Stopwatch();
    double d = 0;
    w.Start();

    for (int i = 0; i < 10000000; i++)
    {
        try
        {
            d = Math.Sin(d);
        }

        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

        finally
        {
            d = Math.Sin(d);
        }
    }

    w.Stop();
    Console.Write("   try/catch/finally: ");
    Console.WriteLine(w.ElapsedMilliseconds);
    w.Reset();
    d = 0;
    w.Start();

    for (int i = 0; i < 10000000; i++)
    {
        d = Math.Sin(d);
        d = Math.Sin(d);
    }

    w.Stop();
    Console.Write("No try/catch/finally: ");
    Console.WriteLine(w.ElapsedMilliseconds);
    Console.WriteLine();
}

Новые результаты:

   try/catch/finally: 382
No try/catch/finally: 332

   try/catch/finally: 375
No try/catch/finally: 332

   try/catch/finally: 376
No try/catch/finally: 333

   try/catch/finally: 375
No try/catch/finally: 330

   try/catch/finally: 373
No try/catch/finally: 329

   try/catch/finally: 373
No try/catch/finally: 330

   try/catch/finally: 373
No try/catch/finally: 352

   try/catch/finally: 374
No try/catch/finally: 331

   try/catch/finally: 380
No try/catch/finally: 329

   try/catch/finally: 374
No try/catch/finally: 334
194
ответ дан 23 November 2019 в 02:41
поделиться

№ Если тривиальная оптимизация, которую исключает блок try / finally, действительно оказывает ощутимое влияние на вашу программу, вам, вероятно, вообще не следует использовать .NET.

61
ответ дан 23 November 2019 в 02:41
поделиться

Довольно исчерпывающее объяснение модели исключений .NET.

Лакомые кусочки производительности Рико Мариани. : Стоимость исключения: Когда бросать, а когда нет

Первый вид стоимости - статический стоимость обработки исключений в ваш код вообще. Управляемые исключения на самом деле здесь сравнительно хорошо, под этим я подразумеваю, что статическая стоимость может быть намного ниже, чем говорят в C ++. Почему этот? Что ж, статическая стоимость действительно понесены в двух местах: Во-первых, актуальные сайты попробуйте / наконец / поймать / бросить где есть код для этих конструкций. Во-вторых, в безымянный код, есть скрытность затраты, связанные с отслеживанием все объекты, которые должны быть разрушен в случае, если выбрасывается исключение. Есть значительный объем логики очистки это должно быть и подлый часть в том, что даже код, который не сам бросить или поймать или иначе есть еще какое-либо открытое использование исключений несет бремя знания, как убирать за собой.

Дмитрий Заславский:

Согласно примечанию Криса Брамме: Есть также расходы, связанные с тем, что некоторая оптимизация не проводится выполняется JIT в присутствии ловушка

33
ответ дан 23 November 2019 в 02:41
поделиться

Я тестировал реальное влияние try..catch в замкнутом цикле, и он сам по себе слишком мал, чтобы быть проблема производительности в любой нормальной ситуации.

Если цикл выполняет очень мало работы (в моем тесте я выполнил x ++ ), вы можете измерить влияние обработки исключений. Цикл с обработкой исключений выполнялся примерно в десять раз дольше.

Если цикл выполняет некоторую реальную работу (в моем тесте я назвал метод Int32.Parse), обработка исключений оказывает слишком слабое влияние, чтобы его можно было измерить. Я получил гораздо большую разницу, поменяв местами циклы ...

14
ответ дан 23 November 2019 в 02:41
поделиться

Блоки try catch оказывают незначительное влияние на производительность, но выброс исключения может быть довольно значительным, это, вероятно, смутило вашего коллегу.

10
ответ дан 23 November 2019 в 02:41
поделиться

Структура в примере отличается от Ben M . Это будет увеличивать накладные расходы внутри внутреннего цикла for , что приведет к тому, что сравнение этих двух случаев будет не лучшим.

Следующее более точно для сравнения, когда весь код для проверки (включая объявление переменной) ) находится внутри блока Try / Catch:

        for (int j = 0; j < 10; j++)
        {
            Stopwatch w = new Stopwatch();
            w.Start();
            try { 
                double d1 = 0; 
                for (int i = 0; i < 10000000; i++) { 
                    d1 = Math.Sin(d1);
                    d1 = Math.Sin(d1); 
                } 
            }
            catch (Exception ex) {
                Console.WriteLine(ex.ToString()); 
            }
            finally { 
                //d1 = Math.Sin(d1); 
            }
            w.Stop(); 
            Console.Write("   try/catch/finally: "); 
            Console.WriteLine(w.ElapsedMilliseconds); 
            w.Reset(); 
            w.Start(); 
            double d2 = 0; 
            for (int i = 0; i < 10000000; i++) { 
                d2 = Math.Sin(d2);
                d2 = Math.Sin(d2); 
            } 
            w.Stop(); 
            Console.Write("No try/catch/finally: "); 
            Console.WriteLine(w.ElapsedMilliseconds); 
            Console.WriteLine();
        }

Когда я запускал исходный тестовый код из Ben M , я заметил разницу как в конфигурации Debug, так и в конфигурации Releas.

Эта версия, Я заметил разницу в отладочной версии (на самом деле больше, чем в другой версии), но не было разницы в версии Release.

Заключение :
Основываясь на этом тесте, я думаю, мы можем сказать, что Try / Catch действительно оказывает небольшое влияние на производительность.

EDIT:
Я попытался увеличить значение цикла с 10000000 до 1000000000 и запустил снова в Release, чтобы увидеть некоторые различия в выпуске, и результат был следующим:

   try/catch/finally: 509
No try/catch/finally: 486

   try/catch/finally: 479
No try/catch/finally: 511

   try/catch/finally: 475
No try/catch/finally: 477

   try/catch/finally: 477
No try/catch/finally: 475

   try/catch/finally: 475
No try/catch/finally: 476

   try/catch/finally: 477
No try/catch/finally: 474

   try/catch/finally: 475
No try/catch/finally: 475

   try/catch/finally: 476
No try/catch/finally: 476

   try/catch/finally: 475
No try/catch/finally: 476

   try/catch/finally: 475
No try/catch/finally: 474

Вы видите, что результат непоследовательный. В некоторых случаях версия, использующая Try / Catch, действительно работает быстрее!

24
ответ дан 23 November 2019 в 02:41
поделиться

После просмотра всей статистики для с try / catch и без try / catch, любопытство заставило меня взглянуть за , чтобы увидеть, что сгенерировано для обоих случаев. Вот код:

C #:

private static void TestWithoutTryCatch(){
    Console.WriteLine("SIN(1) = {0} - No Try/Catch", Math.Sin(1)); 
}

MSIL:

.method private hidebysig static void  TestWithoutTryCatch() cil managed
{
  // Code size       32 (0x20)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldstr      "SIN(1) = {0} - No Try/Catch"
  IL_0006:  ldc.r8     1.
  IL_000f:  call       float64 [mscorlib]System.Math::Sin(float64)
  IL_0014:  box        [mscorlib]System.Double
  IL_0019:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                object)
  IL_001e:  nop
  IL_001f:  ret
} // end of method Program::TestWithoutTryCatch

C #:

private static void TestWithTryCatch(){
    try{
        Console.WriteLine("SIN(1) = {0}", Math.Sin(1)); 
    }
    catch (Exception ex){
        Console.WriteLine(ex);
    }
}

MSIL:

.method private hidebysig static void  TestWithTryCatch() cil managed
{
  // Code size       49 (0x31)
  .maxstack  2
  .locals init ([0] class [mscorlib]System.Exception ex)
  IL_0000:  nop
  .try
  {
    IL_0001:  nop
    IL_0002:  ldstr      "SIN(1) = {0}"
    IL_0007:  ldc.r8     1.
    IL_0010:  call       float64 [mscorlib]System.Math::Sin(float64)
    IL_0015:  box        [mscorlib]System.Double
    IL_001a:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                  object)
    IL_001f:  nop
    IL_0020:  nop
    IL_0021:  leave.s    IL_002f //JUMP IF NO EXCEPTION
  }  // end .try
  catch [mscorlib]System.Exception 
  {
    IL_0023:  stloc.0
    IL_0024:  nop
    IL_0025:  ldloc.0
    IL_0026:  call       void [mscorlib]System.Console::WriteLine(object)
    IL_002b:  nop
    IL_002c:  nop
    IL_002d:  leave.s    IL_002f
  }  // end handler
  IL_002f:  nop
  IL_0030:  ret
} // end of method Program::TestWithTryCatch

Я не эксперт в IL, но мы видим, что в четвертой строке создается локальный объект исключения. .locals init ([0] class [mscorlib] System.Exception ex) после этого все примерно так же, как и для метода без try / catch до семнадцатой строки IL_0021: leave.s IL_002f . Если возникает исключение, управление переходит к строке IL_0025: ldloc.0 , в противном случае мы переходим к метке IL_002d: leave.s IL_002f и функция возвращается.

100
ответ дан 23 November 2019 в 02:41
поделиться

Попытка / перехват ВЛИЯЕТ на производительность.

Но это не большое влияние. Сложность try / catch обычно составляет O (1), как и простое присваивание, за исключением случаев, когда они помещаются в цикл. Так что вы должны использовать их с умом.

Здесь - ссылка на производительность try / catch (хотя и не объясняет ее сложность, но это подразумевается). Взгляните на Выбрасывать меньше исключений раздел

7
ответ дан 23 November 2019 в 02:41
поделиться

Perl, 206 символов, с использованием идеи dmckee

Он длиннее, чем первый, который я отправил, но я все же считаю его интересным . И / или ужасно. Я еще не уверен. Здесь используется идея кодирования dmckee, а также пара других хороших идей, которые я видел. Сначала я думал, что «длина / смещение в фиксированной строке» не может дать меньше данных, чем схема в другом моем решении, которое использует фиксированные два байта на символ (и все байты для печати). На самом деле мне удалось сократить объем данных до значительно меньшего размера (один байт на символ плюс четыре байта для хранения 26-битного шаблона, который мы индексируем), но код для его повторного вывода длиннее, несмотря на все мои усилия. играть в гольф. (Менее сложно, IMO, но все равно длиннее.)

В любом случае, 206 символов; новые строки удаляются, кроме первого.

#!perl -lp
($a,@b)=unpack"b32C*",
"\264\202\317\0\31SF1\2I.T\33N/G\27\308XE0=\x002V7HMRfermlkjihgx\207\205";
$a=~y/01/-./;@m{A..Z,0..9,qw(. , ?)}=map{substr$a,$_%23,1+$_/23}@b;
$_=join' ',map$m{uc$_}||"/",/./g

Пояснение:

  • Данные состоят из двух частей. Первые четыре байта ( "\ 264 \ 202 \ 317 \ 0" ) представляют 32 бита кода Морзе ( "--.-..-.-.----- .. ... - ..-------- "), хотя используются только первые 26 бит. Это «ссылочная строка».
  • В оставшейся части строки данных хранится начальная позиция и длина подстрок ссылочной строки, которые представляют каждый символ - по одному байту на символ в порядке (A, B, .. .Z, 0, 1, ... 9, ".", ",", "?"). Значения кодируются как 23 * (длина - 1) + pos, и декодер меняет это значение на обратное. Последняя начальная позиция, конечно же, 22.
  • Таким образом, распаковка выполняет половину работы по извлечению данных, а третья строка (как показано здесь) делает все остальное, теперь у нас есть хэш с $ m {'a знак равно когда нет исключений. В частности, я думаю, что 32-разрядная реализация Windows имеет высокие накладные расходы, а 64-разрядная реализация - нет.

3
ответ дан 23 November 2019 в 02:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: