Почему GHC такой большой / большой?


147

Есть простой ответ: почему GHC такой большой?

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

Не интересуется евангелизацией «Почему меня не волнует размер, если Haskell - правильный инструмент»; это технический вопрос.


1
Откуда вы получаете эти 500 МБ? Мой GHC далеко не такой большой.
Джейкоб

Если не считать всех библиотек, я полагаю ...
Джейкоб

Извините, я собирался скачать менеджер пакетов, который включает в себя некоторые deps. Я обновил его, чтобы отразить размер загрузки с веб-сайта. Я добавил редактирование, но оно не появилось здесь (пока?). Я думаю, что вопрос все еще стоит. Оно большое.
Кристофер Сделано

20
Вероятно, мы должны сравнить яблоки с яблоками и апельсины с апельсинами. JRE - это среда выполнения, а не набор разработчика. Исходный пакет OpenJDK 7, 82 МБ ( download.java.net/openjdk/jdk7 ) по сравнению с исходным пакетом GHC 7, 23 МБ ( haskell.org/ghc/download_ghc_7_0_1 ). Теперь время выполнения: openjdk-6-jre-headless в Ubuntu, 77 МБ несжатого против Helloworld Haskell, статически связанного с его временем выполнения, <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 вы должны заранее решить, собираетесь ли вы динамически связывать или нет. И нам нужно больше изменений (например, в Cabal и системе пакетов, прежде всего), прежде чем это станет действительно практичным.


16
И тут я подумал, что вся логика, которую предлагает Haskell: ленивая оценка, вывод типа и т. Д.
mcandre

4
Итак, 113 МБ / 4 ~ = 28 МБ, все еще больше, чем 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 (Статический исполняемый файл + API GHC (+ динамическое связывание?) Дает 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 МБ в несжатом состоянии по сравнению с Helloworld Haskell, статически связанным с его средой выполнения, которая составляет <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=en

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

Каталог bin составляет 33 МБ, и я думаю, что только часть из этого является технически необходимой для создания приложений на Haskell.


6
Позвольте мне добавить кое-что к этому: если вы возьмете только базовый компилятор и удалите все, что не является абсолютно необходимым (например, сборка компилятора непрофильным, раздетым и т. Д.), Вы можете уменьшить до 5 МБ. Но попробуйте сравнить размер компиляторов с GCC. (Отредактировал комментарий, поэтому мне пришлось его удалить ... извините)
fuz

5

Короткий ответ: все исполняемые файлы статически связаны, могут содержать отладочную информацию, а библиотеки включены в несколько копий. Об этом уже говорили другие комментаторы.

Динамическое связывание возможно и значительно уменьшит размер. Вот пример Hello.hs:

main = putStrLn "Hello world"

Я строю с GHC 7.4.2 на Windows.

ghc --make -O2дает Hello.exe1105Ks

Бег stripна нем оставляет 630К

ghc --make -O2 -dynamic дает 40К

Зачистка оставляет только 13K.

Это зависимости 5 dll с общим размером 9,2 МБ без зазоров и 5,7 МБ без зачистки.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.