at5*_*321 5 linker linkage rust rust-cargo
我是 Rust 的新手,我试图理解为什么 Rust 不能构建得更快。我专门讨论最常见的情况,我对我的一个源文件做了一个小改动,然后我需要等待几秒钟cargo build才能完成它的工作。即使我的应用程序代码非常小,例如,如果我添加对 MySQL 和 Rocket 的依赖项,这两个 crate 也会附带它们自己的依赖项,显然这就是构建过程显着变慢的原因。显然,“慢”的意思是非常主观的,但是如果我需要等待 5-10 秒才能完成一天一百次的事情,我想知道为什么需要这样,我是否遗漏了什么.
在我看来,Cargo 并没有浪费太多时间来检查它是否需要重新编译这 200-300 个(子)依赖项中的任何一个,但需要这么长时间的是链接器。我试图了解链接器无法以某种方式优化该过程是否存在客观原因。例如,是否有可能以某种方式将整个 MySQL 和 Rocket 依赖项构建和缓存到两个更大的库中,并避免每次都执行所有这些工作?即使以二进制文件中的一些代码重复为代价。
顺便说一句,我尝试了 LLD 链接器(我使用的是 Ubuntu),它在一定程度上加快了速度,但它似乎仍然受到大量子依赖项的严重影响。
例如,是否有可能以某种方式构建并缓存整个 MySQL 和 Rocket 依赖项到两个更大的库中,并避免每次都执行所有这些工作?
我们可以将静态编译的 MySQL/Rocket 库链接到我们的 Rust 项目中(通过 C++ 包装器)。我们来试试吧。
build.rs文件,我们将使用 cxx crate 将 MySQL 和 Rocket 依赖项编译成静态库。extern crate cxx_build;
fn main() {
cxx_build::bridge("src/wrapper.rs")
.file("src/mysql_wrapper.cpp")
.file("src/rocket_wrapper.cpp")
.flag("-std=c++17")
.compile("mysql_wrapper", "rocket_wrapper");
}
Run Code Online (Sandbox Code Playgroud)
wrapper.rs、mysql_wrapper.cpp和的包装文件rocket_wrapper.cpp。// mysql_wrapper.cpp
#include <mysql.h>
void init_mysql() {
mysql_library_init(0, NULL, NULL);
}
void cleanup_mysql() {
mysql_library_end();
}
Run Code Online (Sandbox Code Playgroud)
// rocket_wrapper.cpp
#include <rocket.h>
#include <iostream>
extern "C" {
void init_rocket() {
std::vector<std::string> args = { "myapp", "--port=8000" };
rocket::config::Config config;
config.from_args(args);
rocket::ignite(config);
}
void stop_rocket() {
rocket::shutdown();
}
}
Run Code Online (Sandbox Code Playgroud)
// wrapper.rs
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
fn init_mysql();
fn cleanup_mysql();
fn init_rocket();
fn stop_rocket();
}
}
Run Code Online (Sandbox Code Playgroud)
main.rs) 以链接静态库,而不是直接链接 MySQL 和 Rocket 依赖项。// main.rs
mod ffi {
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
fn init_mysql();
fn cleanup_mysql();
fn init_rocket();
fn stop_rocket();
}
}
}
fn main() {
unsafe {
ffi::init_mysql();
}
// Usage of MySQL lib here
unsafe {
ffi::cleanup_mysql();
}
unsafe {
ffi::init_rocket();
}
// Usage of Rocket f/work here
unsafe {
ffi::stop_rocket();
}
}
Run Code Online (Sandbox Code Playgroud)
cargo build
Run Code Online (Sandbox Code Playgroud)
就是这个。这将包括 mysql 和 Rocket 作为静态库,并且不会Cargo.toml作为直接依赖项进行链接。我不确定我们是否会获得真正显着的收益,它可能取决于项目结构,并且只有在您不打算更新这些依赖项的版本时才应该使用。我可能需要进行性能检查,但稍后。
| 归档时间: |
|
| 查看次数: |
176 次 |
| 最近记录: |