2010-01-15 11 views
15

Estoy construyendo una gran cantidad de código generado automáticamente, incluyendo un archivo particularmente grande (~ 15K líneas), usando un compilador cruzado mingw32 en Linux. La mayoría de los archivos son extremadamente rápidos, pero este archivo grande tarda un tiempo inesperadamente largo (~ 15 minutos) en compilarse.¿Cómo puedo averiguar por qué g ++ tarda mucho tiempo en un archivo en particular?

He intentado manipular varias banderas de optimización para ver si tenían algún efecto, sin suerte. Lo que realmente necesito es alguna forma de determinar qué está haciendo g ++ que lleva tanto tiempo. ¿Hay alguna forma (relativamente simple) de generar resultados en g ++ sobre diferentes fases de la compilación, para ayudarme a reducir el problema?

Lamentablemente, no tengo la capacidad de reconstruir este compilador cruzado, por lo que no es posible agregar información de depuración al compilador y recorrerlo.

¿Qué hay en el archivo:

  • un montón de incluye
  • un montón de comparaciones de cadenas
  • un montón de si-entonces los cheques y las invocaciones constructor

El archivo es una fábrica para producir una tonelada de diferentes subclases específicas de una cierta clase de padres. La mayoría de los incluyen, sin embargo, no son nada terriblemente elegante.


Los resultados de -ftime-informe, según lo sugerido por Neil Butterworth, indican que la fase de "análisis de la vida" está llevando a 921 segundos, que ocupa la mayor parte de los 15 minutos.

Parece que esto tiene lugar durante el análisis de flujo de datos. El archivo en sí es un conjunto de comparaciones de cadenas condicionales, que construyen un objeto por nombre de clase proporcionado como una cadena.

Creemos que cambiar esto para apuntar a un mapa de nombres para los indicadores de función puede mejorar un poco las cosas, así que vamos a intentar eso.


De hecho, la generación de un grupo de funciones de fábrica (por objeto) y crear un mapa a partir del nombre de cadena del objeto a un puntero a su función de reducción del tiempo de compilación de la fábrica a partir de los originales 15 minutos a aproximadamente 25 segundos, que ahorrará a todos toneladas de tiempo en sus compilaciones.

Gracias de nuevo a Neil Butterworth por la información sobre el informe de tiempo de actividad.

+0

Eche un vistazo a esto: http: //stackoverflow.com/questions/318398/why-does-c-compilation-take-so-long –

+0

¿Podría decirnos qué hay en el archivo? Funciones en línea? ¿Enumerados? Define? Incluye y listas de macros? ¿Cuantos de ellos? – Coincoin

+0

¿Tiene el mismo problema si usa el compilador local? Si es así, podría reconstruirlo con el perfil habilitado para ver dónde se gasta el tiempo. –

Respuesta

24

No dará todos los detalles que desee, pero intente ejecutar con los indicadores -v (detallado) y -ftime-report. Este último produce un resumen de lo que ha estado haciendo el compilador.

+0

-informe de tiempo fue la pista que necesitaba. – Schamp

3

Lo más probable es que incluya TONELADAS de incluye. Creo que -MD listará todos los archivos de inclusión en un archivo CPP dado (Eso incluye los incluidos, etc.).

+0

++ Sí. Anidado incluye y las plantillas pueden enviar el preprocesador en un paseo alegre. Al menos las inclusiones pueden manejarse con encabezados precompilados. –

2

Lo que ralentiza g ++ en general son las plantillas. Por ejemplo, a Boost le encanta usarlos. Esto significa código agradable, grandes actuaciones pero poca velocidad de compilación.

Por otro lado, 15min parece extremadamente largo. Después de una búsqueda rápida en Google, parece que es un problema común con mingw

+0

No solo mingw. He visto que Linux gcc y Visual Studio se comportan igual de mal. Por otra parte, era el tipo de paquetes fuente compilados solo una vez, por lo que los compiladores no tuvieron la oportunidad de acelerarlo. – luiscubal

+0

@Tristram Lo que era su cadena de búsqueda de google? – Schamp

1

Otro proceso para intentar es agregar "marcador de progreso" pragma s a su código para atrapar la parte del código que está tardando mucho tiempo. El compilador de Visual Studio proporciona #pragma message(), aunque no hay un pragma estándar para hacer esto.

Coloque un marcador al comienzo del código y un marcador al final del código. El marcador final puede ser #error ya que no le importa el resto del archivo fuente. Mueva los marcadores en consecuencia para atrapar la sección de código que lleva más tiempo.

Sólo un pensamiento ...

1

que haría uso de #if 0/#endif para eliminar grandes porciones del archivo de origen de la compilación. Repita con diferentes bloques de código hasta que determine con precisión qué bloque (es) son lentos. Para empezar, puede ver si su problema es #include al usar #if 0/#endif para excluir todo excepto el #include.

0

Relacionado con @Goz y @Josh_Kelley, puede obtener gcc/g ++ para escupir la fuente preprocesada (con #includes inline) usando -E. Esa es una forma de determinar qué tan grande es su fuente.

Y si el problema es el compilador en sí, es posible que pueda ejecutar el comando de compilación que lleva mucho tiempo para ver si hay un acceso a archivos en particular o una acción interna específica que lleva mucho tiempo.

0

Lo que el compilador ve es la salida del preprocesador, por lo que el tamaño de la fuente individual no es una buena medida, debe considerar la fuente y todos los archivos que incluye, y los archivos que incluyen, etc. La creación de instancias de plantillas para múltiples tipos genera código para cada tipo separado utilizado, por lo que podría terminar siendo una gran cantidad de código. Si ha utilizado ampliamente contenedores STL para muchas clases, por ejemplo.

15K líneas en una fuente es bastante, pero incluso si se divide, todo ese código aún debe compilarse; sin embargo, usar una compilación incremental puede significar que no es necesario compilar todo el tiempo. Realmente no hay necesidad de un archivo tan grande; es solo una mala práctica/diseño. Empiezo a pensar en una mejor modularización cuando un archivo llega a 500 líneas (aunque no soy dogmático al respecto)

0

Una cosa a ver durante la compilación es la cantidad de memoria que tiene su computadora libre. Si el compilador asigna tanta memoria que la computadora comienza a intercambiar, el tiempo de compilación irá muy, muy arriba.

Si ve que eso sucede, una solución fácil es instalar más RAM ... o simplemente dividir el archivo en varias partes que se pueden compilar por separado.

Cuestiones relacionadas