99 votos

Pequeño programa Haskell compilado con GHC en binario enorme

Incluso trivial pequeños programas de Haskell se vuelven gigantescos ejecutables.

He escrito un pequeño programa, que fue compilado (con GHC) al binario con el tamaño extensible 7 MB!

¿Qué puede causar incluso un pequeño programa de Haskell para compilarse al enorme binario?

¿Si algo puedo hacer para reducir esto?

180voto

Don Stewart Puntos 94361

Vamos a ver qué sucede, trate de

  $ du -hs A
  13M   A

  $ file A
  A: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), 
     dynamically linked (uses shared libs), for GNU/Linux 2.6.27, not stripped

  $ ldd A
    linux-vdso.so.1 =>  (0x00007fff1b9ff000)
    libXrandr.so.2 => /usr/lib/libXrandr.so.2 (0x00007fb21f418000)
    libX11.so.6 => /usr/lib/libX11.so.6 (0x00007fb21f0d9000)
    libGLU.so.1 => /usr/lib/libGLU.so.1 (0x00007fb21ee6d000)
    libGL.so.1 => /usr/lib/libGL.so.1 (0x00007fb21ebf4000)
    libgmp.so.10 => /usr/lib/libgmp.so.10 (0x00007fb21e988000)
    libm.so.6 => /lib/libm.so.6 (0x00007fb21e706000)
    ...      

De la ldd de salida que GHC ha producido un vinculada de forma dinámica ejecutable, pero sólo el C bibliotecas están vinculados dinámicamente! Todas las Haskell bibliotecas se copian en pie de la letra.

A un lado, ya que este es un uso intensivo de gráficos de la aplicación, me volvería a compilar con ghc -O2

Hay dos cosas que usted puede hacer.

Pelar los símbolos

Una solución fácil: tira el binario:

$ strip A
$ du -hs A
5.8M    A

Tira de los descartes de los símbolos del archivo objeto. En general sólo se necesitaba para la depuración.

Enlazado dinámicamente Haskell bibliotecas

Más recientemente, GHC ha ganado el apoyo para la vinculación dinámica de C y Haskell bibliotecas. La mayoría de las distribuciones distribuir una versión de GHC construida para apoyar la vinculación dinámica de Haskell bibliotecas. Comparte Haskell bibliotecas pueden ser compartidas entre muchos Haskell programas, sin necesidad de copiar en el archivo ejecutable cada vez.

En el momento de la escritura de Linux y Windows son compatibles.

Para permitir que el Haskell bibliotecas enlazadas dinámicamente, se necesita compilar con -dynamic, así:

 $ ghc -O2 --make -dynamic A.hs

También, las bibliotecas quieres ser compartidos deben ser construidos con --enabled-shared:

 $ cabal install opengl --enable-shared --reinstall     
 $ cabal install glfw   --enable-shared --reinstall

Y que terminará con un mucho más pequeño ejecutable, que tiene tanto de C como de Haskell dependencias dinámicamente resuelto.

$ ghc -O2 -dynamic A.hs                         
[1 of 4] Compiling S3DM.V3          ( S3DM/V3.hs, S3DM/V3.o )
[2 of 4] Compiling S3DM.M3          ( S3DM/M3.hs, S3DM/M3.o )
[3 of 4] Compiling S3DM.X4          ( S3DM/X4.hs, S3DM/X4.o )
[4 of 4] Compiling Main             ( A.hs, A.o )
Linking A...

Y, voilà!

$ du -hs A
124K    A

que se puede quitar para hacer aún más pequeño:

$ strip A
$ du -hs A
84K A

Una pequeña pero muy ejecutable, construida a base de muchos enlazados dinámicamente C y Haskell piezas:

$ ldd A
    libHSOpenGL-2.4.0.1-ghc7.0.3.so => ...
    libHSTensor-1.0.0.1-ghc7.0.3.so => ...
    libHSStateVar-1.0.0.0-ghc7.0.3.so =>...
    libHSObjectName-1.0.0.0-ghc7.0.3.so => ...
    libHSGLURaw-1.1.0.0-ghc7.0.3.so => ...
    libHSOpenGLRaw-1.1.0.1-ghc7.0.3.so => ...
    libHSbase-4.3.1.0-ghc7.0.3.so => ...
    libHSinteger-gmp-0.2.0.3-ghc7.0.3.so => ...
    libHSghc-prim-0.2.0.0-ghc7.0.3.so => ...
    libHSrts-ghc7.0.3.so => ...
    libm.so.6 => /lib/libm.so.6 (0x00007ffa4ffd6000)
    librt.so.1 => /lib/librt.so.1 (0x00007ffa4fdce000)
    libdl.so.2 => /lib/libdl.so.2 (0x00007ffa4fbca000)
    libHSffi-ghc7.0.3.so => ...

Un punto final: incluso, en los sistemas con enlaces estáticos, puede utilizar-split-objs, para conseguir uno .o archivo por la parte superior a nivel de función, que puede reducir aún más el tamaño de estáticamente enlazados bibliotecas. Necesita GHC a ser construido con-split-objs, que algunos sistemas olvidarse de hacer.

9voto

FUZxxl Puntos 21462

Haskell utiliza vinculación estática por defecto. Esto es, los enlaces de todo a OpenGL se copian en su programa. Como son muy grandes, su programa obtiene inflado innecesariamente. Se puede resolver esto mediante el uso de vinculación dinámica, aunque no está habilitado de forma predeterminada.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X