From fd0ad1bbce9c06c5f195b6885f618a409892e774 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Thu, 14 Mar 2024 16:31:21 +0000 Subject: [PATCH 1/3] test: [#87] remove lua script for HTTP tracker benchmarking We will use the aquatic commands to test both the HTTP and UDP trackers. --- tests/README.md | 9 ----- tests/wrk_benchmark_announce.lua | 68 -------------------------------- 2 files changed, 77 deletions(-) delete mode 100644 tests/README.md delete mode 100644 tests/wrk_benchmark_announce.lua diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index 04860056c..000000000 --- a/tests/README.md +++ /dev/null @@ -1,9 +0,0 @@ -### Running Benchmarks - -#### HTTP(S) Announce Peer + Torrent -For this benchmark we use the tool [wrk](https://github.com/wg/wrk). - -To run the benchmark using wrk, execute the following example script (change the url to your own tracker url): - - wrk -c200 -t1 -d10s -s ./wrk_benchmark_announce.lua --latency http://tracker.dutchbits.nl - diff --git a/tests/wrk_benchmark_announce.lua b/tests/wrk_benchmark_announce.lua deleted file mode 100644 index c0bdac48d..000000000 --- a/tests/wrk_benchmark_announce.lua +++ /dev/null @@ -1,68 +0,0 @@ --- else the randomness would be the same every run -math.randomseed(os.time()) - -local charset = "0123456789ABCDEF" - -function hex_to_char(hex) - local n = tonumber(hex, 16) - local f = string.char(n) - return f -end - -function hex_string_to_char_string(hex) - local ret = {} - local r - for i = 0, 19 do - local x = i * 2 - r = hex:sub(x+1, x+2) - local f = hex_to_char(r) - table.insert(ret, f) - end - return table.concat(ret) -end - -function url_encode(str) - str = string.gsub (str, "([^0-9a-zA-Z !'()*._~-])", -- locale independent - function (c) return string.format ("%%%02X", string.byte(c)) end) - str = string.gsub (str, " ", "+") - return str -end - -function gen_hex_string(length) - local ret = {} - local r - for i = 1, length do - r = math.random(1, #charset) - table.insert(ret, charset:sub(r, r)) - end - return table.concat(ret) -end - -function random_info_hash() - local hexString = gen_hex_string(40) - local str = hex_string_to_char_string(hexString) - return url_encode(str) -end - -function generate_unique_info_hashes(size) - local result = {} - - for i = 1, size do - result[i] = random_info_hash() - end - - return result -end - -info_hashes = generate_unique_info_hashes(5000000) - -index = 1 - --- the request function that will run at each request -request = function() - path = "/announce?info_hash=" .. info_hashes[index] .. "&peer_id=-lt0D80-a%D4%10%19%99%A6yh%9A%E1%CD%96&port=54434&uploaded=885&downloaded=0&left=0&corrupt=0&key=A78381BD&numwant=200&compact=1&no_peer_id=1&supportcrypto=1&redundant=0" - index = index + 1 - headers = {} - headers["X-Forwarded-For"] = "1.1.1.1" - return wrk.format("GET", path, headers) -end From d32a748e28f7fdb6a85e4f38beb9be44a070ea93 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Thu, 14 Mar 2024 17:34:28 +0000 Subject: [PATCH 2/3] docs: [#87] benchmarking How to run load tests using aquatic UDP load test commands. --- README.md | 4 + cSpell.json | 1 + docs/benchmarking.md | 252 ++++++++++++++++++ .../config/tracker.udp.benchmarking.toml | 37 +++ 4 files changed, 294 insertions(+) create mode 100644 docs/benchmarking.md create mode 100644 share/default/config/tracker.udp.benchmarking.toml diff --git a/README.md b/README.md index 18f3d361d..ea5078b19 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,10 @@ The following services are provided by the default configuration: - [Tracker (HTTP/TLS)][HTTP] - [Tracker (UDP)][UDP] +## Benchmarking + +- [Benchmarking](./docs/benchmarking.md) + ## Contributing We are happy to support and welcome new people to our project. Please consider our [contributor guide][guide.md].
diff --git a/cSpell.json b/cSpell.json index 646037e59..183ea31fb 100644 --- a/cSpell.json +++ b/cSpell.json @@ -50,6 +50,7 @@ "hexlify", "hlocalhost", "Hydranode", + "hyperthread", "Icelake", "imdl", "impls", diff --git a/docs/benchmarking.md b/docs/benchmarking.md new file mode 100644 index 000000000..8b455d4f9 --- /dev/null +++ b/docs/benchmarking.md @@ -0,0 +1,252 @@ +# Benchmarking + +We have two types of benchmarking: + +- E2E benchmarking running the service (HTTP or UDP tracker). +- Internal torrents repository benchmarking. + +## E2E benchmarking + +We are using the scripts provided by [aquatic](https://github.com/greatest-ape/aquatic). + +Installing both commands: + +```console +cargo install aquatic_udp_load_test +cargo install aquatic_http_load_test +``` + +### Run UDP load test + +Run the tracker with UDP service enabled on port 3000 and set log level to `error`. + +```toml +log_level = "error" + +[[udp_trackers]] +bind_address = "0.0.0.0:3000" +enabled = true +``` + +Run the load test with: + +```console +aquatic_udp_load_test +``` + +Output: + +```output +Starting client with config: Config { + server_address: 127.0.0.1:3000, + log_level: Error, + workers: 1, + duration: 0, + network: NetworkConfig { + multiple_client_ipv4s: true, + first_port: 45000, + poll_timeout: 276, + poll_event_capacity: 2877, + recv_buffer: 6000000, + }, + requests: RequestConfig { + number_of_torrents: 10000, + scrape_max_torrents: 50, + weight_connect: 0, + weight_announce: 100, + weight_scrape: 1, + torrent_gamma_shape: 0.2, + torrent_gamma_scale: 100.0, + peer_seeder_probability: 0.25, + additional_request_probability: 0.5, + }, +} + +Requests out: 32632.43/second +Responses in: 24239.33/second + - Connect responses: 7896.91 + - Announce responses: 16327.01 + - Scrape responses: 15.40 + - Error responses: 0.00 +Peers per announce response: 33.10 +``` + +### Run HTTP load test + +Run the tracker with UDP service enabled on port 3000 and set log level to `error`. + +```toml +[[udp_trackers]] +bind_address = "0.0.0.0:3000" +enabled = true +``` + +Run the load test with: + +```console +aquatic_http_load_test +``` + +Output: + +```output +Starting client with config: Config { + server_address: 127.0.0.1:3000, + log_level: Error, + num_workers: 1, + num_connections: 128, + connection_creation_interval_ms: 10, + url_suffix: "", + duration: 0, + keep_alive: true, + torrents: TorrentConfig { + number_of_torrents: 10000, + peer_seeder_probability: 0.25, + weight_announce: 5, + weight_scrape: 0, + torrent_gamma_shape: 0.2, + torrent_gamma_scale: 100.0, + }, + cpu_pinning: CpuPinningConfigDesc { + active: false, + direction: Descending, + hyperthread: System, + core_offset: 0, + }, +} +``` + +### Comparing UDP tracker with other Rust implementations + +#### Torrust UDP Tracker + +Running the tracker: + +```console +git@github.com:torrust/torrust-tracker.git +cd torrust-tracker +cargo build --release +TORRUST_TRACKER_PATH_CONFIG="./share/default/config/tracker.udp.benchmarking.toml" ./target/release/torrust-tracker +``` + +Running the test: `aquatic_udp_load_test`. + +```output +Requests out: 13075.56/second +Responses in: 12058.38/second + - Connect responses: 1017.18 + - Announce responses: 11035.00 + - Scrape responses: 6.20 + - Error responses: 0.00 +Peers per announce response: 41.13 +``` + +#### Aquatic UDP Tracker + +Running the tracker: + +```console +git clone git@github.com:greatest-ape/aquatic.git +cd aquatic +cargo build --release -p aquatic_udp +./target/release/aquatic_udp -c "aquatic-udp-config.toml" +./target/release/aquatic_udp -c "aquatic-udp-config.toml" +``` + +Running the test: `aquatic_udp_load_test`. + +```output +Requests out: 383873.14/second +Responses in: 383440.35/second + - Connect responses: 429.19 + - Announce responses: 379249.22 + - Scrape responses: 3761.93 + - Error responses: 0.00 +Peers per announce response: 15.33 +``` + +#### Torrust-Actix UDP Tracker + +Run the tracker with UDP service enabled on port 3000 and set log level to `error`. + +```toml +[[udp_trackers]] +bind_address = "0.0.0.0:3000" +enabled = true +``` + +```console +git clone https://github.com/Power2All/torrust-actix.git +cd torrust-actix +cargo build --release +./target/release/torrust-actix --create-config +./target/release/torrust-actix +``` + +Running the test: `aquatic_udp_load_test`. + +```output +Requests out: 3072.94/second +Responses in: 2395.15/second + - Connect responses: 556.79 + - Announce responses: 1821.16 + - Scrape responses: 17.20 + - Error responses: 0.00 +Peers per announce response: 133.88 +``` + +### Results + +Announce request per second: + +| Tracker | Announce | +|---------------|-----------| +| Aquatic | 379,249 | +| Torrust | 11,035 | +| Torrust-Actix | 1,821 | + +## Repository benchmarking + +You can run it with: + +```console +cargo run --release -p torrust-torrent-repository-benchmarks -- --threads 4 --sleep 0 --compare true +``` + +It tests the different implementation for the internal torrent storage. + +```output +tokio::sync::RwLock> +add_one_torrent: Avg/AdjAvg: (60ns, 59ns) +update_one_torrent_in_parallel: Avg/AdjAvg: (10.909457ms, 0ns) +add_multiple_torrents_in_parallel: Avg/AdjAvg: (13.88879ms, 0ns) +update_multiple_torrents_in_parallel: Avg/AdjAvg: (7.772484ms, 7.782535ms) + +std::sync::RwLock> +add_one_torrent: Avg/AdjAvg: (43ns, 39ns) +update_one_torrent_in_parallel: Avg/AdjAvg: (4.020937ms, 4.020937ms) +add_multiple_torrents_in_parallel: Avg/AdjAvg: (5.896177ms, 5.768448ms) +update_multiple_torrents_in_parallel: Avg/AdjAvg: (3.883823ms, 3.883823ms) + +std::sync::RwLock>>> +add_one_torrent: Avg/AdjAvg: (51ns, 49ns) +update_one_torrent_in_parallel: Avg/AdjAvg: (3.252314ms, 3.149109ms) +add_multiple_torrents_in_parallel: Avg/AdjAvg: (8.411094ms, 8.411094ms) +update_multiple_torrents_in_parallel: Avg/AdjAvg: (4.106086ms, 4.106086ms) + +tokio::sync::RwLock>>> +add_one_torrent: Avg/AdjAvg: (91ns, 90ns) +update_one_torrent_in_parallel: Avg/AdjAvg: (3.542378ms, 3.435695ms) +add_multiple_torrents_in_parallel: Avg/AdjAvg: (15.651172ms, 15.651172ms) +update_multiple_torrents_in_parallel: Avg/AdjAvg: (4.368189ms, 4.257572ms) + +tokio::sync::RwLock>>> +add_one_torrent: Avg/AdjAvg: (111ns, 109ns) +update_one_torrent_in_parallel: Avg/AdjAvg: (6.590677ms, 6.808535ms) +add_multiple_torrents_in_parallel: Avg/AdjAvg: (16.572217ms, 16.30488ms) +update_multiple_torrents_in_parallel: Avg/AdjAvg: (4.073221ms, 4.000122ms) +``` + +## Other considerations + +We are testing new repository implementations that allow concurrent writes. See . diff --git a/share/default/config/tracker.udp.benchmarking.toml b/share/default/config/tracker.udp.benchmarking.toml new file mode 100644 index 000000000..182112803 --- /dev/null +++ b/share/default/config/tracker.udp.benchmarking.toml @@ -0,0 +1,37 @@ +announce_interval = 120 +db_driver = "Sqlite3" +db_path = "./storage/tracker/lib/database/sqlite3.db" +external_ip = "0.0.0.0" +inactive_peer_cleanup_interval = 600 +log_level = "error" +max_peer_timeout = 900 +min_announce_interval = 120 +mode = "public" +on_reverse_proxy = false +persistent_torrent_completed_stat = false +remove_peerless_torrents = true +tracker_usage_statistics = true + +[[udp_trackers]] +bind_address = "0.0.0.0:3000" +enabled = true + +[[http_trackers]] +bind_address = "0.0.0.0:7070" +enabled = false +ssl_cert_path = "" +ssl_enabled = false +ssl_key_path = "" + +[http_api] +bind_address = "127.0.0.1:1212" +enabled = false +ssl_cert_path = "" +ssl_enabled = false +ssl_key_path = "" + +[http_api.access_tokens] +admin = "MyAccessToken" + +[health_check_api] +bind_address = "127.0.0.1:1313" From 45c77c33168dce1e5e8c01e82cde79dfd8842393 Mon Sep 17 00:00:00 2001 From: Jose Celano Date: Thu, 14 Mar 2024 19:37:33 +0000 Subject: [PATCH 3/3] fix: linter error, unused code --- src/console/clients/udp/responses.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/console/clients/udp/responses.rs b/src/console/clients/udp/responses.rs index 020c7a367..2fbc38f5f 100644 --- a/src/console/clients/udp/responses.rs +++ b/src/console/clients/udp/responses.rs @@ -68,13 +68,6 @@ impl From for ScrapeResponseDto { } } -#[derive(Serialize)] -struct Peer { - seeders: i32, - completed: i32, - leechers: i32, -} - #[derive(Serialize)] struct TorrentStats { seeders: i32,