为什么GHC这么大/大?

问题描述 投票:0回答:6

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

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

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

haskell ghc
6个回答
194
投票

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

  • 静态
  • 动态
  • 简介
  • GHCi

GHCi 版本只是在单个

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

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

我们最近做到了这一点,以便 GHCi 可以使用静态

.a
文件。这将使我们能够摆脱其中一种味道。从长远来看,我们应该动态链接 GHC,但这是一个更大的变化,因为这需要将动态链接设置为默认值 - 与 C 不同,使用 GHC 您必须预先决定是否要动态链接。在这真正实用之前,我们需要更多的改变(例如,对 Cabal 和软件包系统等)。


58
投票

也许我们应该将苹果与苹果、橙子与橙子进行比较。 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 未压缩时为 77 MB,而 Haskell helloworld 则与其运行时静态链接,即 <1 MB. GHC is not big here.

其中GHC大,是编译后的开发包的大小:

GHC disk usage

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
投票

我的猜测——大量的静态链接。每个库都需要静态链接其依赖项,而依赖项又需要静态链接它们的依赖项等等。这一切通常都是在有或没有分析的情况下编译的,即使没有分析,二进制文件也不会被剥离,因此包含大量的调试器信息。


8
投票

因为它捆绑了 gcc 和一堆库,全部静态链接。

至少在 Windows 上。


6
投票

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

动态链接是可能的,并且会显着减小大小。这是一个例子

Hello.hs

main = putStrLn "Hello world"

我在 Windows 上使用 GHC 7.4.2 进行构建。

ghc --make -O2
给出
Hello.exe
1105Ks

运行

strip
剩下 630K

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

剥掉它只剩下13K。

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


5
投票

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

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

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

bin 目录有 33 MB,我认为构建 Haskell 应用程序在技术上只需要其中的一个子集。

© www.soinside.com 2019 - 2024. All rights reserved.