diff --git a/.gitignore b/.gitignore index ea8c4bf7f..3b1cad7d5 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +tracedir diff --git a/Cargo.toml b/Cargo.toml index 38494e937..1d6621a61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,3 +35,7 @@ members = [ [patch.crates-io] socket2 = { git = "https://github.com/hermit-os/socket2.git", branch = "v0.5.x" } tokio = { git = "https://github.com/hermit-os/tokio.git", branch = "v/tokio-1.45.0" } + +[profile.release-debug] +inherits = "release" +debug = true diff --git a/benches/netbench/Cargo.toml b/benches/netbench/Cargo.toml index 36c342999..08f0a32dc 100644 --- a/benches/netbench/Cargo.toml +++ b/benches/netbench/Cargo.toml @@ -13,12 +13,16 @@ clap = { version ="4.5", features = ["derive"] } core_affinity = "0.8" hdrhist = "0.5" hermit_bench_output = "0.1.0" +rftrace = { version = "0.2", optional = true } +rftrace-frontend = { version = "0.2", optional = true } [target.'cfg(target_os = "hermit")'.dependencies] hermit = { path = "../../hermit", default-features = false } [features] -default = ["hermit/acpi", "hermit/pci", "hermit/smp", "hermit/tcp", "hermit/udp"] +default = ["hermit/acpi", "hermit/pci", "hermit/smp", "hermit/tcp", "hermit/udp", "hermit/virtio-net"] +rftrace = ["dep:rftrace", "dep:rftrace-frontend", "hermit/fs", "hermit/instrument"] +dhcp = ["hermit/dhcpv4"] [[bin]] name = "tcp-server-bw" diff --git a/benches/netbench/run.sh b/benches/netbench/run.sh index 8a2efb73d..b375ab0e7 100755 --- a/benches/netbench/run.sh +++ b/benches/netbench/run.sh @@ -1,44 +1,155 @@ #!/usr/bin/env bash -# Usage: run.sh TARGET BIN -# Example: run.sh linux server-bw -# run.sh hermit client-bw +# Usage: run.sh TARGET BIN [--rftrace] [--user-networking] +# Example: run.sh linux tcp-server-bw +# run.sh hermit tcp-client-bw set -o errexit +rftrace=false +user_networking=false +target= +bin= + +while [[ $# -gt 0 ]]; do + case "$1" in + --rftrace) + rftrace=true + shift + ;; + --user-networking) + user_networking=true + shift + ;; + -*) + echo "Unknown option: $1" >&2 + exit 1 + ;; + *) + if [[ -z "$target" ]]; then + target="$1" + elif [[ -z "$bin" ]]; then + bin="$1" + else + echo "Unexpected argument: $1" >&2 + exit 1 + fi + shift + ;; + esac +done + netbench_dir="${0%/*}" root_dir="$netbench_dir"/../.. -bin=$2 args="--bytes 1048576 --rounds 1000" hermit() { - echo "Building $bin image" - - cargo build --manifest-path "$netbench_dir"/Cargo.toml --bin $bin \ - -Zbuild-std=core,alloc,std,panic_abort -Zbuild-std-features=compiler-builtins-mem \ - --target x86_64-unknown-hermit \ - --release - - echo "Launching $bin image on QEMU" - - qemu-system-x86_64 -cpu host \ - -enable-kvm -display none -smp 1 -m 1G -serial stdio \ - -kernel "$root_dir"/kernel/hermit-loader-x86_64 \ - -initrd "$root_dir"/target/x86_64-unknown-hermit/release/$bin \ - -netdev tap,id=net0,ifname=tap10,script=no,downscript=no,vhost=on \ - -device virtio-net-pci,netdev=net0,disable-legacy=on \ - -append "-- --address 10.0.5.1 $args" + echo "Building $bin image" + + rustflags= + + cargo_cmd=( + cargo build + --manifest-path "$netbench_dir"/Cargo.toml + --bin "$bin" + -Zbuild-std=core,alloc,std,panic_abort + -Zbuild-std-features=compiler-builtins-mem + --target "$(uname -m)-unknown-hermit" + --profile release-debug + ) + + features=() + + if $rftrace; then + features+=(rftrace) + rustflags="-Zinstrument-mcount" + + mkdir -p tracedir + + sudo /usr/libexec/virtiofsd \ + --socket-path=/tmp/vhostqemu \ + --shared-dir=$(pwd)/tracedir \ + --announce-submounts \ + --sandbox none \ + --seccomp none \ + --inode-file-handles=never & + sleep 1 + + sudo chmod 777 /tmp/vhostqemu + fi + + if $user_networking; then + features+=(dhcp) + fi + + features_str="${features[*]}" + cargo_cmd+=(--features "$features_str") + + RUSTFLAGS="$rustflags" "${cargo_cmd[@]}" + + echo "Launching $bin image on QEMU" + + qemu_cmd=( + qemu-system-$(uname -m) + -cpu host + -enable-kvm + -display none + -smp 1 + -m 1G + -serial stdio + -kernel "$root_dir/kernel/hermit-loader-$(uname -m)" + -initrd "$root_dir/target/$(uname -m)-unknown-hermit/release-debug/$bin" + ) + + if $rftrace; then + qemu_cmd+=( + -chardev socket,id=char0,path=/tmp/vhostqemu + -device vhost-user-fs-pci,queue-size=1024,packed=on,chardev=char0,tag=tracedir + -object memory-backend-file,id=mem,size=1G,mem-path=/dev/shm,share=on + -numa node,memdev=mem + ) + fi + + if $user_networking; then + qemu_cmd+=( + -netdev user,id=net0,hostfwd=tcp::9975-:9975,hostfwd=udp::9975-:9975,net=192.168.76.0/24,dhcpstart=192.168.76.9 + -device virtio-net-pci,netdev=net0,disable-legacy=on + -append "-- --address 127.0.0.1 $args" + ) + else + qemu_cmd+=( + -netdev tap,id=net0,ifname=tap10,script=no,downscript=no,vhost=on + -device virtio-net-pci,netdev=net0,disable-legacy=on + -append "-- --address 10.0.5.1 $args" + ) + fi + + sudo "${qemu_cmd[@]}" + + if $rftrace; then + sleep 1 + nm -n "$root_dir"/target/$(uname -m)-unknown-hermit/release-debug/$bin >tracedir/$bin.sym + uftrace dump -d tracedir --flame-graph >tracedir/flamegraph.txt + flamegraph.pl tracedir/flamegraph.txt >tracedir/flamegraph.svg + firefox tracedir/flamegraph.svg + fi } linux() { - echo "Launching $bin on linux" + echo "Launching $bin on linux" + + if $user_networking; then + address=127.0.0.1 + else + address=10.0.5.3 + fi - cargo run --manifest-path "$netbench_dir"/Cargo.toml --bin $bin \ - --release \ - --target x86_64-unknown-linux-gnu \ - -- \ - --address 10.0.5.3 $args + cargo run --manifest-path "$netbench_dir"/Cargo.toml --bin $bin \ + --release \ + --target $(uname -m)-unknown-linux-gnu \ + -- \ + --address $address $args } -$1 +$target diff --git a/benches/netbench/src/rust-tcp-bw/client.rs b/benches/netbench/src/rust-tcp-bw/client.rs index 203816ca3..3ccfe46d9 100644 --- a/benches/netbench/src/rust-tcp-bw/client.rs +++ b/benches/netbench/src/rust-tcp-bw/client.rs @@ -1,12 +1,19 @@ use std::io::{self, Write}; +#[cfg(feature = "rftrace")] +extern crate rftrace as _; use clap::Parser; #[cfg(target_os = "hermit")] use hermit as _; +#[cfg(feature = "rftrace")] +use rftrace_frontend as rftrace; use rust_tcp_io_perf::config::Config; use rust_tcp_io_perf::connection; fn main() { + #[cfg(feature = "rftrace")] + let events = rftrace::init(100000, false); + let args = Config::parse(); println!("Connecting to the server {}:{}...", args.address, args.port); @@ -18,6 +25,9 @@ fn main() { // Create a buffer of 0s, size n_bytes, to be sent over multiple times let buf = vec![0; args.n_bytes]; + #[cfg(feature = "rftrace")] + rftrace::enable(); + for _i in 0..args.n_rounds { let mut pos = 0; @@ -31,9 +41,16 @@ fn main() { } } stream.flush().expect("Unexpected behaviour"); + + #[cfg(feature = "rftrace")] + rftrace::disable(); + connection::close_connection(&stream); println!("Sent everything!"); + + #[cfg(feature = "rftrace")] + rftrace::dump_full_uftrace(events, "/tracedir", "tcp-client-bw").unwrap(); } else { println!("Couldn't connect to server..."); } diff --git a/benches/netbench/src/rust-tcp-bw/server.rs b/benches/netbench/src/rust-tcp-bw/server.rs index 46dbbbf66..e46d23042 100644 --- a/benches/netbench/src/rust-tcp-bw/server.rs +++ b/benches/netbench/src/rust-tcp-bw/server.rs @@ -1,14 +1,21 @@ use std::io::Read; use std::time::Instant; +#[cfg(feature = "rftrace")] +extern crate rftrace as _; use clap::Parser; #[cfg(target_os = "hermit")] use hermit as _; use hermit_bench_output::log_benchmark_data; +#[cfg(feature = "rftrace")] +use rftrace_frontend as rftrace; use rust_tcp_io_perf::config::Config; use rust_tcp_io_perf::connection; fn main() { + #[cfg(feature = "rftrace")] + let events = rftrace::init(100000, false); + let args = Config::parse(); let tot_bytes = args.n_rounds * args.n_bytes; @@ -18,6 +25,10 @@ fn main() { connection::setup(&args, &stream); let start = Instant::now(); + + #[cfg(feature = "rftrace")] + rftrace::enable(); + for i in 0..args.n_rounds { print!("round {i}: "); let round_start = Instant::now(); @@ -27,6 +38,10 @@ fn main() { let mbits = buf.len() as f64 * 8.0f64 / (1024.0f64 * 1024.0f64 * duration.as_secs_f64()); println!("{mbits} Mbit/s"); } + + #[cfg(feature = "rftrace")] + rftrace::disable(); + let end = Instant::now(); let duration = end.duration_since(start); @@ -45,4 +60,7 @@ fn main() { ); connection::close_connection(&stream); + + #[cfg(feature = "rftrace")] + rftrace::dump_full_uftrace(events, "/tracedir", "tcp-server-bw").unwrap(); }