Visual Studio — влияние условных и отключенных точек останова на время выполнения

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

Я предполагаю, что точка останова в пути кода, который не выполняется, не влияет на время выполнения.

Итак, мой вопрос двоякий:

  1. Существуют ли какие-либо ресурсы, которые могут количественно оценить стоимость, связанную с условными точками останова, и если да, то можно ли что-нибудь сделать, чтобы уменьшить их стоимость оценки во время выполнения?
  2. Есть ли какие-либо затраты, связанные с «отключенной» точкой останова? Под отключенным я подразумеваю, что VS отображает маркер точки останова в желобе с полым кругом.

Конечно, если что-то, что я упомянул выше, не имеет смысла, пожалуйста, укажите мне правильное направление.


person Drew Noakes    schedule 19.10.2009    source источник


Ответы (5)


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

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

  • Вызовы функций: это самое медленное, что вы можете сделать, потому что вызов функции требует перезапуска отлаживаемого процесса, чтобы в процессе могла произойти оценка функции.
  • Сравнение строк: под капотом они возвращаются к func evals

Что касается отключенных точек останова, то они не влияют на работу приложения.

person JaredPar    schedule 19.10.2009
comment
Оценка условной точки останова влечет за собой затраты как на прерывание отладчика, так и на оценку любого выражения, используемого для условия. Один из способов снизить стоимость (если это вызывает трудности при отладке приложения) — изменить исходный код для проверки условия с помощью обычного оператора if(), за которым следует нулевой оператор (;), а затем поместить там безусловную точку останова. . Это не всегда возможно (и, очевидно, требует доступа к источнику), но это способ снизить стоимость условной оценки. - person LBushkin; 19.10.2009
comment
@LBushkin, стоимость условной точки останова, к сожалению, намного сложнее. Выражения, набранные в отладчике, оцениваются в смешанном стиле, где часть выполняется в отлаживаемой программе, а часть — в отладчике (иногда только в процессе отладчика). Очень сложно подытожить танец, который происходит в посте SO. Но да, вы правы насчет оптимизации с помощью блока if(). Я делаю это, когда требуется сложное условное выражение. - person JaredPar; 19.10.2009

Одна вещь, на которую следует обратить внимание (которую я усвоил на собственном горьком опыте), - это убедиться, что вы ставите == при сравнении переменной со значением, а не одиночным =

Редактор точек останова не предупреждает вас, но когда точка останова оценивается, переменная изменяется! Мне потребовалось время, чтобы отладить мой код с этим!

Кроме того, если мне действительно нужна условная точка останова для запуска кода; Я добавляю условие в код, затем добавляю что-то вроде string stop = "here"; и поставить там обычную точку останова - тогда код работает быстрее.

person John Warlow    schedule 09.06.2010
comment
Что касается вашего последнего пункта - это работает, только если вы можете редактировать код, а в случае трудно воспроизводимой ошибки, если вы готовы перезапустить процесс. - person Drew Noakes; 10.06.2010

Я где-то читал, что для этих точек останова есть аппаратная поддержка, так что использование меньшего количества условных точек останова определенного типа, по сути, бесплатно, но, кроме того, для этого нужно использовать больше программного обеспечения. (OTOH, это было для нативных приложений, не уверен насчет этих новомодных вещей JIT.)

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

person Macke    schedule 19.10.2009

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

Что я делаю, когда нахожусь в ситуации, подобной вашей, так это делаю макрос assert. (вы можете использовать макрос assert, который предоставляет Visual Studio, но я не нравится). Попросите макрос проверить необходимое условие, а затем вызовите DebugBreak в случае неудачи. В релизной или непроверенной сборке вашего приложения, утверждение ничего не оценивает, поэтому ваш код не пострадает.

Простой макрос assert может выглядеть так:

#ifdef _DEBUG
#define assert(x)\
do{\
  if(!(x)){DebugBreak();}\
}while(0)
#else
#define assert(x)
#endif

и назовите это так:

assert(pValue != NULL && "A bad parameter was passed to the function");

Вы можете поместить дополнительный код в сбой перед DebugBreak (например, распечатать условие, которое не удалось, с помощью #x и/или номер строки/файла с помощью ____FILE____ и ____LINE____, чтобы вы могли дважды щелкнуть сообщение). Вы можете писать сообщения в журнал отладки с помощью OutputDebugString и даже проверить, подключен ли отладчик с помощью IsDebuggerPresent чтобы еще больше адаптировать ваше утверждение. Мне также нравится использовать строковый формат &&, чтобы дать немного больше информации о конкретном утверждении.

Есть несколько моментов, о которых следует помнить при использовании assert. Во-первых, не помещайте код, который ДОЛЖЕН быть запущен в макрос, так как он будет удален в сборке без отладки. По тем же причинам не добавляйте код с побочными эффектами. Кроме того, вы не хотите вызывать DebugBreak(), когда отладчик не подключен, потому что он, по сути, создает исключение, которое, если его не поймать, приведет к завершению приложения.

person Dolphin    schedule 19.10.2009

  1. Попробуйте поставить точку останова в коде, чтобы проверить производительность. НАПРИМЕР.

    Stopwatch st = new Stopwatch();
    st.Start();
    if(my condition)
    {
      st.Stop();
      Debugger.Break();
    }
    

    Нет, не совсем то же самое, но достаточно близко.

  2. Нет - отключенная точка останова отсутствует в исполняемой программе. Он просто хранится в метаданных VS для вашего удобства.

person noctonura    schedule 19.10.2009