2011-02-01 30 views
137

C'è una risposta semplice: perché GHC è così grande?Perché GHC è così grande/grande?

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

Non sono interessato al evangelizzazione di "Perché shouldn non importa delle dimensioni se Haskell è lo strumento giusto "; questa è una domanda tecnica.

+1

Da dove prendi questo 500 MB? Il mio GHC non è mai stato così vicino. – Jacob

+0

A meno che non contiate tutte le librerie, immagino ... – Jacob

+0

Scusate, stavo andando a scaricare un pacchetto manager che include alcuni deps. L'ho aggiornato per riflettere la dimensione del download dal sito web. Ho aggiunto un riassunto Modifica ma non è stato visualizzato qui (ancora?). Penso che la domanda sia ancora valida. È grande. –

risposta

174

È un po 'sciocco davvero. Ogni biblioteca che viene fornito con GHC è previsto in non meno di 4 gusti:

  • statico
  • dinamica
  • profilate
  • GHCi

La versione GHCi è solo la versione statica collegati insieme in un singolo file .o. Le altre tre versioni hanno tutte il proprio set di file di interfaccia (file .hi). Le versioni profilate sembrano essere circa il doppio delle versioni non compilate (il che è un po 'sospetto, dovrei cercare perché).

Ricorda che GHC è di per sé una libreria, quindi stai ricevendo 4 copie di GHC. Non solo, ma il file binario di GHC è collegato staticamente, quindi sono 5 copie di GHC.

Recentemente abbiamo fatto in modo che GHCi potesse utilizzare i file statici .a. Questo ci permetterà di sbarazzarci di uno di questi sapori. A lungo termine, dovremmo collegare dinamicamente GHC, ma questo è un cambiamento più grande perché ciò implicherebbe il collegamento dinamico di default - a differenza di C, con GHC devi decidere in anticipo se vuoi collegare in modo dinamico o meno. E abbiamo bisogno di ulteriori cambiamenti (ad es. Per Cabal e il sistema dei pacchetti, tra le altre cose) prima che questo sia veramente pratico.

+15

E qui ho pensato che fosse tutta la logica che Haskell offre: valutazione pigra, tipo di inferenza, ecc. – mcandre

+4

Quindi, 113 MB/4 ~ = 28 MB, ancora più grande di OpenJRE ... Ma considera GHC è paragonabile a OpenJDK, non solo JRE , Mi fa sentire meglio. –

+0

Ora che penso che GHC usi il collegamento dinamico, forse le idee del Dr. @ Simon Marlow per la compressione dei quattro sapori sono più pratiche? Cites: 1. # 3658 (Collega dinamicamente GHCi (e usa il linker di sistema) su piattaforme che lo supportano) - GHC https://ghc.haskell.org/trac/ghc/ticket/3658; 2. # 8266 (collegamento dinamico su Mac) - GHC https://ghc.haskell.org/trac/ghc/ticket/8266; 3. # 8376 (Static Executable + GHC API (+ Dynamic Linking?) Fornisce Segfault) - GHC – AnneTheAgile

4

Ecco la ripartizione dimensione della directory sulla mia macchina:

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

Sembra che il più grande directory (123 MB) è i binari per la compilazione del compilatore stesso. I documenti pesano con una sbalorditiva 65 MB. Il terzo posto è Cabal a 41 MB.

La directory bin è 33 MB e penso che solo un sottoinsieme di ciò è tecnicamente necessario per creare applicazioni Haskell.

+6

Lasciatemi aggiungere qualcosa a questo: Se si prende solo il compilatore barebone e si spoglia tutto ciò che non è assolutamente necessario, (come costruire il compilatore non compilato, spogliato ecc.), puoi scendere a circa 5 MB. Ma prova a confrontare la dimensione del compilatore con GCC. (Modificato il commento, quindi ho dovuto cancellarlo ... mi dispiace) – fuz

8

La mia ipotesi: molti e molti collegamenti statici. Ogni biblioteca ha bisogno di collegare in modo statico le sue dipendenze, che a loro volta hanno bisogno di collegare staticamente le loro e di conseguenza. E questo è tutto compilato spesso con e senza profilazione, e anche senza profilare i binari non sono spogliati e quindi contengono molte informazioni sul debugger.

+1

Probabilmente non mi dispiacerebbe se GHC passasse a un programma completo, ricompilare quasi tutto il modello, simile a jhc. Potrebbe anche compilare più velocemente se si trattenerebbe "ld" dallo swapping. –

8

Poiché raggruppa gcc e un gruppo di librerie, tutte collegate staticamente.

Almeno su Windows.

+0

E anche su linux. – fuz

+12

no, non su linux. dipende solo da gcc. perché Windows non ha gcc nella sua "distribuzione", deve venire con ghc. – comonad

54

Probabilmente dovremmo confrontare le mele con le mele e le arance con le arance. JRE è un runtime, non un kit di sviluppo. Possiamo confrontare: la dimensione sorgente del kit di sviluppo, la dimensione del kit di sviluppo compilato e la dimensione compilata del runtime minimo.

Il pacchetto sorgente OpenJDK 7 è 82 MB (download.java.net/openjdk/jdk7) rispetto al bundle sorgente di GHC 7, che è 23 MB (haskell.org/ghc/download_ghc_7_0_1). GHC non è grande qui. Dimensioni di runtime: openjdk-6-jre-headless su Ubuntu è 77 MB non compressi rispetto a Haskell helloworld, collegato staticamente al suo runtime, che è < 1 MB. GHC non è grande qui.

Dove GHC è grande, è la dimensione del kit di sviluppo compilato:

GHC disk usage

GHC si prende 270 MB, e con tutte le librerie e le utilità che si incontrano ci vuole più di 500 MB. E sì, è molto, anche con le librerie di base e uno strumento di costruzione/gestore delle dipendenze. La piattaforma di sviluppo Java è più piccola.

GHC:

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

contro withdependencies OpenJDK:

$ 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 

Ma è ancora più di 100 MB, 26 MB, non come si scrive.

cose pesi massimi ghc6 e ghc6 prof sono:

$ 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 

Si prega di notare quanto è grande libHSghc-6.12.1_p.a. Quindi la risposta sembra essere il collegamento statico e le versioni di profilazione per ogni libreria là fuori.

+4

+1 per "openjdk-6-jre-headless su Ubuntu è 77 MB non compresso vs Haskell helloworld, collegato staticamente al suo runtime, che è <1 MB. GHC non è grande qui." – fuz

5

La risposta breve è che è perché tutti gli eseguibili sono collegati in modo statico, possono avere informazioni di debug e le librerie sono incluse in più copie. Questo è già stato detto da altri commentatori.

Il collegamento dinamico è possibile e ridurrà drasticamente le dimensioni. Ecco un esempio Hello.hs:

main = putStrLn "Hello world" 

costruisco con GHC 7.4.2 su Windows.

ghc --make -O2Hello.exe di 1105Ks

esecuzione strip su di esso lascia 630K

ghc --make -O2 -dynamic dà 40K

Spogliarello lascia appena 13K.

Le dipendenze sono 5 dll con una dimensione totale di 9,2 MB non spogliati e 5,7 MB spogliati.