2010-01-15 17 views
15

Sto costruendo un sacco di codice generato automaticamente, incluso un file particolarmente grande (~ 15K linee), usando un cross-compilatore mingw32 su linux. La maggior parte dei file è estremamente veloce, ma questo file di grandi dimensioni richiede un tempo inatteso (circa 15 minuti) per la compilazione.Come faccio a sapere perché g ++ impiega molto tempo su un particolare file?

Ho provato a manipolare varie bandiere di ottimizzazione per vedere se hanno avuto alcun effetto, senza alcuna fortuna. Quello di cui ho veramente bisogno è un modo per determinare che cosa sta facendo g ++ che richiede tanto tempo. Ci sono dei modi (relativamente semplici) per fare in modo che g + + generi l'output su diverse fasi della compilazione, per aiutarmi a restringere il problema?

Purtroppo, non ho la possibilità di ricostruire questo cross-compiler, quindi aggiungere le informazioni di debug al compilatore e passarlo attraverso non è una possibilità.

Cosa c'è nel file:

  • un mazzo di comprende
  • un mucchio di confronti tra stringhe
  • una serie di if-then controlli e invocando un costruttore

Il file è un fabbrica per produrre una tonnellata di sottoclassi specifiche differenti di una certa classe genitore. La maggior parte degli include, tuttavia, non sono niente di particolarmente fantasioso.


I risultati di -ftime-report, come suggerito da Neil Butterworth, indicano che la fase di "analisi della vita" sta prendendo 921 secondi, che occupa la maggior parte dei 15 minuti.

Sembra che ciò avvenga durante l'analisi del flusso di dati. Il file stesso è un insieme di confronti di stringhe condizionali, che costruiscono un oggetto per nome di classe fornito come stringa.

Pensiamo che cambiando questo punto in una mappa di nomi per i puntatori di funzione si possa migliorare un po 'le cose, quindi proveremo a farlo.


Infatti, generando una serie di funzioni predefinite (per oggetto) e la creazione di una mappa dal nome stringa dell'oggetto a un puntatore alla funzione ridotta fabbrica fase di compilazione dall'originale 15 minuti per circa 25 secondi, che farà risparmiare a tutti un sacco di tempo sulle loro build.

Grazie ancora a Neil Butterworth per il suggerimento circa -ftime-report.

+0

Dai un'occhiata a questo: http: //stackoverflow.com/questions/318398/why-does-c-compilation-take-so-long –

+0

Puoi dirci cosa c'è nel file? Funzioni in linea? Enums? Definisce? Include e liste macro? Quanti di loro? – Coincoin

+0

Hai lo stesso problema se usi il compilatore locale? In tal caso, è possibile ricostruirlo con il profilo abilitato per vedere dove viene speso il tempo. –

risposta

24

non darà tutti i dettagli che si desidera, ma provare a eseguire con il -v (verbose) e -ftime-report bandiere. Quest'ultimo produce un riassunto di ciò che il compilatore ha fatto.

+0

-ftime-report era l'indizio di cui avevo bisogno. – Schamp

3

Molto probabilmente include TONNES di include. Credo che MD elencherà tutti i file di inclusione in un determinato file CPP (che include include di include e così via).

+0

++ Sì. Gli include e i modelli annidati possono inviare il preprocessore a una corsa allegra. Almeno gli include possono essere gestiti con intestazioni precompilate. –

2

Ciò che rallenta g ++ in generale sono modelli. Ad esempio, Boost ama usarli. Questo significa bel codice, grandi prestazioni ma scarsa velocità di compilazione.

D'altra parte, 15min sembra estremamente lungo. Dopo un rapido googling, sembra che si tratta di un problema comune con MinGW

+0

Ho appena visto che Linux gcc e Visual Studio si comportano altrettanto male, quindi, ancora una volta, è stato il tipo di pacchetti sorgente compilati una sola volta, quindi i compilatori non avevano la possibilità di accelerarlo. – luiscubal

+0

@Tristram Cosa era la tua stringa di ricerca su google? – Schamp

1

Un altro processo da provare è aggiungere "indicatore di avanzamento" pragma s al codice per intercettare la parte del codice che impiega molto tempo. Il compilatore di Visual Studio fornisce #pragma message(), sebbene non ci sia un pragma standard per farlo.

Mettere un marcatore all'inizio del codice e un marcatore alla fine del codice. Il marcatore finale potrebbe essere un #error poiché non ti interessa il resto del file sorgente. Sposta i marker di conseguenza per intrappolare la sezione di codice impiegando il tempo più lungo.

Solo un pensiero ...

1

userei #if 0/#endif per eliminare grandi porzioni del file di origine dalla compilazione. Ripeti con diversi blocchi di codice fino a quando non indicherai quale blocco (o blocchi) sono lenti. Per i principianti, puoi vedere se il tuo #include è il problema utilizzando #if 0/#endif per escludere tutto tranne il #include.

0

Correlato a @Goz e @Josh_Kelley, è possibile ottenere gcc/g ++ per sputare l'origine preelaborata (con #include in linea) utilizzando -E. Questo è un modo per determinare quanto sia grande la tua fonte.

E se il compilatore stesso è il problema, si può essere in grado di stracciare il comando di compilazione che impiega molto tempo per vedere se c'è un particolare accesso ai file o un'azione interna specifica che richiede molto tempo.

0

Ciò che il compilatore vede è l'output del pre-processore, quindi la dimensione della singola sorgente non è una buona misura, è necessario considerare la fonte e tutti i file che include e i file che includono ecc. L'istanziazione di modelli per più tipi genera codice per ogni tipo separato utilizzato, in modo che possa finire per essere un sacco di codice. Ad esempio, se hai utilizzato ampiamente container STL per molte classi.

Le linee 15K in una sorgente sono piuttosto numerose, ma anche se divise, tutto quel codice deve ancora essere compilato; tuttavia, l'uso di una build incrementale può significare che non è necessario compilare tutto il tempo. Non c'è davvero bisogno di un file così grande; è solo una cattiva pratica/design. Inizio a pensare a una migliore modularizzazione quando un file arriva a 500 righe (anche se non ne sono dogmatico)

0

Una cosa da osservare durante la compilazione è quanta memoria il computer ha gratuitamente. Se il compilatore alloca così tanta memoria che il computer inizia a scambiare, il tempo di compilazione andrà benissimo.

Se ciò accade, una soluzione semplice è installare più RAM ... o semplicemente dividere il file in più parti che possono essere compilate separatamente.

Problemi correlati