Convert the stress.rs example into a simple benchmark.

There are no more bugs exposed by stress.rs as far as I can tell,
so let's make it do something more useful.
v0.7.x
whitequark 2017-12-22 20:59:30 +00:00
parent b2c2214725
commit fb11c4a84d
3 changed files with 41 additions and 7 deletions

View File

@ -69,10 +69,8 @@ required-features = ["std", "phy-tap_interface", "socket-tcp", "socket-udp"]
name = "loopback"
required-features = ["log", "socket-tcp"]
# This is really a test, but it requires root privileges for setup (the tap interface)
# so it is built as an example.
[[example]]
name = "stress"
name = "benchmark"
required-features = ["std", "phy-tap_interface", "socket-tcp"]
[profile.release]

View File

@ -8,6 +8,9 @@ at cost of performance degradation.
_smoltcp_ does not need heap allocation *at all*, is [extensively documented][docs],
and compiles on stable Rust 1.20 and later.
_smoltcp_ achieves [~Gbps of throughput](#examplesbenchmarkrs) when tested against
the Linux TCP stack in loopback mode.
[docs]: https://docs.rs/smoltcp/
## Features
@ -295,6 +298,29 @@ cargo run --example client -- tap0 ADDRESS PORT
It connects to the given address (not a hostname) and port (e.g. `socat stdio tcp4-listen:1234`),
and will respond with reversed chunks of the input indefinitely.
### examples/benchmark.rs
_examples/benchmark.rs_ implements a simple throughput benchmark.
Read its [source code](/examples/benchmark.rs), then run it as:
```sh
cargo run --release --example benchmark -- tap0 [reader|writer]
```
It establishes a connection to itself from a different thread and reads or writes a large amount
of data in one direction.
A typical result (achieved on a Intel Core i7-7500U CPU and a Linux 4.9.65 x86_64 kernel running
on a Dell XPS 13 9360 laptop) is as follows:
```
$ cargo run -q --release --example benchmark tap0 reader
throughput: 2.219 Gbps
$ cargo run -q --release --example benchmark tap0 writer
throughput: 4.519 Gbps
```
## Bare-metal usage examples
Examples that use no services from the host OS are necessarily less illustrative than examples

View File

@ -22,14 +22,16 @@ use smoltcp::iface::{NeighborCache, EthernetInterfaceBuilder};
use smoltcp::socket::SocketSet;
use smoltcp::socket::{TcpSocket, TcpSocketBuffer};
const AMOUNT: usize = 10_000_000;
const AMOUNT: usize = 1_000_000_000;
enum Client { Reader, Writer }
fn client(kind: Client) {
let port = match kind { Client::Reader => 1234, Client::Writer => 1235 };
let mut stream = TcpStream::connect(("192.168.69.1", port)).unwrap();
let mut buffer = vec![0; 64];
let mut buffer = vec![0; 1_000_000];
let start = Instant::now();
let mut processed = 0;
while processed < AMOUNT {
@ -47,7 +49,15 @@ fn client(kind: Client) {
Err(err) => panic!("cannot process: {}", err)
}
}
println!("client done");
let end = Instant::now();
let elapsed = end - start;
let elapsed = elapsed.as_secs() as f64
+ elapsed.subsec_nanos() as f64 * 1e-9;
println!("throughput: {:.3} Gbps", AMOUNT as f64 / elapsed / 0.125e9);
CLIENT_DONE.store(true, Ordering::SeqCst);
}
@ -139,6 +149,6 @@ fn main() {
}
}
phy_wait(fd, iface.poll_delay(&sockets, timestamp)).expect("wait error");
phy_wait(fd, iface.poll_delay(&sockets, timestamp).or(Some(1000))).expect("wait error");
}
}