Like would Arc have less overhead than this? also should i keep the server str as box
use anyhow::Result;
use tokio::{io::AsyncWriteExt, net::TcpListener};
use tor_server::config::Config;
#[tokio::main]
async fn main() -> Result<()> {
let config = Config::load("config.toml")?;
let server: Box<str> = config.server;
let listener = TcpListener::bind("0.0.0.0:80").await.unwrap();
let bytes: Box<[u8]> = Box::from(server.as_bytes());
loop {
let bytes = bytes.clone();
let (mut socket, _) = listener.accept().await?;
tokio::spawn(async move {
if let Err(e) = socket.write_all(&bytes).await {
eprintln!("Failed to write to socket: {e}");
}
});
}
}
Yes, I'd prefer using an Arc in this case, but both would be fine.
The difference in cost would be this clone:
let bytes = bytes.clone();
vs using an arc clone.
If you're using an Arc it's just an atomic increment vs with a box copy all of the bytes and another allocation.
I don't think you would actually notice a difference unless the size of the box is large. In this example you're sending the exact same data on each connection. However, if the response needs to be modified/different for each connection then a box might make more sense.
In this case, you could probably even just Box::leak your config (or parts thereof) and use &'static, since the data lives for (nearly) the rest of the process lifetime anyway.
More generally, since you're dealing in tokio networking already, it can be worth considering using the Bytes type (which itself utilizes atomic reference counting, but also supports subslicing).