设置opt-level内部库与 rust

vfwfrxfs  于 6个月前  发布在  其他
关注(0)|答案(1)|浏览(51)

在rust版本中,默认为opt-level = 3。这在很多情况下都不是预期的行为。根据库的不同,这会显著增加二进制文件的大小,同时可能比opt-level = 2慢。我发现了一个选项,可以使用库覆盖最终项目的这些默认值:

[profile.release.package.my_package]
opt-level = 2

字符串
在许多情况下,库作者最清楚默认情况下应该在哪个优化级别构建库,因此库本身能够覆盖此默认值是有意义的。我尝试用途:

[profile.release]
opt-level = 2


Cargo.toml库中,但这没有任何效果。有没有什么方法可以让它工作,或者这是只有最终项目才能做的事情?有没有一种方法可以实现更细粒度的优化级别,例如每个文件,或者这需要每个文件都放在一个单独的库中?

nukf8bse

nukf8bse1#

这是不可能的
opt-level是Cargo profile的一部分,它控制编译器的行为。配置文件是在构建时从默认配置文件、任何最终用户自定义配置文件以及用于执行构建的Cargo.toml设置的任何覆盖中选择的。您在库的Cargo.toml中设置的覆盖仅影响属于库的二进制文件。
如果您选择分发动态库,则可以为分布式共享对象/DLL设置opt-level,但这会阻止库的函数内联到用户代码中。
你最好的选择(关于opt-level)是建议用户(在文档,README或其他地方)opt-level = 3会产生代码膨胀,并建议使用opt-level = 2。一个提供类似建议的流行项目是Bevy,它建议设置opt-level以使调试构建更快。
根据库的不同,这可能会显著增加二进制文件的大小,同时可能比opt-level = 2慢。
如果您担心最终的二进制文件大小,还有其他方法可以减少生成的代码量。您可能会建议用户启用LTO,这可以以额外的编译时间为代价减少代码大小。
另一个常见的罪魁祸首是泛型,特别是非常长的函数的单体化。如果性能允许,您可以选择将泛型函数作为调用公共非泛型函数的存根。例如:

fn foo<S: AsRef<str>>(input: S) {
    // Some long, complex function.
    // ...
}

字符串
代码是为每一个调用foo()的不同类型生成的(&strStringCow<str>等)。你可以通过强制所有这样的调用遵循相同的路径来减少重复单态化的成本:

fn foo<S: AsRef<str>>(input: S) {
    foo_str(input.as_ref());
}

fn foo_str(input: &str) {
    // Complex logic goes here.
    // ...
}


这为foo()的每个单态化生成很少的代码,并且所有生成的函数都调用共享代码路径,从而导致更小的二进制文件和可能更好的指令缓存使用率。当然,YMMV;首先分析并关注导致最膨胀的函数。

相关问题