Почему условные точки останова так сильно тормозят мою программу? - PullRequest
14 голосов
/ 06 августа 2009

Когда я отлаживаю что-то, что идет не так внутри цикла, скажем, на 600-й итерации, это может быть болью, которую приходится ломать для каждого. Поэтому я попытался установить условную точку останова, чтобы сломать только если я = 600. Это работает, но теперь требуется почти полная минута, чтобы достичь той точки, которая раньше была почти мгновенной. Что происходит, и есть ли способ это исправить?

Ответы [ 6 ]

22 голосов
/ 06 августа 2009

Когда вы достигаете точки останова, Windows останавливает процесс и уведомляет отладчик. Он должен переключать контексты, оценивать условия, решать, что нет, вы не хотите получать уведомления об этом, перезапускать процесс и переключаться обратно. Это может занять много процессорных циклов. Если вы делаете это в замкнутом цикле, потребуется на пару порядков больше процессорных циклов, чем в одной итерации цикла.

Если вы хотите немного поработать с вашим кодом, есть способ сделать условные точки останова без дополнительных затрат.

if <condition here> then
  asm int 3 end;

Это простая инструкция по сборке, которая вручную отправляет уведомление о точке останова в ОС. Теперь вы можете оценить свое состояние внутри программы, не переключая контексты. Просто убедитесь, что вынули его снова, когда закончите. Если int 3 сработает внутри программы, которая не подключена к отладчику, он вызовет исключение.

6 голосов
/ 06 августа 2009

Это замедляет его, потому что каждый раз, когда вы достигаете этой точки, он должен проверять ваше состояние.

Что я обычно делаю, так это временно создаю другую переменную, подобную этой (в C, но должна быть выполнима в Delphi).

int xyzzynum = 600;
while (true) {
    doSomething();
    if (--xyzzynum == 0)
        xyzzynum = xyzzynum;
}

затем я ставлю безусловную точку останова на строку "xyzzynum = xyzzynum;".

Программа работает на полной скорости, пока не пройдет цикл 600 раз, поскольку отладчик просто выполняет обычное прерывание точки останова, а не проверяет условия каждый раз.

Вы можете сделать условие настолько сложным, насколько захотите.

4 голосов
/ 07 августа 2009

В дополнение к ответу Мейсона вы можете сделать так, чтобы сборка int 3 компилировалась только в том случае, если программа построена с определенным условием отладки:

{$ifdef debug}
{$message warn 'debug breakpoint present in code'}
if <condition here> then
  asm int 3 end;
{$endif}

Итак, когда вы отлаживаете в ide, у вас есть условие отладки в опциях проекта. Когда вы создаете конечный продукт для своих клиентов (со своим сценарием сборки?), Вы не включаете этот символ, поэтому он не будет скомпилирован.

Я также включил директиву компилятора $ message, поэтому при компиляции вы увидите предупреждение о том, что код все еще там. Если вы будете делать это везде, где используете int 3, у вас будет хороший список мест, по которым вы можете дважды щелкнуть мышью, чтобы перейти прямо к нарушающему коду.

N @

3 голосов
/ 06 августа 2009

Объяснения Мэйсона довольно хороши.
Его код можно сделать немного более безопасным , протестировав его в отладчике:

if (DebugHook <> 0) and <your specific condition here> then
  asm int 3 end;

Это не будет ничего делать, когда приложение работает нормально, и остановится, если оно будет запущено под отладчиком (запущено ли из IDE или подключено к отладчику).
А с логическим сочетанием клавиш <your specific condition here> даже не будет оцениваться, если вы не находитесь под отладчиком.

1 голос
/ 06 августа 2009

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

0 голосов
/ 06 августа 2009

Обычно точки останова условия работают, вставляя соответствующую инструкцию прерывания в код, а затем проверяя указанные вами условия. Он будет проверять на каждой итерации, и вполне может быть, что способ, которым реализована проверка, ответственен за задержку, поскольку маловероятно, что отладчик компилирует и вставляет полный код проверки и кода точки останова в существующий код.

Способ, которым вы могли бы ускорить это, если вы поместите условие, сопровождаемое операцией без побочных эффектов, непосредственно в код и нарушите эту операцию. Просто не забудьте удалить условие и опцию, когда вы закончите.

...