Помощь - Поиск - Пользователи - Календарь
Полная версия: Влияние блока try на скорость
Форум «Всё о Паскале» > Delphi, Assembler и другие языки. > Delphi
TarasBer
По идее влиять не должно. Однако

program TestTry;

{$APPTYPE CONSOLE}

uses
  Windows, Dialogs;

var
  T: integer;
  i: integer;

procedure Delay;
var
  i: integer;
  s: extended;
begin
  try
	s := sin(1);
  except
	ShowMessage('WTF?');
  //  ShowMessage('W T F ?');
	Halt;   
  end;
end;

begin
  T := GetTickCount;
  while T = GetTickCount do;
  T := GetTickCount;
  for i := 0 to 9999999 do Delay;
  i := GetTickCount - T;
  WriteLn(i);
  ReadLn;
end.


Все проверки убрал, отладчик выключил, оптимизацию включил.
В таком виде у меня выводит 2534-2544
Однако, если раскомментировать строчку со вторым сообщением, то он вдруг выводит 2834-2854.
Если добавить туда ещё строчку ShowMessage('W T F ?'), то он выведет 2613
Откуда берётся такая разница?
И как вообще устроен этот блок на самом деле?
volvo
Очень интересно... Вообще-то если ошибки не было, то содержимое блока except пропускается:
RSDN: Исключительные ситуации и надежное программирование

Кстати, это все компилируется в Debug-е или в Release? Что, если ВООБЩЕ убрать блок try/except - это даст прирост скорости на твоем компиляторе? Я попробовал у себя добавить десяток строк ShowMessage('всякая фигня') - время выполнения нисколько не увеличилось.
TarasBer
Это компилируется на дельфе-семёрке, все проверки выключены, отладка выключена, отладчик тоже, оптимизация включена. Я и ctrl+alt+c нажимал, ничего такого необычного (по данной теме) не обнаружил. С одним показом сообщения и с 3 скорость примерно одна, а с двумя - другая. Я подобрал именно такие два сообщения, которые наиболее замедляют выполнение. Странно даже, что с 3 сообщениями это делается быстрее, чем с 2мя.
Если убрать часть except, будет 2601. Если убрать try, оставив синус, будет 2353, ну это может из-за того, что try совершает заменяет указатель на обработчик исключений, это требует немного времени.
volvo
Цитата
С одним показом сообщения и с 3 скорость примерно одна, а с двумя - другая.
Да нет там показа, вот в чем проблема... Не было исключения - блок except проигнорировался... Если б был показ - то твоя программа тут же завершилась бы, ибо Halt находится там же...

Кстати, проверил этот же код в FPC (заменив ShowMessage на Writeln)... Мало того, что абсолютно одинаковое поведение (время нисколько не увеличивается вне зависимости от числа "выводимых" строк), так еще и время одно и то же. Что там что тут: 410
TarasBer
> Да нет там показа, вот в чем проблема...

Я понимаю.
Вопрос в том, что само наличие там этой строчки почему-то влияет на скорость.
volvo
А вот это как у тебя работает:
{$APPTYPE CONSOLE}
{.$OPTIMIZATION OFF}

uses
  Windows, Dialogs, SysUtils;

procedure Delay;
var
  s: extended;
begin
  try
    s := sin(1);
  except
    on E: Exception do // Это может оказаться необходимым...
    begin
      ShowMessage('WTF?');
      ShowMessage('W T F ?');
      Halt;
    end;
  end;
end;

var
  T: cardinal;
  i: integer;
begin
  T := GetTickCount;
  while T = GetTickCount do;

  T := GetTickCount;
  for i := 0 to 9999999 do Delay;
  i := GetTickCount - T;
  WriteLn(i);
  ReadLn;
end.
?
TarasBer
Для трёх сообщений время не изменилось, для двух - уменьшилось с 2800 до 2600.
Странно, что никогда не вызывающийся код на что-то влияет.
volvo
Цитата
И как вообще устроен этот блок на самом деле?
Вот что показывает Дельфийский дизассемблер (View->DebugWindows->CPU Windows->Disassembly) для кода:

procedure Delay;
var
  s: extended;
begin
  try
    s := sin(1);
  except
    ShowMessage('WTF?');
    Halt;
  end;
end;

Project1.dpr.13: begin
0046C6F8 55               push ebp
0046C6F9 8BEC             mov ebp,esp
0046C6FB 83C4F0           add esp,-$10
0046C6FE 53               push ebx
0046C6FF 56               push esi
0046C700 57               push edi
Project1.dpr.14: try
0046C701 33C0             xor eax,eax
0046C703 55               push ebp
0046C704 682EC74600       push $0046c72e
0046C709 64FF30           push dword ptr fs:[eax]
0046C70C 648920           mov fs:[eax],esp
Project1.dpr.15: s := sin(1);
0046C70F 68FF3F0000       push $00003fff
0046C714 6800000080       push $80000000
0046C719 6A00             push $00
0046C71B E8846BF9FF       call Sin
0046C720 DB7DF0           fstp tbyte ptr [ebp-$10]
0046C723 9B               wait 
0046C724 33C0             xor eax,eax
0046C726 5A               pop edx
0046C727 59               pop ecx
0046C728 59               pop ecx
0046C729 648910           mov fs:[eax],edx
0046C72C EB19             jmp $0046c747
0046C72E E90D80F9FF       jmp @HandleAnyException
Project1.dpr.19: ShowMessage('WTF?');
0046C733 B85CC74600       mov eax,$0046c75c
0046C738 E8B7F8FFFF       call ShowMessage
Project1.dpr.21: Halt;
0046C73D E89E89F9FF       call @Halt0
0046C742 E85184F9FF       call @DoneExcept
Project1.dpr.24: end;
0046C747 5F               pop edi
0046C748 5E               pop esi
0046C749 5B               pop ebx
0046C74A 8BE5             mov esp,ebp
0046C74C 5D               pop ebp
0046C74D C3               ret 


А при добавлении второй строки:
procedure Delay;
var
  s: extended;
begin
  try
    s := sin(1);
  except
    ShowMessage('WTF?');
    ShowMessage('W T F?');
    Halt;
  end;
end;


код транслируется вот так:
Project1.dpr.13: begin
0046C6F8 55               push ebp
0046C6F9 8BEC             mov ebp,esp
0046C6FB 83C4F0           add esp,-$10
0046C6FE 53               push ebx
0046C6FF 56               push esi
0046C700 57               push edi
Project1.dpr.14: try
0046C701 33C0             xor eax,eax
0046C703 55               push ebp
0046C704 682EC74600       push $0046c72e
0046C709 64FF30           push dword ptr fs:[eax]
0046C70C 648920           mov fs:[eax],esp
Project1.dpr.15: s := sin(1);
0046C70F 68FF3F0000       push $00003fff
0046C714 6800000080       push $80000000
0046C719 6A00             push $00
0046C71B E8846BF9FF       call Sin
0046C720 DB7DF0           fstp tbyte ptr [ebp-$10]
0046C723 9B               wait 
0046C724 33C0             xor eax,eax
0046C726 5A               pop edx
0046C727 59               pop ecx
0046C728 59               pop ecx
0046C729 648910           mov fs:[eax],edx
0046C72C EB23             jmp $0046c751
0046C72E E90D80F9FF       jmp @HandleAnyException
Project1.dpr.17: ShowMessage('WTF?');
0046C733 B864C74600       mov eax,$0046c764
0046C738 E8B7F8FFFF       call ShowMessage
Project1.dpr.18: ShowMessage('W T F?');
0046C73D B87CC74600       mov eax,$0046c77c
0046C742 E8ADF8FFFF       call ShowMessage
Project1.dpr.19: Halt;
0046C747 E89489F9FF       call @Halt0
0046C74C E84784F9FF       call @DoneExcept
Project1.dpr.21: end;
0046C751 5F               pop edi
0046C752 5E               pop esi
0046C753 5B               pop ebx
0046C754 8BE5             mov esp,ebp
0046C756 5D               pop ebp
0046C757 C3               ret 


Что здесь может замедлять выполнение?

В семерке есть возможность посмотреть на дизассемблированный код? Если есть, приведи, пожалуйста, эти два фрагмента... Сравнить хочется.
TarasBer
Да я первым же делом ктрл+альт+с нажал.
Два часа заливал два рисунка.
Который 2_втф - это без он е:ексепшон, а второй - с ним и с трёмя сообщениями.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.