无法访问的Rust代码是否被编译并包含在最终的二进制文件中?

pu82cl6c  于 2023-01-26  发布在  其他
关注(0)|答案(1)|浏览(98)

我对Rust和一般的编译语言都是新手。我作为依赖项包含的每个crate最终都会在二进制文件中结束吗,即使我没有使用那个crate中的任何一个函数?
如果我只使用一个大型库中的一个函数,那么整个库都会被编译,还是只编译那个函数以及它所需要的任何函数?
在Javascript中,有树摇动,以消除死代码,而没有任何缺点,除了额外的时间摇动树。是否存在等效的Rust?毕竟,Clippy擅长于发现死代码,所以它应该能够只是不编译和包括在二进制文件中。
我知道使用opt = 'z'可以优化二进制大小,但代价是执行速度变慢。

ajsxfq5m

ajsxfq5m1#

快速浏览一下之后,rustc确实在IR级别上做了一些死代码消除。

但我想大部分里程都是LLVM的。

  • https://llvm.org/docs/Passes.html#dce-dead-code-elimination
  • https://llvm.org/docs/Passes.html#deadargelim-dead-argument-elimination
  • https://llvm.org/docs/Passes.html#deadtypeelim-dead-type-elimination
  • https://llvm.org/docs/Passes.html#die-dead-instruction-elimination
  • https://llvm.org/docs/Passes.html#dse-dead-store-elimination
  • https://llvm.org/docs/Passes.html#globaldce-dead-global-elimination
  • https://llvm.org/docs/Passes.html#loop-deletion-delete-dead-loops

最后,链接器(假设你打开了lto)也会删除它发现死了的代码。
重要的是,无论是rust还是LLVM都不能保证一段死代码会被删除。2即使在调试版本中,像未调用函数这样的小问题也可能被删除。请记住,在更高的优化级别上会进行大量的内联和转换,因此在源代码中看起来没有死的东西最终可能会在最终的构建和removed.如果你真的为二进制文件的大小而烦恼,想知道是否删除了某些东西是一种效率低下的方法。下面的链接是一个很好的资源,它提到了你为获得更小的二进制文件所做的权衡。
https://github.com/johnthagen/min-sized-rust
其中的重点包括:

[profile.release]
strip = true
opt-level = "z"
lto = true
codegen-units = 1

所有这些都有成本(它们不是默认的是有原因的!),我会衡量编译时间,二进制大小,希望在应用每一个之前和之后做一些分析,看看是否值得。链接到一些改变行为的东西,比如panic = "abort"
当然,cargo-bloat不可能不被提及--它将有助于发现您提到的问题,比如有一个库,您可以使用单个函数来避免引入大量代码。

相关问题