diff --git a/Cargo.lock b/Cargo.lock index 3ff5970..a32f4ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,6 +53,12 @@ dependencies = [ "libc", ] +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + [[package]] name = "ansi_term" version = "0.12.1" @@ -345,6 +351,12 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.2.19" @@ -392,6 +404,33 @@ dependencies = [ "windows-link", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + [[package]] name = "clang-sys" version = "1.8.1" @@ -556,6 +595,42 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "criterion" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap 4.5.35", + "criterion-plot", + "is-terminal", + "itertools 0.10.5", + "num-traits", + "once_cell", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" +dependencies = [ + "cast", + "itertools 0.10.5", +] + [[package]] name = "crossbeam-channel" version = "0.5.15" @@ -565,6 +640,16 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + [[package]] name = "crossbeam-epoch" version = "0.9.18" @@ -580,6 +665,12 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-common" version = "0.1.6" @@ -930,6 +1021,16 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1417,6 +1518,15 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.12.1" @@ -1799,6 +1909,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + [[package]] name = "openssl" version = "0.10.72" @@ -1938,10 +2054,12 @@ version = "0.7.1" dependencies = [ "bytes", "chrono", + "criterion", "jsonwebtoken 9.3.1", "rand 0.9.0", "rmp-serde", "serde", + "serde_bytes", "sha2", "tokio", "tokio-util", @@ -2108,6 +2226,34 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + [[package]] name = "portable-atomic" version = "1.11.0" @@ -2386,6 +2532,26 @@ dependencies = [ "bitflags 2.9.0", ] +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_syscall" version = "0.5.11" @@ -2696,6 +2862,15 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scc" version = "2.3.3" @@ -2777,6 +2952,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.219" @@ -3188,6 +3372,16 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "tinyvec" version = "1.9.0" @@ -3698,6 +3892,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" diff --git a/ownserver_lib/Cargo.toml b/ownserver_lib/Cargo.toml index d18f43b..47dc267 100644 --- a/ownserver_lib/Cargo.toml +++ b/ownserver_lib/Cargo.toml @@ -15,6 +15,7 @@ keywords = ["network", "networking", "game", "minecraft"] [dependencies] serde = { version = "1.0", features = ["derive"] } +serde_bytes = "0.11" rmp-serde = "1.1" rand = "0.9" sha2 = "0.10" @@ -25,4 +26,9 @@ chrono = { version="0.4.40", features = ["serde"] } jsonwebtoken = "9" [dev-dependencies] -tokio = { version = "1", features = ["full"] } \ No newline at end of file +tokio = { version = "1", features = ["full"] } +criterion = "0.5" + +[[bench]] +name = "codec" +harness = false diff --git a/ownserver_lib/benches/codec.rs b/ownserver_lib/benches/codec.rs new file mode 100644 index 0000000..168c540 --- /dev/null +++ b/ownserver_lib/benches/codec.rs @@ -0,0 +1,76 @@ +use bytes::BytesMut; +use criterion::{black_box, criterion_group, criterion_main, Criterion}; +use ownserver_lib::{ControlPacketV2, ControlPacketV2Codec, EndpointId, RemoteInfo, StreamId}; +use tokio_util::codec::{Decoder, Encoder}; + +fn bench_encode_init(c: &mut Criterion) { + let stream_id = StreamId::default(); + let endpoint_id = EndpointId::default(); + let remote_info = RemoteInfo::new("127.0.0.1:8080".parse().unwrap()); + let packet = ControlPacketV2::Init(stream_id, endpoint_id, remote_info); + + c.bench_function("control_packet_encode_init", |b| { + b.iter(|| { + let mut codec = ControlPacketV2Codec::new(); + let mut dst = BytesMut::new(); + codec.encode(packet.clone(), &mut dst).unwrap(); + black_box(dst); + }) + }); +} + +fn bench_encode_data(c: &mut Criterion) { + let stream_id = StreamId::default(); + let packet = ControlPacketV2::Data(stream_id, vec![0; 1024]); + + c.bench_function("control_packet_encode_data", |b| { + b.iter(|| { + let mut codec = ControlPacketV2Codec::new(); + let mut dst = BytesMut::new(); + codec.encode(packet.clone(), &mut dst).unwrap(); + black_box(dst); + }) + }); +} + +fn bench_decode_init(c: &mut Criterion) { + let stream_id = StreamId::default(); + let endpoint_id = EndpointId::default(); + let remote_info = RemoteInfo::new("127.0.0.1:8080".parse().unwrap()); + let packet = ControlPacketV2::Init(stream_id, endpoint_id, remote_info); + + let mut codec = ControlPacketV2Codec::new(); + let mut encoded = BytesMut::new(); + codec.encode(packet, &mut encoded).unwrap(); + + c.bench_function("control_packet_decode_init", |b| { + b.iter(|| { + let mut data = encoded.clone(); + let mut codec = ControlPacketV2Codec::new(); + let _ = codec.decode(&mut data).unwrap().unwrap(); + black_box(data); + }) + }); +} + +fn bench_decode_data(c: &mut Criterion) { + let stream_id = StreamId::default(); + let packet = ControlPacketV2::Data(stream_id, vec![0; 1024]); + + let mut codec = ControlPacketV2Codec::new(); + let mut encoded = BytesMut::new(); + codec.encode(packet, &mut encoded).unwrap(); + + c.bench_function("control_packet_decode_data", |b| { + b.iter(|| { + let mut data = encoded.clone(); + let mut codec = ControlPacketV2Codec::new(); + let _ = codec.decode(&mut data).unwrap().unwrap(); + black_box(data); + }) + }); +} + +criterion_group!(benches, bench_encode_init, bench_decode_init, bench_encode_data, bench_decode_data); +criterion_main!(benches); + diff --git a/ownserver_lib/src/lib.rs b/ownserver_lib/src/lib.rs index 4c52191..ab16fb6 100644 --- a/ownserver_lib/src/lib.rs +++ b/ownserver_lib/src/lib.rs @@ -98,7 +98,7 @@ pub enum ClientType { #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub enum ControlPacketV2 { Init(StreamId, EndpointId, RemoteInfo), - Data(StreamId, Vec), + Data(StreamId, #[serde(with = "serde_bytes")] Vec), /// client --> server /// Notifies the server that a connection to the local server was refused. /// The server will close the corresponding remote stream upon receiving this notification. @@ -177,7 +177,11 @@ impl Encoder for ControlPacketV2Codec { type Error = io::Error; fn encode(&mut self, item: ControlPacketV2, dst: &mut BytesMut) -> Result<(), Self::Error> { - let encoded = rmp_serde::to_vec(&item).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + let mut encoded = Vec::new(); + let mut serializer = rmp_serde::Serializer::new(&mut encoded) + .with_bytes(rmp_serde::config::BytesMode::ForceAll); + item.serialize(&mut serializer).map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + dst.extend_from_slice(&encoded); Ok(()) }