rm pub_visibility -rf
cargo new pub_visibility -q
cd pub_visibility/
cargo_build() {
cargo b --release -q
echo "before strip:"
ls -lh target/release/pub_visibility
strip target/release/pub_visibility
echo "after strip:"
ls -lh target/release/pub_visibility
echo ""
}
cargo_build
echo "add tokio: full features"
cargo add tokio -F full -q
cat src/main.rs
cargo_build
cat > src/main.rs << EOF
pub use tokio::*;
pub mod never_used {
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;
use tokio::runtime::Runtime;
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create the runtime
let rt = Runtime::new()?;
// Spawn the root task
rt.block_on(async {
let listener = TcpListener::bind("127.0.0.1:8080").await?;
loop {
let (mut socket, _) = listener.accept().await?;
tokio::spawn(async move {
let mut buf = [0; 1024];
// In a loop, read data from the socket and write the data back.
loop {
let n = match socket.read(&mut buf).await {
// socket closed
Ok(n) if n == 0 => return,
Ok(n) => n,
Err(e) => {
println!("failed to read from socket; err = {:?}", e);
return;
}
};
// Write the data back
if let Err(e) = socket.write_all(&buf[0..n]).await {
println!("failed to write to socket; err = {:?}", e);
return;
}
}
});
}
})
}
}
fn main() {}
EOF
cat src/main.rs
cargo_build
before strip:
-rwxr-xr-x 2 root root 3.9M Jul 26 13:33 target/release/pub_visibility
after strip:
-rwxr-xr-x 2 root root 319K Jul 26 13:33 target/release/pub_visibility
add tokio: full features
fn main() {
println!("Hello, world!");
}
before strip:
-rwxr-xr-x 2 root root 3.9M Jul 26 13:34 target/release/pub_visibility
after strip:
-rwxr-xr-x 2 root root 319K Jul 26 13:34 target/release/pub_visibility
pub use tokio::*;
...
before strip:
-rwxr-xr-x 2 root root 3.9M Jul 26 13:34 target/release/pub_visibility
after strip:
-rwxr-xr-x 2 root root 311K Jul 26 13:34 target/release/pub_visibility
warning: unused `Result` that must be used
--> src/main.rs:47:5
|
47 | never_used::main();
| ^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_must_use)]` on by default
= note: this `Result` may be an `Err` variant, which should be handled
before strip:
-rwxr-xr-x 2 root root 4.6M Jul 26 14:39 target/release/pub_visibility
after strip:
-rwxr-xr-x 2 root root 739K Jul 26 14:39 target/release/pub_visibility
rm pub_visibility -rf
cargo new pub_visibility -q
cd pub_visibility/
cargo_build() {
cargo b --release -q
echo "before strip:"
ls -lh target/release/pub_visibility
strip target/release/pub_visibility
echo "after strip:"
ls -lh target/release/pub_visibility
echo ""
}
cargo_build
echo "add tokio: full features"
cargo add tokio -F full -q
cat src/main.rs
cargo_build
cat > src/main.rs << EOF
pub use tokio::*;
pub mod never_used {
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;
use tokio::runtime::Runtime;
pub fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create the runtime
let rt = Runtime::new()?;
// Spawn the root task
rt.block_on(async {
let listener = TcpListener::bind("127.0.0.1:8080").await?;
loop {
let (mut socket, _) = listener.accept().await?;
tokio::spawn(async move {
let mut buf = [0; 1024];
// In a loop, read data from the socket and write the data back.
loop {
let n = match socket.read(&mut buf).await {
// socket closed
Ok(n) if n == 0 => return,
Ok(n) => n,
Err(e) => {
println!("failed to read from socket; err = {:?}", e);
return;
}
};
// Write the data back
if let Err(e) = socket.write_all(&buf[0..n]).await {
println!("failed to write to socket; err = {:?}", e);
return;
}
}
});
}
})
}
}
fn main() {}
EOF
cat src/main.rs
cargo_build
before strip:
-rwxr-xr-x 2 root root 3.9M Jul 26 13:33 target/release/pub_visibility
after strip:
-rwxr-xr-x 2 root root 319K Jul 26 13:33 target/release/pub_visibility
add tokio: full features
fn main() {
println!("Hello, world!");
}
before strip:
-rwxr-xr-x 2 root root 3.9M Jul 26 13:34 target/release/pub_visibility
after strip:
-rwxr-xr-x 2 root root 319K Jul 26 13:34 target/release/pub_visibility
pub use tokio::*;
...
before strip:
-rwxr-xr-x 2 root root 3.9M Jul 26 13:34 target/release/pub_visibility
after strip:
-rwxr-xr-x 2 root root 311K Jul 26 13:34 target/release/pub_visibility
评论区
写评论Rust 不是 Zero Cost Abstraction 么?
我认为不会影响性能,更多是影响代码架构。
准确地说是没有链接进去,编译和链接是两个不同的过程。
--
👇
苦瓜小仔: 不会。
一个粗略的观察是,Rust 并不会把未实际调用的东西编译进二进制文件,所以你的程序性能不会受到 pub/private 的影响:
增加了理解, 感谢前辈! (发帖的时候就有这句话, 不是后加的)
--
👇
苦瓜小仔:
这句话你是后来加的吧。
你可以测试
https://godbolt.org/z/11ovz9b5h
这句话你是后来加的吧。
对于一个实际的调用,性能和可见性无关,性能受调用所做的事情的影响。
一些显而易见的事实:
如果有人在意最后为什么变成 311K 的话,答案还是那句话:Rust 并不会把未实际调用的东西编译进二进制文件。
显然,第二种情况没有使用打印相关的功能,所以 Rust 不会把那些代码编译进去。(如果你加上
println!("Hello, world!");
大小依然是 319K)当你调用
never_used::main
:体积一定会增加:
不会。
一个粗略的观察是,Rust 并不会把未实际调用的东西编译进二进制文件,所以你的程序性能不会受到 pub/private 的影响:
估计要看源码, 或者问核心开发