有一个简单的答案吗:为什么GHC这么大?
- OCaml: 2MB
- Python: 15MB
- SBCL: 9MB
- OpenJRE - 26MB
- GHC: 113MB
不关心"如果Haskell是正确的工具,我为什么不应该在意大小"的鼓吹,这是一个技术问题。
有一个简单的答案吗:为什么GHC这么大?
不关心"如果Haskell是正确的工具,我为什么不应该在意大小"的鼓吹,这是一个技术问题。
这有点傻。 GHC提供的每个库都至少有四种版本:
GHCi版本只是将静态版本链接在一起形成单个.o
文件。其他三个版本都有自己的接口文件(.hi
文件)。进行性能分析的版本似乎比未经过性能分析的版本大约两倍(这有点可疑,我应该研究一下为什么)。
请记住,GHC本身是一个库,因此您会得到4份GHC副本。不仅如此,GHC二进制文件本身也是静态链接的,这就是5份GHC副本。
我们最近使得GHCi可以使用静态的.a
文件。这将允许我们摆脱其中的一个版本。从长远来看,我们应该动态地链接GHC,但这需要更大的改变,因为这将意味着动态链接将成为默认选项——与C语言不同,对于GHC,你必须预先决定是否要进行动态链接。我们还需要进行更多的改变(例如在Cabal和包系统等方面),才能让这变得真正实用。
我们应该将苹果与苹果,橙子与橙子进行比较。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也不算大。
GHC体积庞大的地方在于编译后的开发工具包大小:
GHC本身占用270 MB,加上所有一起提供的库和实用程序,则超过500 MB。是的,它很大,即使带有基础库和构建工具/依赖管理器。Java开发平台则更小。
GHC:
$ aptitude show ghc6 | grep Size
Uncompressed Size: 388M
使用withdependencies选项来针对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
有多大。因此,似乎对于每个库都有静态链接和分析版本的答案。
因为它捆绑了gcc和一堆库,全部都是静态链接的。
至少在Windows上是这样。
rpm
但没有yum
,所以没有简单的方法来获取依赖项,因此每个应用程序都像Docker/Snap一样捆绑了所有依赖项。此外,虽然存在MSI依赖项,但由于MSI的过度设计,它们很少被使用。当新的打包技术最终被采用时(可能是AppX的继任者),这种情况可能会改变。 - nponeccop简短回答是因为所有可执行文件都是静态链接的,可能包含调试信息,并且库被包含在多个副本中。其他评论者已经说过这一点。
动态链接是可能的,它将大大减小体积。以下是一个例子Hello.hs
:
main = putStrLn "Hello world"
我在Windows上使用GHC 7.4.2进行构建。
ghc --make -O2
命令生成大小为1105K的Hello.exe
文件。
对其运行strip
命令后,大小缩小至630K。
ghc --make -O2 -dynamic
命令生成大小为40K的文件。
对其运行strip
命令后,大小仅剩下13K。
它依赖于5个dll文件,未压缩时总大小为9.2 MB,压缩后大小为5.7 MB。
这是我的计算机上目录大小的统计:
https://spreadsheets.google.com/ccc?key=0AveoXImmNnZ6dDlQeHY2MmxPcEYzYkpweEtDSS1fUlE&hl=en
看起来最大的目录(123 MB)是编译编译器本身的二进制文件。文档有惊人的65 MB。第三名是41 MB的Cabal。