Накладные расходы, связанные с OutputDebugString в сборке выпуска - PullRequest
18 голосов
/ 08 апреля 2009

Существуют ли значительные издержки, связанные с вызовом OutputDebugString в сборке выпуска?

Ответы [ 7 ]

15 голосов
/ 08 апреля 2009

Измерено - 10M звонки занимают около 50 секунд. Я думаю, что это приводит к значительным накладным расходам на неиспользованную функциональность.

Использование макроса может помочь избавиться от этого в сборке релиза:

#ifdef _DEBUG
    #define LOGMESSAGE( str ) OutputDebugString( str );
#else
    #define LOGMESSAGE( str )
#endif

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

11 голосов
/ 18 августа 2009

Я пишу это задолго до того, как на этот вопрос дан ответ, но в данных ответах отсутствует определенный аспект:

OutputDebugString может быть довольно быстрым, когда никто не слушает его вывод. Однако наличие слушателя, работающего в фоновом режиме (будь то DbgView, DBWin32, Visual Studio и т. Д.), Может сделать его более чем в 10 раз медленнее (намного больше в среде MT). Причина заключается в том, что эти слушатели перехватывают событие отчета, и их обработка события выполняется в рамках вызова OutputDebugString. Более того, если несколько потоков одновременно вызывают OutputDebugString, они будут синхронизированы. Для получения дополнительной информации см. Осторожно: DebugView (OutputDebugString) и производительность .

В качестве примечания, я думаю, что если вы не используете приложение в реальном времени, вам не следует беспокоиться о том, что для выполнения вызовов 10M требуется 50 секунд. Если ваш журнал содержит 10 миллионов записей, то потраченные 50 секунд - это наименьшая из ваших проблем, теперь, когда вам нужно как-то проанализировать зверя. Журнал 10K звучит гораздо разумнее, и его создание займет всего 0,05 секунды согласно измерениям Sharp.

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

9 голосов
/ 08 апреля 2009

Я читал в статье, что OutPutDebugString внутренне делает несколько интересных вещей:

  1. Создает \ открывает мьютекс и ждет бесконечно, пока мьютекс не будет получен.
  2. Передача данных между приложением и отладчиком осуществляется через блок общей памяти размером 4 Кбайт с Mutex и двумя объектами Event, защищающими доступ к нему.

Даже если отладчик не подключен (в режиме выпуска), использование OutputDebugstring сопряжено со значительными расходами при использовании различных объектов ядра.

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

8 голосов
/ 08 апреля 2009

Я не видел проблем в десятках приложений на стороне сервера в режиме релиза, которые все имеют встроенные метрики. Вы можете получить впечатление , что это медленно, потому что большинство приложений отладчика, которые вы можете найти (DBWIN32 и др.), Довольно медленно выводят данные на экран, что создает впечатление запаздывания.

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

6 голосов
/ 08 апреля 2009

Никогда не оставляйте вызовы OutputDebugString () в сборке выпуска. Всегда удаляйте их, используя операторы #ifdef, или используйте другой параметр, чтобы отключить их.

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

Theres DebugView , чтобы поймать вывод приложений, но, конечно, это хорошо, если не каждое приложение общается без веской причины.

4 голосов
/ 08 апреля 2009

Почему бы не измерить это самостоятельно? Скомпилируйте следующий код, запустите его и проверьте время. Затем удалите вызов OutputDebugString, перекомпилируйте и запустите снова. Должно занять около трех минут вашего времени.

   #include <windows.h>

    int main() {
        const int COUNT = 1000000;
        int z = 0;    
        for ( unsigned int i = 0; i < COUNT; i++ ) {
            z += i;
            OutputDebugString( "foo" );
        }
        return z;
    }
2 голосов
/ 21 мая 2010

Мне было любопытно на эту тему, поэтому я провел небольшое исследование.

Я опубликовал результаты, исходный код и файлы проекта, чтобы вы могли повторить тесты для вашей установки. Охватывает запуск приложения режима выпуска без какого-либо мониторинга OutputDebugString, а затем с помощью Visual Studio 6, Visual Studio 2005 и Visual Studio 2010 отслеживает OutputDebugString, чтобы увидеть, какие различия в производительности существуют для каждой версии Visual Studio.

Интересные результаты: Visual Studio 2010 обрабатывает информацию OutputDebugString в 7 раз медленнее, чем Visual Studio 6.

Полная статья здесь: Сколько стоит OutputDebugString?

...