【问题标题】:Haskell: unnecessary binary growth with module importsHaskell:模块导入导致不必要的二进制增长
【发布时间】:2012-03-01 04:06:19
【问题描述】:

当我通过以下方式之一将(大)模块导入主模块时:

import Mymodule
import qualified Mymodule as M
import Mymodule (MyDatatype)

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

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

【问题讨论】:

    标签: haskell


    【解决方案1】:

    就 GHC 而言,导入列表只是为了便于阅读和避免名称冲突;它们根本不会影响链接的内容。

    此外,即使您只从库中导入了几个函数,它们可能仍依赖于内部的大部分库,因此您不必期望仅使用某些可用接口会看到大小减小一般。

    默认情况下,GHC 链接整个库,而不仅仅是您使用的部分;您可以通过使用 GHC 的 -split-objs 选项构建库来避免这种情况(或将 split-objs: True 放入您的 cabal-install 配置文件(Unix 上为 ~/.cabal/config)),但它会减慢编译速度,并且似乎不被GHC 开发人员:

    -split-objs

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

    ——The GHC manual

    这将忽略您使用的库中未使用的部分,无论您导入什么。

    您可能也有兴趣使用shared Haskell libraries

    【讨论】:

    • 引用 ehird 的话:“就 GHC 而言,导入列表只是为了可读性和避免名称冲突;它们根本不会影响链接的内容。”这不可能是真的,因为即使我只在主模块中放置了一个“import Mymodule”而不在该模块中使用任何东西,也会发生大小的增长。
    • “导入列表”是指模块名称后面括号中要导入的标识符列表,而不是模块顶部的导入语句列表。
    • 对,这是有道理的。感谢您的澄清和非常丰富的答案!
    • 最终链接失效
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    相关资源
    最近更新 更多