为什么GHC这么大/大?


147

有一个简单的答案:GHC为什么这么大?

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

对“为什么Haskell是正确的工具,为什么我不应该关心大小”的布道不感兴趣;这是一个技术问题。


1
您从哪里获得这500MB?我的GHC远没有那么大。
雅各布

除非您数完所有库,否则我想...
Jacob Jacob

抱歉,我正在下载软件包管理器,其中包括一些部门。我对其进行了更新,以反映从网站下载的大小。我添加了“编辑摘要”,但未在此处显示(还?)。我认为问题仍然存在。好大
Christopher Done

20
也许我们应该将苹果与苹果进行比较,将桔子与橙进行比较。JRE是运行时,而不是开发人员工具包。OpenJDK 7源码包82 MB(download.java.net/openjdk/jdk7)与GHC 7源码包23 MB(haskell.org/ghc/download_ghc_7_0_1)。现在运行时:Ubuntu上的openjdk-6-jre-headless,与Haskell helloworld压缩后为77 MB,与运行时静态链接,小于1 MB。
sastanin 2011年

今天,我对2014年的尺寸感到好奇。看来这种说法仍然成立。我找到了网址:1.GHC haskell.org/ghc/download_ghc_7_8_3 ; 2.OpenJCK packages.ubuntu.com/precise/openjdk-7-jdk
AnneTheAgile

Answers:


187

真的有点傻。每个随附GHC的库都提供了至少4种口味

  • 静态的
  • 动态
  • 异形的
  • GHCi

GHCi版本只是在单个.o文件中链接在一起的静态版本。其他三个版本也都有自己的一组接口文件(.hifile)。概要文件版本似乎是未概要文件版本的两倍(这有点可疑,我应该研究为什么)。

请记住,GHC本身是一个库,因此您将获得4份GHC副本。不仅如此,GHC二进制文件本身也是静态链接的,因此这是GHC的5个副本。

我们最近做到了这一点,以便GHCi可以使用静态.a文件。这将使我们摆脱这些味道之一。从长远来看,我们应该动态链接GHC,但这是一个更大的变化,因为这将需要使动态链接成为默认链接-与C语言不同,与GHC不同,您必须预先决定是否要动态链接。在此切实可行之前,我们需要进行更多更改(例如,对Cabal和包装系统进行更改)。


16
在这里,我认为这是所有的逻辑哈斯克尔报价:懒惰的评价,类型推断等等
mcandre

4
因此,113MB / 4〜= 28MB,仍然比OpenJRE大...但是考虑到GHC与OpenJDK相当,而不仅仅是JRE,这让我感觉更好。
Earth Engine

1
现在,我认为GHC使用动态链接,也许@Simon Marlow博士关于压缩这四种风味的想法更实际吗?引用:1.#3658(在支持它的平台上动态链接GHCi(并使用系统链接器))– GHC ghc.haskell.org/trac/ghc/ticket/3658;2.#8266(在Mac上为动态链接)– GHC ghc.haskell.org/trac/ghc/ticket/8266;3.#8376(静态可执行文件+ GHC API(+动态链接?)给出了Segfault)– GHC
AnneTheAgile 2014年

56

也许我们应该将苹果与苹果进行比较,将桔子与橙进行比较。JRE是运行时,而不是开发人员工具包。我们可以比较一下:开发套件的源大小,已编译的开发套件的大小和最小运行时的已编译大小。

OpenJDK 7源包为82 MB(download.java.net/openjdk/jdk7),而GHC 7源包为23 MB(haskell.org/ghc/download_ghc_7_0_1)。GHC在这里并不大。运行时大小:Ubuntu上的openjdk-6-jre-headless未压缩,而Haskell helloworld则为77 MB,与运行时静态链接,小于1 MB。GHC在这里并不大。

GHC大的地方是编译后的开发套件的大小:

GHC磁盘使用

GHC本身占用270 MB,而所有库和实用程序加在一起则占用500 MB以上。是的,即使有了基础库和构建工具/依赖管理器,它也很多。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 MB,而不是您编写时的26 MB。

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”,它甚至可以编译得更快。
约翰L”,

8

因为它捆绑了gcc和一堆库,所以它们都是静态链接的。

至少在Windows上。


12
不,不是在Linux上。它仅取决于gcc。因为Windows在其“发行版”中没有gcc,所以它必须与ghc一起提供。
2011年

5

这是我的盒子上的目录大小明细:

https://spreadsheets.google.com/ccc?key=0AveoXImmNnZ6dDlQeHY2MmxPcEYzYkpweEtDSS1fUlE&hl=zh-CN

看起来最大的目录(123 MB)是用于编译编译器本身的二进制文件。文件重达惊人的65 MB。第三名是Cabal,容量为41 MB。

bin目录为33 MB,我认为其中只有一部分是构建Haskell应用程序的技术要求。


6
让我添加一些内容:如果仅使用准系统编译器并剥离所有绝对不需要的东西(例如构建未配置文件,剥离等的编译器),则可以减少到大约5 MB。但是,尝试将编译器的大小与GCC进行比较。(编辑了评论,所以我不得不删除它...对不起)
fuz 2011年

5

简短的答案是,因为所有可执行文件都是静态链接的,可能其中包含调试信息,并且库包含在多个副本中。其他评论者已经说过这一点。

动态链接是可能的,并且将大大减小尺寸。这是一个例子Hello.hs

main = putStrLn "Hello world"

我在Windows上使用GHC 7.4.2构建。

ghc --make -O2给出Hello.exe1105Ks

strip在其上运行可剩下630K

ghc --make -O2 -dynamic 给出40K

剥离它仅剩下13K。

它的依存关系是5个dll,它们的总大小为9.2 MB(未剥离)和5.7 MB(剥离)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.