< 返回版块

AndyJado 发表于 2022-07-26 10:33

大到mod小到struct和fn, 新手写代码, 喜欢都整成pub然后在main里跑一跑.

安全上的问题我能想到, 但对性能上有多少影响呢? 影响机制是什么呢?

评论区

写评论
flmn 2022-07-27 16:25

Rust 不是 Zero Cost Abstraction 么?

我认为不会影响性能,更多是影响代码架构。

rustdesk 2022-07-27 01:21

准确地说是没有链接进去,编译和链接是两个不同的过程。

--
👇
苦瓜小仔: 不会。

一个粗略的观察是,Rust 并不会把未实际调用的东西编译进二进制文件,所以你的程序性能不会受到 pub/private 的影响:

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
作者 AndyJado 2022-07-26 20:04

增加了理解, 感谢前辈! (发帖的时候就有这句话, 不是后加的)

--
👇
苦瓜小仔:

这句话你是后来加的吧。

苦瓜小仔 2022-07-26 19:47
苦瓜小仔 2022-07-26 18:53

喜欢都整成pub然后在main里跑一跑

这句话你是后来加的吧。

对于一个实际的调用,性能和可见性无关,性能受调用所做的事情的影响。

苦瓜小仔 2022-07-26 14:41

一些显而易见的事实:

如果有人在意最后为什么变成 311K 的话,答案还是那句话:Rust 并不会把未实际调用的东西编译进二进制文件。

fn main() {
    println!("Hello, world!");
}

// 一堆没用过的 pub
fn main() {}

显然,第二种情况没有使用打印相关的功能,所以 Rust 不会把那些代码编译进去。(如果你加上 println!("Hello, world!"); 大小依然是 319K)

当你调用 never_used::main:

fn main() {
    never_used::main();
}

体积一定会增加:

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
苦瓜小仔 2022-07-26 13:35

不会。

一个粗略的观察是,Rust 并不会把未实际调用的东西编译进二进制文件,所以你的程序性能不会受到 pub/private 的影响:

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
豆沙饼 is Louys 2022-07-26 11:17

估计要看源码, 或者问核心开发

1 共 8 条评论, 1 页