2009-04-08 20 views

risposta

14

Misurato: le chiamate da 10 M richiedono circa 50 secondi. Penso che sia un significativo overhead per le funzionalità inutilizzate.

Utilizzando una macro può aiutare a sbarazzarsi di questo build di rilascio:

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

rimuove Non solo le chiamate, ma anche la valutazione dei parametri e le stringhe di testo sono completamente rimosso e non li vedrete in il file binario.

4

Perché non misurarlo da soli? Compilare il seguente codice, eseguirlo ora &. Quindi rimuovere la chiamata a OutputDebugString, ricompilare e rieseguire. Dovrebbe prendere circa tre minuti di tempo.

#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; 
    } 
+4

Nota che proprio l'esecuzione di questo codice non è tutta la storia. Le prestazioni saranno in gran parte determinate da ciò che sta monitorando l'output di debug (DebugView, debugger di Visual Studio, ecc.) E potrebbero differire a seconda della versione di Windows in esecuzione, quindi è necessario testare in molte circostanze diverse. Ci vorrebbero più di tre minuti della propria ora. –

+1

Ho provato lo snippet di codice precedente utilizzando il tempo di un uomo povero (NULL) - start. Le 1000.000 volte impiegano 13 secondi se si attiva OutputDebugString, ma nessun debugger collegato, se DbgViewer è aperto per catturare l'output, il tempo è di 169 secondi. Se si disattiva OutputDebugString, il tempo misurato è 0 secondi. – zhaorufei

8

Non ho mai visto un problema in decine di applicazioni lato server in modalità di rilascio nel corso degli anni, i quali sono dotati di metriche. Puoi ottenere l'impressione che è lenta perché la maggior parte delle applicazioni di debug-catcher che puoi trovare (DBWIN32 et al) sono piuttosto lente nel lanciare i dati sullo schermo, il che dà l'impressione di ritardo.

Naturalmente tutte le nostre applicazioni hanno questa uscita disabilitata per default, ma è utile per essere in grado di accenderlo in campo, dato che è possibile quindi visualizzare l'output di debug da diverse applicazioni, serializzato in qualcosa di simile DBWin32 . Questa può essere una tecnica di debug molto utile per i bug che riguardano la comunicazione di applicazioni.

+0

+1 per _è utile per essere in grado di attivarlo nel campo_ –

9

avevo letto in un articolo che OutputDebugString internamente fa alcune cose interessanti:

  1. Crea \ Apre mutex e aspettare all'infinito fino mutex è acquisito.
  2. Passa i dati tra l'applicazione e il debugger tramite un blocco da 4kbyte di memoria condivisa, con un Mutex e due oggetti Event che proteggono l'accesso ad esso.

Anche se il debugger non è collegato (in modalità di rilascio) vi è un costo significativo nell'utilizzo di OutputDebugstring con l'utilizzo di vari oggetti del kernel.

Il successo delle prestazioni è molto evidente se si scrive un codice di esempio e un test.

6

Non lasciare mai le chiamate di OutputDebugString() in una build di rilascio. Rimuoverli sempre usando le istruzioni #ifdef o fornire un altro interruttore per disattivarli.

Se li si lascia in, hanno loro disabilitata di default, e solo attivarli su richiesta, perché altrimenti la vostra applicazione sarà più difficile eseguire il debug di altre applicazioni che si comportano belle (vale a dire, solo i dati di output di debug su richiesta).

Theres DebugView per catturare l'output di app, ma ovviamente è buono solo se non tutte le chatter di app lungo senza una buona ragione.

10

sto scrivendo questo per molto tempo dopo questa domanda è stato risposto, ma le risposte fornite perdere un certo aspetto:

OutputDebugString può essere abbastanza veloce quando nessuno è in ascolto alla sua uscita.Tuttavia, avere un listener in esecuzione in background (che si tratti di DbgView, DBWin32, Visual Studio ecc.) Può renderlo più di 10 volte più lento (molto di più nell'ambiente MT). Il motivo per cui tali ascoltatori agganciano l'evento del report e la loro gestione dell'evento viene eseguita nell'ambito della chiamata OutputDebugString. Inoltre, se più thread chiamano OutputDebugString contemporaneamente, verranno sincronizzati. Per ulteriori informazioni, vedere Watch out: DebugView (OutputDebugString) & Performance.

Come nota a margine, penso che, a meno che tu non stia utilizzando un'applicazione in tempo reale, non dovresti preoccuparti di una struttura che impiega 50 secondi per eseguire chiamate 10M. Se il tuo log contiene 10 milioni di voci, i 50 secondi sprecati sono l'ultimo dei tuoi problemi, ora che devi in ​​qualche modo analizzare la bestia. Un log di 10K suona molto più ragionevole, e la creazione di quello richiederà solo 0,05 secondi come da misurazione del dente di sharptooth.

Quindi, se l'output è di dimensioni ragionevoli, l'uso di OutputDebugString non dovrebbe farti molto male. Tuttavia, tenere presente che si verificherà un rallentamento una volta che qualcuno nel sistema inizia ad ascoltare questo output.

2

Ero curioso di questo argomento, quindi ho fatto qualche ricerca.

Ho pubblicato i risultati, il codice sorgente e i file di progetto in modo da poter ripetere i test per la configurazione. Copre l'esecuzione di un'app in modalità di rilascio senza alcun monitoraggio di OutputDebugString e quindi con Visual Studio 6, Visual Studio 2005 e Visual Studio 2010 monitorando OutputDebugString per vedere quali differenze di prestazioni esistono per ciascuna versione di Visual Studio.

risultati interessanti, Visual Studio 2010 processi OutputDebugString informazioni fino a 7x più lento di quello di Visual Studio 6.

Articolo completo qui: Whats the cost of OutputDebugString?

Problemi correlati