¿Por qué es GHC tan grande / grande?

147

¿Hay una respuesta simple: por qué es tan grande el GHC?

  • OCaml: 2MB
  • Python: 15 MB
  • SBCL: 9MB
  • OpenJRE - 26MB
  • GHC: 113MB

No me interesa el evangelismo de "Por qué no debería importarme el tamaño si Haskell es la herramienta adecuada"; Esta es una pregunta técnica.

Christopher Done
fuente
1
¿De dónde sacas estos 500 MB? Mi GHC no está tan cerca de ese tamaño.
Jacob
A menos que cuentes todas las bibliotecas, supongo ...
Jacob
Lo siento, estaba descargando un administrador de paquetes que incluye algunos deps. Lo actualicé para reflejar el tamaño de descarga del sitio web. Agregué un resumen de edición pero no apareció aquí (¿todavía?). Creo que la pregunta sigue en pie. Es grande.
Christopher Hecho
20
Probablemente deberíamos comparar manzanas con manzanas y naranjas con naranjas. JRE es un tiempo de ejecución, no un kit para desarrolladores. Paquete fuente OpenJDK 7, 82 MB ( download.java.net/openjdk/jdk7 ) vs paquete fuente GHC 7, 23 MB ( haskell.org/ghc/download_ghc_7_0_1 ). Ahora tiempo de ejecución: openjdk-6-jre-headless en Ubuntu, 77 MB sin comprimir frente a Haskell helloworld, estáticamente vinculado con su tiempo de ejecución, <1 MB.
Sastanin 01 de
Hoy tenía curiosidad sobre los tamaños ahora 2014. Parece que el argumento aún se mantiene. Encontré URLS: 1.GHC haskell.org/ghc/download_ghc_7_8_3 ; 2.OpenJCK packages.ubuntu.com/precise/openjdk-7-jdk
AnneTheAgile

Respuestas:

187

Es un poco tonto realmente. Cada biblioteca que viene con GHC se proporciona en no menos de 4 sabores :

  • estático
  • dinámica
  • perfilado
  • GHCi

La versión GHCi es solo la versión estática vinculada en un solo .oarchivo. Las otras tres versiones también tienen su propio conjunto de archivos de interfaz ( .hiarchivos). Las versiones perfiladas parecen tener aproximadamente el doble del tamaño de las versiones sin perfil (lo cual es un poco sospechoso, debería investigar por qué es así).

Recuerde que GHC en sí es una biblioteca , por lo que obtendrá 4 copias de GHC. No solo eso, sino que el binario GHC en sí está estáticamente vinculado, por lo que son 5 copias de GHC.

Recientemente lo hicimos para que GHCi pudiera usar los .aarchivos estáticos . Eso nos permitirá deshacernos de uno de estos sabores. A largo plazo, deberíamos vincular dinámicamente GHC, pero ese es un cambio mayor porque eso implicaría hacer que la vinculación dinámica sea la predeterminada: a diferencia de C, con GHC debe decidir por adelantado si va a vincular dinámicamente o no. Y necesitamos más cambios (por ejemplo, Cabal y el sistema de paquetes, entre otras cosas) antes de que esto sea realmente práctico.

Simon Marlow
fuente
16
Y yo que pensaba que era toda la lógica que ofrece Haskell: evaluación perezosa, la inferencia de tipos, etc.
mcandre
44
Entonces, 113MB / 4 ~ = 28MB, aún más grande que OpenJRE ... Pero considere que GHC es comparable a OpenJDK, no solo JRE, me hace sentir mejor.
Earth Engine
1
Ahora que creo que GHC usa la vinculación dinámica, ¿quizás las ideas del Dr. @ Simon Marlow para la compresión de los cuatro sabores son más prácticas? Citas: 1. # 3658 (Vincular dinámicamente GHCi (y usar el vinculador del sistema) en plataformas que lo admiten) - GHC ghc.haskell.org/trac/ghc/ticket/3658 ; 2. # 8266 (Enlace dinámico en Mac) - GHC ghc.haskell.org/trac/ghc/ticket/8266 ; 3. # 8376 (Ejecutable estático + API de GHC (+ ¿Enlace dinámico?) Da Segfault) - GHC
AnneTheAgile
56

Probablemente deberíamos comparar manzanas con manzanas y naranjas con naranjas. JRE es un tiempo de ejecución, no un kit para desarrolladores. Podemos comparar: el tamaño de origen del kit de desarrollo, el tamaño del kit de desarrollo compilado y el tamaño compilado del tiempo de ejecución mínimo.

El paquete fuente OpenJDK 7 es de 82 MB (download.java.net/openjdk/jdk7) frente al paquete fuente GHC 7, que es de 23 MB (haskell.org/ghc/download_ghc_7_0_1). GHC no es grande aquí. Tamaño de tiempo de ejecución: openjdk-6-jre-headless en Ubuntu es de 77 MB sin comprimir frente a Haskell helloworld, vinculado estáticamente con su tiempo de ejecución, que es <1 MB. GHC no es grande aquí.

Donde GHC es grande, es el tamaño del kit de desarrollo compilado:

Uso de disco GHC

GHC en sí ocupa 270 MB, y con todas las bibliotecas y utilidades que se unen, ocupa más de 500 MB. Y sí, es mucho, incluso con bibliotecas base y una herramienta de compilación / administrador de dependencias. La plataforma de desarrollo de Java es más pequeña.

GHC:

$ aptitude show ghc6 | grep Size
Uncompressed Size: 388M

contra OpenJDK con dependencias:

$ aptitude show openjdk-6-jdk openjdk-6-jre openjdk-6-jre-headless ant maven2 ivy | grep Size
Uncompressed Size: 34.9M
Uncompressed Size: 905k
Uncompressed Size: 77.3M
Uncompressed Size: 1,585k
Uncompressed Size: 3,736k
Uncompressed Size: 991k

Pero todavía tiene más de 100 MB, no 26 MB mientras escribe.

Las cosas pesadas en ghc6 y ghc6-prof son:

$ dpkg -L ghc6 | grep '\.a$' | xargs ls -1ks | sort -k 1 -n -r | head -3
57048 /usr/lib/ghc-6.12.1/ghc-6.12.1/libHSghc-6.12.1.a
22668 /usr/lib/ghc-6.12.1/Cabal-1.8.0.2/libHSCabal-1.8.0.2.a
21468 /usr/lib/ghc-6.12.1/base-4.2.0.0/libHSbase-4.2.0.0.a
$ dpkg -L ghc6-prof | grep '\.a$' | xargs ls -1ks | sort -k 1 -n -r | head -3
112596 /usr/lib/ghc-6.12.1/ghc-6.12.1/libHSghc-6.12.1_p.a
 33536 /usr/lib/ghc-6.12.1/Cabal-1.8.0.2/libHSCabal-1.8.0.2_p.a
 31724 /usr/lib/ghc-6.12.1/base-4.2.0.0/libHSbase-4.2.0.0_p.a

Tenga en cuenta lo grande que es libHSghc-6.12.1_p.a. Por lo tanto, la respuesta parece ser la vinculación estática y las versiones de creación de perfiles para todas las bibliotecas disponibles.

sastanin
fuente
9

Mi suposición: montones y montones de enlaces estáticos. Cada biblioteca necesita vincular estáticamente sus dependencias, que a su vez necesitan vincular estáticamente las suyas y las soforth. Y todo esto se compila a menudo con y sin perfiles, e incluso sin perfiles, los binarios no se eliminan y, por lo tanto, contienen mucha información del depurador.

sclv
fuente
2
Probablemente no me importaría si GHC cambiara a un programa completo, recompile casi todo el modelo, similar a jhc. Incluso podría compilarse más rápido si evitara que 'ld' se intercambie.
John L
8

Porque agrupa gcc y un montón de bibliotecas, todas vinculadas estáticamente.

Al menos en Windows.

Marko
fuente
12
No, no en Linux. solo depende de gcc. como windows no tiene gcc en su "distribución", tiene que venir con ghc.
comonad
5

Aquí está el desglose del tamaño del directorio en mi caja:

https://spreadsheets.google.com/ccc?key=0AveoXImmNnZ6dDlQeHY2MmxPcEYzYkpweEtDSS1fUlE&hl=en

Parece que el directorio más grande (123 MB) son los binarios para compilar el compilador. Los documentos pesan unos asombrosos 65 MB. El tercer lugar es Cabal con 41 MB.

El directorio bin es de 33 MB, y creo que solo un subconjunto de eso es lo que técnicamente se requiere para construir aplicaciones Haskell.

Jacob
fuente
66
Permítanme agregar algo a esto: si solo toma el compilador barebone y elimina cualquier cosa que no sea absolutamente necesaria (como compilar el compilador sin perfil, despojado, etc.), puede bajar a aproximadamente 5 MB. Pero intente comparar el tamaño de los compiladores con GCC. (Edité el comentario, así que tuve que eliminarlo ... lo siento)
fuz
5

La respuesta breve es que es porque todos los ejecutables están vinculados estáticamente, pueden tener información de depuración y las bibliotecas están incluidas en varias copias. Esto ya lo han dicho otros comentaristas.

La vinculación dinámica es posible y reducirá drásticamente el tamaño. Aquí hay un ejemplo Hello.hs:

main = putStrLn "Hello world"

Construyo con GHC 7.4.2 en Windows.

ghc --make -O2da Hello.exede 1105Ks

Correr stripen él deja 630K

ghc --make -O2 -dynamic da 40K

Pelarlo deja solo 13K.

Sus dependencias son 5 dlls con un tamaño total de 9.2 MB sin tirar y 5.7 MB sin tirar.

nponeccop
fuente