Чому GHC настільки великий / великий?


147

Є проста відповідь: Чому GHC настільки великий?

  • OCaml: 2 Мб
  • Пітон: 15 Мб
  • SBCL: 9 Мб
  • OpenJRE - 26 Мб
  • GHC: 113 Мб

Не цікавиться євангелізацією "Чому я не повинен дбати про розмір, якщо Haskell - це правильний інструмент"; це технічне питання.


1
Звідки ви берете цей 500MB? Мій GHC ніде не такий великий.
Яків

Якщо ви не порахуєте всі бібліотеки, я думаю ...
Яків

Вибачте, я не збирався завантажувати менеджер пакунків, який включає деякі програми. Я оновив його, щоб відобразити розмір завантаження з веб-сайту. Я додав конспект редагування, але він тут не з’явився (поки що?). Я думаю, питання все ще стоїть. Воно велике.
Крістофер зробив

20
Напевно, нам слід порівняти яблука з яблуками, а апельсини - з апельсинами. JRE - це час виконання, а не комплект розробників. OpenJDK 7 джерела розшарування, 82 MB ( download.java.net/openjdk/jdk7 ) проти GHC 7 вихідного пучка, 23 МБ ( haskell.org/ghc/download_ghc_7_0_1 ). Тепер час виконання: openjdk-6-jre-headless на Ubuntu, 77 Мб, нестиснений проти Haskell helloworld, статично пов'язаний з його часом виконання, <1 Мб.
зустріч

Сьогодні мені було цікаво про розміри зараз 2014 року. Здається, аргумент все ще дотримується. Я знайшов URL-адреси: 1.GHC haskell.org/ghc/download_ghc_7_8_3 ; 2.OpenJCK packages.ubuntu.com/precise/openjdk-7-jdk
AnneTheAgile

Відповіді:


187

Це справді трохи нерозумно. Кожна бібліотека, що постачається з GHC, надається не менше ніж у 4 смаках :

  • статичний
  • динамічний
  • профільований
  • GHCi

Версія GHCi - це лише статична версія, пов'язана разом в одному .oфайлі. У всіх трьох інших версіях також є свій набір файлів інтерфейсу ( .hiфайлів). Профільовані версії, схоже, приблизно вдвічі перевищують непрофільовані версії (що трохи підозріло, я мушу розглянути, чому це так).

Пам'ятайте, що GHC сама по собі є бібліотекою , тому ви отримуєте 4 копії GHC. Не тільки це, але і сам бінарний GHC є статично пов'язаним, так що це 5 копій GHC.

Нещодавно ми зробили це, щоб GHCi могли використовувати статичні .aфайли. Це дозволить нам позбутися одного з цих ароматів. Більш тривалий термін, ми повинні динамічно пов'язувати GHC, але це більша зміна, оскільки це спричинить динамічне пов'язування за замовчуванням - на відміну від C, з GHC ви повинні вирішити попереду, чи будете ви динамічно зв’язуватися чи ні. І нам потрібно більше змін (наприклад, до Кабалу та пакетної системи, серед іншого), перш ніж це буде реально практичним.


16
І тут я подумав, що це вся логіка, яку пропонує Haskell: лінива оцінка, тип висновку тощо
mcandre

4
Отже, 113MB / 4 ~ = 28MB, все ще більший, ніж OpenJRE ... Але врахуйте, що GHC можна порівняти з OpenJDK, а не лише JRE, це змушує мене відчувати себе краще.
Земляний двигун

1
Тепер, коли я думаю, що GHC використовує динамічні зв'язки, можливо, ідеї доктора @Simon Marlow щодо стиснення чотирьох ароматів є більш практичними? Cites: 1. # 3658 (Динамічно посилайтеся на GHCi (та використовуйте системний лінкер) на платформах, які його підтримують) - GHC ghc.haskell.org/trac/ghc/ticket/3658 ; 2. # 8266 (Динамічне посилання на Mac) - GHC ghc.haskell.org/trac/ghc/ticket/8266 ; 3. # 8376 (Static Executable + GHC API (+ Dynamic Linking?) Дає Segfault) - GHC
AnneTheAgile

56

Напевно, нам слід порівняти яблука з яблуками, а апельсини - з апельсинами. JRE - це час виконання, а не комплект розробників. Ми можемо порівняти: розмір джерела набору для розробки, розмір складеного набору розробок та розмір складеного мінімального часу виконання.

Вихідний пакет OpenJDK 7 становить 82 Мб (download.java.net/openjdk/jdk7) проти вихідного пакета GHC 7, що становить 23 Мб (haskell.org/ghc/download_ghc_7_0_1). GHC тут не великий. Розмір часу: openjdk-6-jre-headless на Ubuntu становить 77 Мб, нестиснений проти Haskell helloworld, статично пов'язаний з його часом виконання, який становить <1 Мб. GHC тут не великий.

Там, де GHC великий, - це розмір складеного набору для розробки:

Використання GHC диска

Сам GHC займає 270 МБ, а з усіма бібліотеками та утилітами, які поєднуються, він займає понад 500 Мб. І так, це багато, навіть з базовими бібліотеками та інструментом збирання / менеджера залежностей. Платформа для розробки Java менша.

GHC:

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

проти 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

Але це все-таки понад 100 Мб, а не 26 Мб, як ви пишете.

Важкі речі у ghc6 та ghc6-prof є:

$ 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

Зверніть увагу, наскільки вона велика libHSghc-6.12.1_p.a. Таким чином, відповідь здається статичним зв’язком і профілем версій для кожної бібліотеки там.


9

Моя здогадка - багато-багато статичних зв'язків. Кожній бібліотеці необхідно статично пов’язати свої залежності, які, в свою чергу, повинні статично пов’язати їхні і супротивні. І все це збирається часто як із профілюванням, так і без нього, і навіть без профілювання бінарні файли не знімаються, і тому зберігається багато налагоджувальної інформації.


2
Я, мабуть, не заперечував би, якби GHC перейшов на цілу програму, перекомпілював майже всі моделі, схожі на jhc. Він може навіть компілюватись швидше, якщо це не дозволить "ld" від заміни.
Джон Л

8

Оскільки він поєднує gcc та купу бібліотек, всі статично пов'язані.

Принаймні, на Windows.


12
ні, не на Linux. це залежить лише від gcc. тому що Windows не має gcc у своєму "розповсюдженні", він повинен прийти з ghc.
comonad

5

Ось розбивка на розмір каталогів у моєму полі

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

Схоже, найбільший каталог (123 МБ) - це двійкові файли для компіляції самого компілятора. Документи важать вражаючі 65 МБ. Третє місце - Кабал у 41 МБ.

Каталог бін становить 33 Мб, і я думаю, що для створення програм Haskell технічно потрібно лише підмножина.


6
Дозвольте додати щось до цього: якщо ви берете лише компілятор barebone і зніміть все, що не є абсолютно необхідним (наприклад, побудова компілятора непрофільованого, знятого тощо), ви можете знизитись до приблизно 5 Мб. Але спробуйте порівняти розмір компіляторів з GCC. (Відредагував коментар, тому мені довелося його видалити ... вибачте)
fuz

5

Коротка відповідь полягає в тому, що всі виконувані файли статично пов'язані, можливо, в них є інформація про налагодження, і бібліотеки включаються в декількох копіях. Про це вже говорили інші коментатори.

Можливе динамічне зв’язування та значно зменшить розмір. Ось приклад Hello.hs:

main = putStrLn "Hello world"

Я будую з GHC 7.4.2 на Windows.

ghc --make -O2дає Hello.exe1105Ks

Біг stripна ньому залишає 630K

ghc --make -O2 -dynamic дає 40К

Знімаючи його, залишається всього 13К.

Її залежності - це 5 dll загальним розміром 9,2 Мб, роздягнуті та 5,7 Мб.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.