为什么GHC这么大/大?

时间:2011-02-01 03:28:29

标签: haskell ghc

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

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

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

6 个答案:

答案 0 :(得分:182)

真的有点傻。 GHC附带的每个库都提供不少于 4种口味

  • 静态
  • 动态
  • 成型
  • GHCI

GHCi版本只是在单个.o文件中链接在一起的静态版本。其他三个版本都有自己的一组接口文件(.hi文件)。配置文件版本的大小似乎是unprofiled版本的两倍(这有点可疑,我应该研究一下为什么会这样)。

请记住 GHC本身就是一个库,所以你得到4份GHC。不仅如此,GHC二进制本身也是静态链接的,因此GHC的副本是5份。

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

答案 1 :(得分:55)

可能我们应该比较苹果和苹果,橘子和橙子。 JRE是运行时,而不是开发人员工具包。我们可以比较:开发工具包的源大小,已编译开发工具包的大小以及最小运行时的编译大小。

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

GHC很大,是编译开发工具包的大小:

GHC disk usage

GHC本身需要270 MB,并且所有库和实用程序组合在一起需要超过500 MB。是的,它很多,即使使用基础库和构建工具/依赖管理器也是如此。 Java开发平台较小。

GHC:

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

反对OpenJDK withdependencies:

$ 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有多大。所以答案似乎是每个库的静态链接和分析版本。

答案 2 :(得分:9)

我的猜测 - 很多很多静态链接。每个库都需要静态链接其依赖关系,这依赖关系需要静态链接它们和软件。这些都是经常编译的,无论是否进行分析,即使没有分析二进制文件也不会被剥离,因此需要保存大量的调试器信息。

答案 3 :(得分:8)

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

至少在Windows上。

答案 4 :(得分:5)

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

动态链接是可能的,并会大大减小尺寸。以下是Hello.hs示例:

main = putStrLn "Hello world"

我在Windows上使用GHC 7.4.2构建。

ghc --make -O2提供了1105K的Hello.exe

在其上运行strip会留下630K

ghc --make -O2 -dynamic提供40K

剥离它只剩下13K。

它的依赖是5个dll,总大小为9.2 MB未剥离和5.7 MB剥离。

答案 5 :(得分:4)

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

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

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

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