Haskell:模块导入导致不必要的二进制增长

8
当我以以下方式之一将一个(大)模块导入到主模块中时:
import Mymodule
import qualified Mymodule as M
import Mymodule (MyDatatype)

与不导入该模块相比,编译后的二进制文件增长了同样巨大的数量。无论在Main模块中是否使用该模块中的任何内容,这种情况都会发生。编译器(我使用的是Debian Testing上的GHC)不应该只添加运行所需的内容到二进制文件中吗?

在我的特定情况下,我在Mymodule中有一个巨大的Map,而我在Main模块中没有使用它。选择性地导入我真正需要的东西并没有改变编译后的二进制文件的增长。

1个回答

17
就 GHC 而言,import 列表仅供可读性和避免名称冲突使用,它们并不影响链接的内容。
此外,即使您只从库中导入了几个函数,它们可能仍然内部依赖于该库的大部分,因此通常不应期望仅从可用界面中使用一些内容会看到尺寸缩小。
默认情况下,GHC 链接整个库,而不仅仅是您使用的部分;您可以通过使用 GHC 的 -split-objs 选项(或在 cabal-install 配置文件(~/.cabal/config 在 Unix 上)中添加split-objs: True)来避免这种情况,但会减慢编译速度,并且似乎不被 GHC 开发人员推荐:

-split-objs

告诉链接器将通常生成的单个对象文件拆分为多个对象文件,每个模块的顶级 Haskell 函数或类型一个。这只对库有意义,在这种情况下,它意味着与库链接的可执行文件更小,因为它们仅链接到需要的对象文件。但是,将所有部分分别组装是昂贵的,因此这比正常编译要慢。此外,库本身的大小(.a 文件)可能是原始大小到 2.5 倍。我们使用此功能构建 GHC 的库。

GHC 手册

这将省略您使用的库的未使用部分,而不管您导入了什么。
您也可能有兴趣使用共享 Haskell 库

引用ehird的话:“就GHC而言,导入列表只是为了可读性和避免名称冲突;它们根本不影响链接的内容。”这是不可能的,因为即使我只在主模块中放置“import Mymodule”而没有使用该模块中的任何内容,大小也会增长。 - Josephine
1
“Import list” 指的是在模块名称后面括号中要导入的标识符列表,而不是模块顶部的导入语句列表。 - ehird
好的,那很有道理。感谢您的澄清和非常详细的回答! - Josephine
最后一个链接已经失效。 - SwiftsNamesake

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接