aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--benchmarks/http/README.md4
-rw-r--r--benchmarks/http/drogon-baseline/.gitignore2
-rwxr-xr-xbenchmarks/http/drogon-baseline/build.sh15
-rw-r--r--benchmarks/http/drogon-baseline/main.cc172
-rw-r--r--benchmarks/http/run.py36
-rw-r--r--docs/research/075-http-host-against-axum.md36
-rw-r--r--research/experiments/011-http-frameworks/2026-09-26-pi5-sd.jsonl120
-rw-r--r--research/experiments/011-http-frameworks/README.md7
8 files changed, 382 insertions, 10 deletions
diff --git a/benchmarks/http/README.md b/benchmarks/http/README.md
index e26174b..b253dad 100644
--- a/benchmarks/http/README.md
+++ b/benchmarks/http/README.md
@@ -1,10 +1,12 @@
# HTTP 벤치마크
-Pure의 문서 서버들과 같은 계약의 axum 서비스를 같은 기기·코어 배정·부하 생성기로 잰다([075](../../docs/research/075-http-host-against-axum.md)).
+Pure의 문서 서버들과 같은 계약의 axum(Rust)·drogon(C++) 서비스를 같은 기기·코어 배정·부하 생성기로 잰다
+([075](../../docs/research/075-http-host-against-axum.md)).
```sh
cc -O2 -std=c17 -o load load.c
(cd axum-baseline && cargo build --release)
+drogon-baseline/build.sh # Debian의 drogon 패키지를 설치하지 않고 .deps에 풀어 빌드한다
make -C ../../prototypes/connections build/pure-serve
make -C ../../prototypes/connections BUILD=build/tree STORE=store-tree.c build/tree/pure-connections
aup build ../../../aup/examples/editor.aup -o editor.pmod
diff --git a/benchmarks/http/drogon-baseline/.gitignore b/benchmarks/http/drogon-baseline/.gitignore
new file mode 100644
index 0000000..ec322a0
--- /dev/null
+++ b/benchmarks/http/drogon-baseline/.gitignore
@@ -0,0 +1,2 @@
+.deps/
+drogon-baseline
diff --git a/benchmarks/http/drogon-baseline/build.sh b/benchmarks/http/drogon-baseline/build.sh
new file mode 100755
index 0000000..342f388
--- /dev/null
+++ b/benchmarks/http/drogon-baseline/build.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+# Build the drogon reference service against Debian's drogon without
+# installing anything: the packages are downloaded and unpacked under .deps
+# (an old-style rpath, so drogon finds its own dependencies there too).
+set -e
+cd "$(dirname "$0")"
+LIB=.deps/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)
+if [ ! -d "$LIB" ]; then
+ mkdir -p .deps/debs
+ (cd .deps/debs && apt-get download libdrogon-dev libdrogon1t64 libtrantor-dev libtrantor1 libjsoncpp-dev \
+ libhiredis1.1.0 libyaml-cpp0.8 && for deb in *.deb; do dpkg -x "$deb" ..; done)
+fi
+g++ -O2 -std=c++17 -I.deps/usr/include -I.deps/usr/include/jsoncpp -o drogon-baseline main.cc \
+ -L"$LIB" -Wl,--disable-new-dtags,-rpath,"$PWD/$LIB" -Wl,-rpath-link,"$LIB" -ldrogon -ltrantor -l:libjsoncpp.so.26 \
+ -lssl -lcrypto -lz -luuid -lpthread
diff --git a/benchmarks/http/drogon-baseline/main.cc b/benchmarks/http/drogon-baseline/main.cc
new file mode 100644
index 0000000..3151084
--- /dev/null
+++ b/benchmarks/http/drogon-baseline/main.cc
@@ -0,0 +1,172 @@
+// Reference service for Pure's HTTP benchmarks in drogon (C++), with the
+// contract of axum-baseline (see its src/main.rs): GET/PUT /objects/{key},
+// If-Match / If-None-Match: *, a PUT body of u32le start, u32le remove, then
+// the bytes to insert; the reply is the inserted bytes; ETag is the revision.
+//
+// drogon-baseline --port P [--durable DIR | --atomic DIR]
+// --durable writes the document and fdatasyncs before answering (not crash
+// safe); --atomic writes key.tmp, fsyncs it, renames it over the key and
+// fsyncs the directory. Handlers block their event loop while they sync, as
+// a straightforward drogon handler would.
+#include <arpa/inet.h>
+#include <drogon/drogon.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <cstdio>
+#include <cstring>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+
+using namespace drogon;
+
+struct Document {
+ std::mutex lock;
+ std::string bytes;
+ uint64_t revision = 0;
+};
+
+static std::mutex documents_lock;
+static std::unordered_map<std::string, std::shared_ptr<Document>> documents;
+static std::string durable;
+static bool atomic_writes = false;
+
+static bool valid_key(const std::string &key) {
+ if (key.empty() || key.size() > 64) return false;
+ for (char c : key)
+ if (!isalnum((unsigned char)c) && c != '-' && c != '_') return false;
+ return true;
+}
+
+static std::shared_ptr<Document> document(const std::string &key) {
+ std::lock_guard<std::mutex> guard(documents_lock);
+ auto &slot = documents[key];
+ if (!slot) slot = std::make_shared<Document>();
+ return slot;
+}
+
+static HttpResponsePtr tagged(HttpStatusCode status, uint64_t revision, const char *error, std::string body) {
+ auto response = HttpResponse::newHttpResponse();
+ response->setStatusCode(status);
+ response->setContentTypeCode(CT_APPLICATION_OCTET_STREAM);
+ response->addHeader("X-Pure-Error", error);
+ if (revision) response->addHeader("ETag", "\"" + std::to_string(revision) + "\"");
+ response->setBody(std::move(body));
+ return response;
+}
+
+static bool write_all(int fd, const std::string &bytes) {
+ for (size_t at = 0; at < bytes.size();) {
+ ssize_t n = write(fd, bytes.data() + at, bytes.size() - at);
+ if (n <= 0) return false;
+ at += (size_t)n;
+ }
+ return true;
+}
+
+static bool persist(const std::string &key, const std::string &bytes) {
+ std::string path = durable + "/" + key;
+ if (!atomic_writes) {
+ int fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ bool ok = fd >= 0 && write_all(fd, bytes) && fdatasync(fd) == 0;
+ if (fd >= 0) close(fd);
+ return ok;
+ }
+ std::string temporary = path + ".tmp";
+ int fd = open(temporary.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ bool ok = fd >= 0 && write_all(fd, bytes) && fsync(fd) == 0;
+ if (fd >= 0) close(fd);
+ ok = ok && rename(temporary.c_str(), path.c_str()) == 0;
+ int directory = ok ? open(durable.c_str(), O_RDONLY | O_DIRECTORY) : -1;
+ ok = ok && directory >= 0 && fsync(directory) == 0;
+ if (directory >= 0) close(directory);
+ return ok;
+}
+
+static HttpResponsePtr show(const std::string &key) {
+ if (!valid_key(key)) return tagged(k400BadRequest, 0, "request", "");
+ auto doc = document(key);
+ std::lock_guard<std::mutex> guard(doc->lock);
+ if (!doc->revision) return tagged(k404NotFound, 0, "not_found", "");
+ return tagged(k200OK, doc->revision, "none", doc->bytes);
+}
+
+static HttpResponsePtr edit(const HttpRequestPtr &request, const std::string &key) {
+ const std::string &match = request->getHeader("if-match"), &none = request->getHeader("if-none-match");
+ std::string_view body = request->body();
+ uint64_t expected = 0;
+ bool known = false;
+ if (!match.empty() && none.empty() && match.size() > 2 && match.front() == '"' && match.back() == '"') {
+ char *end = nullptr;
+ std::string digits = match.substr(1, match.size() - 2);
+ expected = strtoull(digits.c_str(), &end, 10);
+ known = !digits.empty() && end && !*end;
+ } else if (match.empty() && none == "*") known = true;
+ if (!known || !valid_key(key) || body.size() < 8) return tagged(k400BadRequest, 0, "request", "");
+ uint32_t start, remove;
+ memcpy(&start, body.data(), 4);
+ memcpy(&remove, body.data() + 4, 4);
+ auto doc = document(key);
+ std::lock_guard<std::mutex> guard(doc->lock);
+ if (doc->revision != expected) return tagged(k412PreconditionFailed, doc->revision, "conflict", "");
+ if (start > doc->bytes.size() || remove > doc->bytes.size() - start)
+ return tagged(k413RequestEntityTooLarge, 0, "limit", "");
+ std::string_view insert = body.substr(8);
+ doc->bytes.replace(start, remove, insert.data(), insert.size());
+ if (!durable.empty() && !persist(key, doc->bytes)) return tagged(k500InternalServerError, 0, "storage", "");
+ ++doc->revision;
+ return tagged(k200OK, doc->revision, "none", std::string(insert));
+}
+
+/* drogon listens once per event loop (SO_REUSEPORT): port 0 would give each
+ * loop a port of its own, so a free port is chosen first. */
+static uint16_t free_port() {
+ int fd = socket(AF_INET, SOCK_STREAM, 0);
+ sockaddr_in address{};
+ address.sin_family = AF_INET;
+ address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ socklen_t length = sizeof(address);
+ uint16_t port = 0;
+ if (fd >= 0 && !bind(fd, (sockaddr *)&address, sizeof(address)) && !getsockname(fd, (sockaddr *)&address, &length))
+ port = ntohs(address.sin_port);
+ if (fd >= 0) close(fd);
+ return port;
+}
+
+int main(int argc, char **argv) {
+ uint16_t port = 8769;
+ for (int i = 1; i + 1 < argc; i += 2) {
+ std::string flag = argv[i];
+ if (flag == "--port") port = (uint16_t)std::stoi(argv[i + 1]);
+ else if (flag == "--durable") durable = argv[i + 1];
+ else if (flag == "--atomic") durable = argv[i + 1], atomic_writes = true;
+ else {
+ fprintf(stderr, "unknown argument %s\n", argv[i]);
+ return 2;
+ }
+ }
+ if (!durable.empty()) mkdir(durable.c_str(), 0755);
+ app().registerHandler(
+ "/objects/{key}",
+ [](const HttpRequestPtr &request, std::function<void(const HttpResponsePtr &)> &&callback,
+ const std::string &key) {
+ callback(request->method() == Get ? show(key) : edit(request, key));
+ },
+ {Get, Put});
+ if (!port) port = free_port();
+ app().addListener("127.0.0.1", port);
+ app().setThreadNum(3); // the benchmark gives servers three cores
+ app().setClientMaxBodySize(64 << 20);
+ app().setClientMaxMemoryBodySize(64 << 20);
+ app().setLogLevel(trantor::Logger::kWarn);
+ app().registerBeginningAdvice([] {
+ auto listeners = app().getListeners();
+ printf("{\"port\":%u}\n", listeners.empty() ? 0u : (unsigned)listeners[0].toPort());
+ fflush(stdout);
+ });
+ app().run();
+}
diff --git a/benchmarks/http/run.py b/benchmarks/http/run.py
index f9fdbc0..91356f9 100644
--- a/benchmarks/http/run.py
+++ b/benchmarks/http/run.py
@@ -1,11 +1,14 @@
#!/usr/bin/env python3
-"""HTTP benchmarks: Pure's document servers against an axum service with the
-same contract, on the same machine, with the same load generator.
+"""HTTP benchmarks: Pure's document servers against axum (Rust) and drogon (C++)
+services with the same contract, on the same machine, with the same load
+generator.
Servers are pinned to CPUs 0-2 and the load to CPU 3; stores live under
--directory (use the device you care about: fsync costs are the device's).
Prints one JSON object per (server, workload, round) and a summary table of
-medians over rounds.
+medians over rounds. The load generator has one core, so near its limit the
+servers' CPU time tells them apart: 2xx/cpu-s is answers per second of server
+CPU (all threads, user and system).
Durable writes are only comparable on a device in the same state. An SD card
slows down under sustained syncs, so the order of runs alone can change a
@@ -17,6 +20,7 @@ next to each result.
import argparse
import json
import os
+import re
import select
import shutil
import signal
@@ -42,6 +46,12 @@ def start(args):
return process, port
+def cpu_seconds(pid):
+ """User and system time of every thread of the process."""
+ fields = Path(f'/proc/{pid}/stat').read_text().rsplit(')', 1)[1].split()
+ return (int(fields[11]) + int(fields[12])) / os.sysconf('SC_CLK_TCK')
+
+
def rss_kib(pid, field):
for line in Path(f'/proc/{pid}/status').read_text().splitlines():
if line.startswith(field):
@@ -91,12 +101,13 @@ def main():
parser.add_argument('--directory', type=Path, default=Path('/var/tmp'))
parser.add_argument('--seconds', type=float, default=5)
parser.add_argument('--only', default='')
- parser.add_argument('--workloads', default='', help='run only workloads whose label starts with one of these')
+ parser.add_argument('--workloads', default='', help='run only workloads whose label matches this regular expression')
parser.add_argument('--rounds', type=int, default=1, help='repeat every server, rotating their order')
parser.add_argument('--pause', type=float, default=0, help='seconds to rest the device between runs')
parser.add_argument('--budget', type=int, default=64 << 20, help="Pure's payload budget in bytes")
args = parser.parse_args()
axum = HERE / 'axum-baseline/target/release/axum-baseline'
+ drogon = HERE / 'drogon-baseline/drogon-baseline'
base = Path(tempfile.mkdtemp(dir=args.directory, prefix='pure-http-bench-'))
servers = {
'pure-program': lambda d: [PURE / 'build/tree/pure-connections', '--program', PURE / 'examples/editor.pure',
@@ -108,6 +119,9 @@ def main():
'axum-memory': lambda d: [axum, '--port', '0'],
'axum-durable': lambda d: [axum, '--port', '0', '--durable', d],
'axum-atomic': lambda d: [axum, '--port', '0', '--atomic', d],
+ 'drogon-memory': lambda d: [drogon, '--port', '0'],
+ 'drogon-durable': lambda d: [drogon, '--port', '0', '--durable', d],
+ 'drogon-atomic': lambda d: [drogon, '--port', '0', '--atomic', d],
}
workloads = [
('get 64B, 64 conn, close', dict(connections=64, method='get', keys=64, mode='close')),
@@ -117,7 +131,7 @@ def main():
('put 16B, 8 conn, keep-alive', dict(connections=8, method='put', keys=8, mode='keep-alive')),
]
if args.workloads:
- workloads = [w for w in workloads if w[0].startswith(tuple(args.workloads.split(',')))]
+ workloads = [w for w in workloads if re.search(args.workloads, w[0])]
chosen = [name for name in servers if not args.only or name in args.only.split(',')]
results = []
try:
@@ -136,10 +150,13 @@ def main():
# the 1 MiB document is k0 for this workload
put(port, 'k0', b'B' * (1 << 20), 1)
probe = probe_ms(base) if workload['method'] == 'put' else None
+ used = cpu_seconds(process.pid)
measured = load(port, workload['connections'], args.seconds, workload['method'],
workload['keys'], workload['mode'])
+ used = cpu_seconds(process.pid) - used
measured.update(server=name, workload=label, round=round_, probe_ms=probe,
- rss_kib=rss_kib(process.pid, 'VmRSS:'),
+ rss_kib=rss_kib(process.pid, 'VmRSS:'), cpu_seconds=round(used, 2),
+ ok_per_cpu_second=round(measured['2xx'] / used) if used else 0,
ok_per_second=round(measured['2xx'] / args.seconds), idle_rss_kib=idle)
results.append(measured)
print(json.dumps(measured), flush=True)
@@ -155,8 +172,8 @@ def main():
median = lambda rows, field: statistics.median(r[field] for r in rows)
print()
print(f"medians over {args.rounds} round(s)")
- print(f"{'workload':32s} {'server':14s} {'2xx/s':>9s} {'p50 us':>8s} {'p99 us':>8s} {'errors':>7s} "
- f"{'non-2xx':>8s} {'probe ms':>9s}")
+ print(f"{'workload':32s} {'server':14s} {'2xx/s':>9s} {'2xx/cpu-s':>10s} {'p50 us':>8s} {'p99 us':>8s} "
+ f"{'errors':>7s} {'non-2xx':>8s} {'probe ms':>9s}")
for label, _ in workloads:
for name in chosen:
rows = [r for r in results if r['server'] == name and r['workload'] == label]
@@ -164,7 +181,8 @@ def main():
continue
probes = [r['probe_ms'] for r in rows if r['probe_ms'] is not None]
probe = f"{min(probes):.1f}-{max(probes):.1f}" if probes else '-'
- print(f"{label:32s} {name:14s} {median(rows, 'ok_per_second'):9.0f} {median(rows, 'p50_us'):8.0f} "
+ print(f"{label:32s} {name:14s} {median(rows, 'ok_per_second'):9.0f} "
+ f"{median(rows, 'ok_per_cpu_second'):10.0f} {median(rows, 'p50_us'):8.0f} "
f"{median(rows, 'p99_us'):8.0f} {sum(r['errors'] for r in rows):7d} "
f"{sum(r['4xx'] + r['5xx'] for r in rows):8d} {probe:>9s}")
print()
diff --git a/docs/research/075-http-host-against-axum.md b/docs/research/075-http-host-against-axum.md
index 8a03889..17cfe39 100644
--- a/docs/research/075-http-host-against-axum.md
+++ b/docs/research/075-http-host-against-axum.md
@@ -137,3 +137,39 @@ ThreadSanitizer는 이 커널(47비트 가상 주소)을 지원하지 않아 쓰
충돌에 안전한 axum 대비 쓰기 처리량 3.4–4.5배, 봉우리 RSS 3.0–4.6 MiB 대 7.3–9.6 MiB다. 이제 읽기, 1 MiB 읽기,
저장 보장 쓰기 모두에서 axum보다 빠르고 메모리를 덜 쓴다.
+
+## 5단계: drogon 추가, CPU 효율
+
+drogon(C++) 1.9.0으로 같은 계약의 서비스를 만들었다(`benchmarks/http/drogon-baseline`, Debian 패키지를 설치하지
+않고 풀어서 빌드). 메모리·fdatasync·충돌 안전 세 모드, IO 스레드 3개다. 처음 잰 값(65k/s)은 잘못이었다.
+drogon은 IO 루프마다 `SO_REUSEPORT` 리스너를 따로 여는데, 포트 0을 주면 루프마다 다른 포트가 잡혀 부하가 루프
+하나에만 갔다. 빈 포트를 먼저 골라 쓰게 고쳤다.
+
+부하 생성기는 코어 하나라 초당 약 15만 건 근처에서 먼저 한계에 닿는다. 그래서 하네스가 서버 CPU 시간(모든 스레드,
+user+system)당 성공 응답 수(`2xx/cpu-s`)도 기록한다. 아래 표는 서버 순서를 회전한 3라운드(3초씩)의 중앙값이다
+([원시 결과](../../research/experiments/011-http-frameworks/2026-09-26-pi5-sd.jsonl)).
+괄호 안은 p99(µs)다.
+
+| 작업 | pure-serve | pure-serve 3샤드 | axum | drogon |
+|---|---:|---:|---:|---:|
+| GET 64 B keep-alive, 성공/초 | 127,764 (576) | **151,608** (608) | 120,942 (1,152) | 145,269 (736) |
+| 같은 작업, 성공/CPU-초 | **128,191** | 99,961 | 61,754 | 65,338 |
+| GET 64 B 연결마다 닫기, 성공/초 | **23,219** | 22,619 | 21,208 | 20,910 |
+| 같은 작업, 성공/CPU-초 | **41,629** | 36,482 | 18,462 | 18,450 |
+| GET 1 MiB keep-alive, 성공/초 | **2,794** | 1,751 | 1,372 | 708 |
+| PUT 충돌 안전, 연결 64, 성공/초 | 2,155 | **2,450** | 421 | 83 |
+| PUT 충돌 안전, 연결 8, 성공/초 | 548 | **551** | 105 | 41 |
+| 봉우리 RSS | **5.0 MiB** | 6.1 MiB | 14.4 MiB | 76.5 MiB |
+
+axum과 drogon의 GET·RSS는 메모리 모드, PUT은 충돌 안전 모드(임시 파일, fsync, rename, 디렉터리 fsync)다. Pure는
+모든 쓰기를 트리 저장소에 커밋한다. 참고로 충돌에 안전하지 않은 fdatasync 모드는 axum 433·101, drogon 146·87이었다.
+메모리 모드의 PUT은 axum 58,360·33,767, drogon 60,482·37,802로 내구성이 없어 비교 대상이 아니다.
+
+- 작은 GET 처리량은 3샤드가 가장 높다. CPU 효율은 1스레드가 axum·drogon의 약 2배다(부하 생성기 한계 근처에서
+ 3샤드는 스레드끼리 부하를 나누느라 효율이 낮아진다).
+- 1 MiB GET은 axum의 2배, drogon의 3.9배다. drogon은 본문을 `std::string`으로 여러 번 복사한다.
+- 충돌 안전 쓰기는 axum의 5.1–5.8배, drogon의 13–30배다. drogon 판은 가장 단순한 핸들러라 동기화하는 동안 이벤트
+ 루프를 막는다(axum 판은 `spawn_blocking`으로 넘긴다). 동기화를 별도 스레드 풀로 옮기면 drogon 값은 나아질 수
+ 있다. 그래도 요청마다 동기화하는 한 axum 판과 같은 한계에 닿는다.
+- 메모리는 axum의 약 1/3, drogon의 약 1/15다.
+
diff --git a/research/experiments/011-http-frameworks/2026-09-26-pi5-sd.jsonl b/research/experiments/011-http-frameworks/2026-09-26-pi5-sd.jsonl
new file mode 100644
index 0000000..ba1d8ee
--- /dev/null
+++ b/research/experiments/011-http-frameworks/2026-09-26-pi5-sd.jsonl
@@ -0,0 +1,120 @@
+{"requests_per_second": 23216, "completed": 69656, "2xx": 69656, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2688, "p99_us": 3584, "max_us": 5376, "server": "pure-serve", "workload": "get 64B, 64 conn, close", "round": 0, "probe_ms": null, "rss_kib": 2544, "cpu_seconds": 1.66, "ok_per_cpu_second": 41961, "ok_per_second": 23219, "idle_rss_kib": 2032}
+{"requests_per_second": 128205, "completed": 384617, "2xx": 384617, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 480, "p99_us": 544, "max_us": 2048, "server": "pure-serve", "workload": "get 64B, 64 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 2544, "cpu_seconds": 2.99, "ok_per_cpu_second": 128634, "ok_per_second": 128206, "idle_rss_kib": 2032}
+{"requests_per_second": 2742, "completed": 8225, "2xx": 8225, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2688, "p99_us": 4864, "max_us": 6912, "server": "pure-serve", "workload": "get 1MiB, 8 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 3808, "cpu_seconds": 3.0, "ok_per_cpu_second": 2742, "ok_per_second": 2742, "idle_rss_kib": 2032}
+{"requests_per_second": 1575, "completed": 4728, "2xx": 4664, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 19456, "p99_us": 589824, "max_us": 589824, "server": "pure-serve", "workload": "put 16B, 64 conn, keep-alive", "round": 0, "probe_ms": 1.02, "rss_kib": 3008, "cpu_seconds": 0.12, "ok_per_cpu_second": 38867, "ok_per_second": 1555, "idle_rss_kib": 2032}
+{"requests_per_second": 539, "completed": 1653, "2xx": 1645, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 6400, "p99_us": 90112, "max_us": 147456, "server": "pure-serve", "workload": "put 16B, 8 conn, keep-alive", "round": 0, "probe_ms": 1.53, "rss_kib": 3040, "cpu_seconds": 0.08, "ok_per_cpu_second": 20562, "ok_per_second": 548, "idle_rss_kib": 2032}
+{"requests_per_second": 22416, "completed": 67282, "2xx": 67282, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 4608, "max_us": 23552, "server": "pure-serve-3", "workload": "get 64B, 64 conn, close", "round": 0, "probe_ms": null, "rss_kib": 3664, "cpu_seconds": 1.84, "ok_per_cpu_second": 36566, "ok_per_second": 22427, "idle_rss_kib": 2576}
+{"requests_per_second": 152151, "completed": 456454, "2xx": 456454, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 400, "p99_us": 608, "max_us": 4352, "server": "pure-serve-3", "workload": "get 64B, 64 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 3664, "cpu_seconds": 4.55, "ok_per_cpu_second": 100320, "ok_per_second": 152151, "idle_rss_kib": 2576}
+{"requests_per_second": 1750, "completed": 5253, "2xx": 5253, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 4096, "p99_us": 7424, "max_us": 12800, "server": "pure-serve-3", "workload": "get 1MiB, 8 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 6720, "cpu_seconds": 4.86, "ok_per_cpu_second": 1081, "ok_per_second": 1751, "idle_rss_kib": 2576}
+{"requests_per_second": 2480, "completed": 7459, "2xx": 7395, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 12800, "p99_us": 110592, "max_us": 188416, "server": "pure-serve-3", "workload": "put 16B, 64 conn, keep-alive", "round": 0, "probe_ms": 1.2, "rss_kib": 4880, "cpu_seconds": 0.22, "ok_per_cpu_second": 33614, "ok_per_second": 2465, "idle_rss_kib": 2576}
+{"requests_per_second": 404, "completed": 1223, "2xx": 1215, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 7424, "p99_us": 131072, "max_us": 139264, "server": "pure-serve-3", "workload": "put 16B, 8 conn, keep-alive", "round": 0, "probe_ms": 1.35, "rss_kib": 4816, "cpu_seconds": 0.09, "ok_per_cpu_second": 13500, "ok_per_second": 405, "idle_rss_kib": 2576}
+{"requests_per_second": 21208, "completed": 63625, "2xx": 63625, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 6912, "max_us": 16384, "server": "axum-memory", "workload": "get 64B, 64 conn, close", "round": 0, "probe_ms": null, "rss_kib": 5008, "cpu_seconds": 3.45, "ok_per_cpu_second": 18442, "ok_per_second": 21208, "idle_rss_kib": 2720}
+{"requests_per_second": 125361, "completed": 376084, "2xx": 376084, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 496, "p99_us": 800, "max_us": 5632, "server": "axum-memory", "workload": "get 64B, 64 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 5504, "cpu_seconds": 6.09, "ok_per_cpu_second": 61754, "ok_per_second": 125361, "idle_rss_kib": 2720}
+{"requests_per_second": 1375, "completed": 4125, "2xx": 4125, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 5632, "p99_us": 8192, "max_us": 12288, "server": "axum-memory", "workload": "get 1MiB, 8 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 9312, "cpu_seconds": 4.12, "ok_per_cpu_second": 1001, "ok_per_second": 1375, "idle_rss_kib": 2720}
+{"requests_per_second": 57206, "completed": 171618, "2xx": 171554, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 1024, "p99_us": 2688, "max_us": 12800, "server": "axum-memory", "workload": "put 16B, 64 conn, keep-alive", "round": 0, "probe_ms": 1.34, "rss_kib": 12240, "cpu_seconds": 6.6, "ok_per_cpu_second": 25993, "ok_per_second": 57185, "idle_rss_kib": 2720}
+{"requests_per_second": 33768, "completed": 101308, "2xx": 101300, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 216, "p99_us": 608, "max_us": 5376, "server": "axum-memory", "workload": "put 16B, 8 conn, keep-alive", "round": 0, "probe_ms": 1.19, "rss_kib": 14736, "cpu_seconds": 6.82, "ok_per_cpu_second": 14853, "ok_per_second": 33767, "idle_rss_kib": 2720}
+{"requests_per_second": 22635, "completed": 67908, "2xx": 67908, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2432, "p99_us": 4096, "max_us": 16384, "server": "axum-durable", "workload": "get 64B, 64 conn, close", "round": 0, "probe_ms": null, "rss_kib": 4624, "cpu_seconds": 3.61, "ok_per_cpu_second": 18811, "ok_per_second": 22636, "idle_rss_kib": 2720}
+{"requests_per_second": 123700, "completed": 371101, "2xx": 371101, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 496, "p99_us": 864, "max_us": 3840, "server": "axum-durable", "workload": "get 64B, 64 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 5344, "cpu_seconds": 6.03, "ok_per_cpu_second": 61542, "ok_per_second": 123700, "idle_rss_kib": 2720}
+{"requests_per_second": 1375, "completed": 4125, "2xx": 4125, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 5632, "p99_us": 7680, "max_us": 11264, "server": "axum-durable", "workload": "get 1MiB, 8 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 9072, "cpu_seconds": 4.12, "ok_per_cpu_second": 1001, "ok_per_second": 1375, "idle_rss_kib": 2720}
+{"requests_per_second": 453, "completed": 1364, "2xx": 1300, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 106496, "p99_us": 360448, "max_us": 1638400, "server": "axum-durable", "workload": "put 16B, 64 conn, keep-alive", "round": 0, "probe_ms": 0.96, "rss_kib": 13824, "cpu_seconds": 0.2, "ok_per_cpu_second": 6500, "ok_per_second": 433, "idle_rss_kib": 2720}
+{"requests_per_second": 141, "completed": 430, "2xx": 422, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 32768, "p99_us": 114688, "max_us": 442368, "server": "axum-durable", "workload": "put 16B, 8 conn, keep-alive", "round": 0, "probe_ms": 2.72, "rss_kib": 13824, "cpu_seconds": 0.11, "ok_per_cpu_second": 3836, "ok_per_second": 141, "idle_rss_kib": 2720}
+{"requests_per_second": 21930, "completed": 65796, "2xx": 65796, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 4096, "max_us": 19456, "server": "axum-atomic", "workload": "get 64B, 64 conn, close", "round": 0, "probe_ms": null, "rss_kib": 4000, "cpu_seconds": 3.52, "ok_per_cpu_second": 18692, "ok_per_second": 21932, "idle_rss_kib": 2736}
+{"requests_per_second": 125214, "completed": 375641, "2xx": 375641, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 496, "p99_us": 768, "max_us": 4352, "server": "axum-atomic", "workload": "get 64B, 64 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 5360, "cpu_seconds": 6.09, "ok_per_cpu_second": 61682, "ok_per_second": 125214, "idle_rss_kib": 2736}
+{"requests_per_second": 1279, "completed": 3837, "2xx": 3837, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 5888, "p99_us": 9728, "max_us": 14848, "server": "axum-atomic", "workload": "get 1MiB, 8 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 9200, "cpu_seconds": 4.08, "ok_per_cpu_second": 940, "ok_per_second": 1279, "idle_rss_kib": 2736}
+{"requests_per_second": 475, "completed": 1464, "2xx": 1400, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 126976, "p99_us": 212992, "max_us": 622592, "server": "axum-atomic", "workload": "put 16B, 64 conn, keep-alive", "round": 0, "probe_ms": 1.24, "rss_kib": 14064, "cpu_seconds": 0.27, "ok_per_cpu_second": 5185, "ok_per_second": 467, "idle_rss_kib": 2736}
+{"requests_per_second": 106, "completed": 323, "2xx": 315, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 47104, "p99_us": 262144, "max_us": 262144, "server": "axum-atomic", "workload": "put 16B, 8 conn, keep-alive", "round": 0, "probe_ms": 0.96, "rss_kib": 14064, "cpu_seconds": 0.1, "ok_per_cpu_second": 3150, "ok_per_second": 105, "idle_rss_kib": 2736}
+{"requests_per_second": 20981, "completed": 62945, "2xx": 62945, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 4864, "max_us": 12800, "server": "drogon-memory", "workload": "get 64B, 64 conn, close", "round": 0, "probe_ms": null, "rss_kib": 69456, "cpu_seconds": 3.39, "ok_per_cpu_second": 18568, "ok_per_second": 20982, "idle_rss_kib": 10656}
+{"requests_per_second": 148504, "completed": 445540, "2xx": 445540, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 400, "p99_us": 640, "max_us": 8192, "server": "drogon-memory", "workload": "get 64B, 64 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 69472, "cpu_seconds": 6.75, "ok_per_cpu_second": 66006, "ok_per_second": 148513, "idle_rss_kib": 10656}
+{"requests_per_second": 691, "completed": 2073, "2xx": 2073, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 8704, "p99_us": 29696, "max_us": 81920, "server": "drogon-memory", "workload": "get 1MiB, 8 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 76640, "cpu_seconds": 7.55, "ok_per_cpu_second": 275, "ok_per_second": 691, "idle_rss_kib": 10656}
+{"requests_per_second": 60240, "completed": 180740, "2xx": 180676, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 896, "p99_us": 4608, "max_us": 36864, "server": "drogon-memory", "workload": "put 16B, 64 conn, keep-alive", "round": 0, "probe_ms": 1.15, "rss_kib": 76672, "cpu_seconds": 6.85, "ok_per_cpu_second": 26376, "ok_per_second": 60225, "idle_rss_kib": 10656}
+{"requests_per_second": 37804, "completed": 113414, "2xx": 113406, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 168, "p99_us": 864, "max_us": 3200, "server": "drogon-memory", "workload": "put 16B, 8 conn, keep-alive", "round": 0, "probe_ms": 1.34, "rss_kib": 78192, "cpu_seconds": 5.45, "ok_per_cpu_second": 20808, "ok_per_second": 37802, "idle_rss_kib": 10656}
+{"requests_per_second": 20359, "completed": 61088, "2xx": 61088, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2688, "p99_us": 5888, "max_us": 20480, "server": "drogon-durable", "workload": "get 64B, 64 conn, close", "round": 0, "probe_ms": null, "rss_kib": 67872, "cpu_seconds": 3.42, "ok_per_cpu_second": 17862, "ok_per_second": 20363, "idle_rss_kib": 10640}
+{"requests_per_second": 148325, "completed": 444987, "2xx": 444987, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 400, "p99_us": 640, "max_us": 5888, "server": "drogon-durable", "workload": "get 64B, 64 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 67904, "cpu_seconds": 7.08, "ok_per_cpu_second": 62851, "ok_per_second": 148329, "idle_rss_kib": 10640}
+{"requests_per_second": 699, "completed": 2096, "2xx": 2096, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 8192, "p99_us": 34816, "max_us": 53248, "server": "drogon-durable", "workload": "get 1MiB, 8 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 75088, "cpu_seconds": 7.21, "ok_per_cpu_second": 291, "ok_per_second": 699, "idle_rss_kib": 10640}
+{"requests_per_second": 184, "completed": 558, "2xx": 494, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 327680, "p99_us": 589824, "max_us": 720896, "server": "drogon-durable", "workload": "put 16B, 64 conn, keep-alive", "round": 0, "probe_ms": 1.22, "rss_kib": 75088, "cpu_seconds": 0.07, "ok_per_cpu_second": 7057, "ok_per_second": 165, "idle_rss_kib": 10640}
+{"requests_per_second": 86, "completed": 259, "2xx": 250, "4xx": 9, "5xx": 0, "errors": 0, "p50_us": 90112, "p99_us": 622592, "max_us": 720896, "server": "drogon-durable", "workload": "put 16B, 8 conn, keep-alive", "round": 0, "probe_ms": 6.01, "rss_kib": 75088, "cpu_seconds": 0.07, "ok_per_cpu_second": 3571, "ok_per_second": 83, "idle_rss_kib": 10640}
+{"requests_per_second": 21078, "completed": 63237, "2xx": 63237, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 4864, "max_us": 16384, "server": "drogon-atomic", "workload": "get 64B, 64 conn, close", "round": 0, "probe_ms": null, "rss_kib": 69808, "cpu_seconds": 3.44, "ok_per_cpu_second": 18383, "ok_per_second": 21079, "idle_rss_kib": 10672}
+{"requests_per_second": 148148, "completed": 444475, "2xx": 444475, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 384, "p99_us": 640, "max_us": 8192, "server": "drogon-atomic", "workload": "get 64B, 64 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 69872, "cpu_seconds": 7.04, "ok_per_cpu_second": 63136, "ok_per_second": 148158, "idle_rss_kib": 10672}
+{"requests_per_second": 667, "completed": 2002, "2xx": 2002, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 9216, "p99_us": 26624, "max_us": 55296, "server": "drogon-atomic", "workload": "get 1MiB, 8 conn, keep-alive", "round": 0, "probe_ms": null, "rss_kib": 77024, "cpu_seconds": 7.46, "ok_per_cpu_second": 268, "ok_per_second": 667, "idle_rss_kib": 10672}
+{"requests_per_second": 104, "completed": 312, "2xx": 248, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 589824, "p99_us": 1114112, "max_us": 1507328, "server": "drogon-atomic", "workload": "put 16B, 64 conn, keep-alive", "round": 0, "probe_ms": 1.5, "rss_kib": 77024, "cpu_seconds": 0.07, "ok_per_cpu_second": 3543, "ok_per_second": 83, "idle_rss_kib": 10672}
+{"requests_per_second": 42, "completed": 128, "2xx": 120, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 122880, "p99_us": 1179648, "max_us": 1245184, "server": "drogon-atomic", "workload": "put 16B, 8 conn, keep-alive", "round": 0, "probe_ms": 4.62, "rss_kib": 77024, "cpu_seconds": 0.05, "ok_per_cpu_second": 2400, "ok_per_second": 40, "idle_rss_kib": 10672}
+{"requests_per_second": 22613, "completed": 67857, "2xx": 67857, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 4352, "max_us": 26624, "server": "pure-serve-3", "workload": "get 64B, 64 conn, close", "round": 1, "probe_ms": null, "rss_kib": 3664, "cpu_seconds": 1.86, "ok_per_cpu_second": 36482, "ok_per_second": 22619, "idle_rss_kib": 2592}
+{"requests_per_second": 151606, "completed": 454824, "2xx": 454824, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 400, "p99_us": 608, "max_us": 11264, "server": "pure-serve-3", "workload": "get 64B, 64 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 3664, "cpu_seconds": 4.55, "ok_per_cpu_second": 99961, "ok_per_second": 151608, "idle_rss_kib": 2592}
+{"requests_per_second": 1738, "completed": 5215, "2xx": 5215, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 4096, "p99_us": 9728, "max_us": 16384, "server": "pure-serve-3", "workload": "get 1MiB, 8 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 6720, "cpu_seconds": 4.67, "ok_per_cpu_second": 1117, "ok_per_second": 1738, "idle_rss_kib": 2592}
+{"requests_per_second": 2470, "completed": 7415, "2xx": 7351, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 11264, "p99_us": 245760, "max_us": 262144, "server": "pure-serve-3", "workload": "put 16B, 64 conn, keep-alive", "round": 1, "probe_ms": 1.23, "rss_kib": 4768, "cpu_seconds": 0.19, "ok_per_cpu_second": 38689, "ok_per_second": 2450, "idle_rss_kib": 2592}
+{"requests_per_second": 610, "completed": 1857, "2xx": 1849, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 6144, "p99_us": 94208, "max_us": 147456, "server": "pure-serve-3", "workload": "put 16B, 8 conn, keep-alive", "round": 1, "probe_ms": 0.99, "rss_kib": 4480, "cpu_seconds": 0.16, "ok_per_cpu_second": 11556, "ok_per_second": 616, "idle_rss_kib": 2592}
+{"requests_per_second": 21658, "completed": 64997, "2xx": 64997, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 4608, "max_us": 18432, "server": "axum-memory", "workload": "get 64B, 64 conn, close", "round": 1, "probe_ms": null, "rss_kib": 4512, "cpu_seconds": 3.47, "ok_per_cpu_second": 18731, "ok_per_second": 21666, "idle_rss_kib": 2736}
+{"requests_per_second": 113865, "completed": 341596, "2xx": 341596, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 496, "p99_us": 1408, "max_us": 8704, "server": "axum-memory", "workload": "get 64B, 64 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 5264, "cpu_seconds": 5.6, "ok_per_cpu_second": 60999, "ok_per_second": 113865, "idle_rss_kib": 2736}
+{"requests_per_second": 1372, "completed": 4115, "2xx": 4115, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 5632, "p99_us": 8704, "max_us": 14336, "server": "axum-memory", "workload": "get 1MiB, 8 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 8992, "cpu_seconds": 4.1, "ok_per_cpu_second": 1004, "ok_per_second": 1372, "idle_rss_kib": 2736}
+{"requests_per_second": 58381, "completed": 175144, "2xx": 175080, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 960, "p99_us": 2688, "max_us": 8704, "server": "axum-memory", "workload": "put 16B, 64 conn, keep-alive", "round": 1, "probe_ms": 1.2, "rss_kib": 11984, "cpu_seconds": 6.78, "ok_per_cpu_second": 25823, "ok_per_second": 58360, "idle_rss_kib": 2736}
+{"requests_per_second": 33771, "completed": 101314, "2xx": 101306, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 208, "p99_us": 576, "max_us": 4608, "server": "axum-memory", "workload": "put 16B, 8 conn, keep-alive", "round": 1, "probe_ms": 1.18, "rss_kib": 14688, "cpu_seconds": 6.72, "ok_per_cpu_second": 15075, "ok_per_second": 33769, "idle_rss_kib": 2736}
+{"requests_per_second": 22137, "completed": 66423, "2xx": 66423, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 4096, "max_us": 8704, "server": "axum-durable", "workload": "get 64B, 64 conn, close", "round": 1, "probe_ms": null, "rss_kib": 4416, "cpu_seconds": 3.53, "ok_per_cpu_second": 18817, "ok_per_second": 22141, "idle_rss_kib": 2720}
+{"requests_per_second": 122526, "completed": 367579, "2xx": 367579, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 496, "p99_us": 1024, "max_us": 5120, "server": "axum-durable", "workload": "get 64B, 64 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 5264, "cpu_seconds": 5.95, "ok_per_cpu_second": 61778, "ok_per_second": 122526, "idle_rss_kib": 2720}
+{"requests_per_second": 1413, "completed": 4238, "2xx": 4238, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 5376, "p99_us": 7168, "max_us": 10240, "server": "axum-durable", "workload": "get 1MiB, 8 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 8992, "cpu_seconds": 4.14, "ok_per_cpu_second": 1024, "ok_per_second": 1413, "idle_rss_kib": 2720}
+{"requests_per_second": 424, "completed": 1278, "2xx": 1214, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 102400, "p99_us": 376832, "max_us": 720896, "server": "axum-durable", "workload": "put 16B, 64 conn, keep-alive", "round": 1, "probe_ms": 0.95, "rss_kib": 12976, "cpu_seconds": 0.18, "ok_per_cpu_second": 6744, "ok_per_second": 405, "idle_rss_kib": 2720}
+{"requests_per_second": 101, "completed": 309, "2xx": 301, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 86016, "p99_us": 196608, "max_us": 262144, "server": "axum-durable", "workload": "put 16B, 8 conn, keep-alive", "round": 1, "probe_ms": 1.21, "rss_kib": 13056, "cpu_seconds": 0.1, "ok_per_cpu_second": 3010, "ok_per_second": 100, "idle_rss_kib": 2720}
+{"requests_per_second": 22216, "completed": 66671, "2xx": 66671, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2432, "p99_us": 4608, "max_us": 21504, "server": "axum-atomic", "workload": "get 64B, 64 conn, close", "round": 1, "probe_ms": null, "rss_kib": 3792, "cpu_seconds": 3.56, "ok_per_cpu_second": 18728, "ok_per_second": 22224, "idle_rss_kib": 2704}
+{"requests_per_second": 121769, "completed": 365307, "2xx": 365307, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 496, "p99_us": 1024, "max_us": 4608, "server": "axum-atomic", "workload": "get 64B, 64 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 5216, "cpu_seconds": 5.89, "ok_per_cpu_second": 62022, "ok_per_second": 121769, "idle_rss_kib": 2704}
+{"requests_per_second": 1323, "completed": 3970, "2xx": 3970, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 5888, "p99_us": 7680, "max_us": 9216, "server": "axum-atomic", "workload": "get 1MiB, 8 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 8944, "cpu_seconds": 4.14, "ok_per_cpu_second": 959, "ok_per_second": 1323, "idle_rss_kib": 2704}
+{"requests_per_second": 436, "completed": 1328, "2xx": 1264, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 131072, "p99_us": 344064, "max_us": 622592, "server": "axum-atomic", "workload": "put 16B, 64 conn, keep-alive", "round": 1, "probe_ms": 1.35, "rss_kib": 13872, "cpu_seconds": 0.24, "ok_per_cpu_second": 5267, "ok_per_second": 421, "idle_rss_kib": 2704}
+{"requests_per_second": 79, "completed": 241, "2xx": 233, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 94208, "p99_us": 229376, "max_us": 237568, "server": "axum-atomic", "workload": "put 16B, 8 conn, keep-alive", "round": 1, "probe_ms": 0.96, "rss_kib": 13872, "cpu_seconds": 0.09, "ok_per_cpu_second": 2589, "ok_per_second": 78, "idle_rss_kib": 2704}
+{"requests_per_second": 20176, "completed": 60535, "2xx": 60535, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2688, "p99_us": 4864, "max_us": 21504, "server": "drogon-memory", "workload": "get 64B, 64 conn, close", "round": 1, "probe_ms": null, "rss_kib": 67280, "cpu_seconds": 3.45, "ok_per_cpu_second": 17546, "ok_per_second": 20178, "idle_rss_kib": 10640}
+{"requests_per_second": 139000, "completed": 417016, "2xx": 417016, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 384, "p99_us": 1984, "max_us": 36864, "server": "drogon-memory", "workload": "get 64B, 64 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 67312, "cpu_seconds": 6.85, "ok_per_cpu_second": 60878, "ok_per_second": 139005, "idle_rss_kib": 10640}
+{"requests_per_second": 762, "completed": 2287, "2xx": 2287, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 7424, "p99_us": 29696, "max_us": 34816, "server": "drogon-memory", "workload": "get 1MiB, 8 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 74480, "cpu_seconds": 7.63, "ok_per_cpu_second": 300, "ok_per_second": 762, "idle_rss_kib": 10640}
+{"requests_per_second": 60875, "completed": 182627, "2xx": 182563, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 928, "p99_us": 2816, "max_us": 14336, "server": "drogon-memory", "workload": "put 16B, 64 conn, keep-alive", "round": 1, "probe_ms": 1.16, "rss_kib": 74512, "cpu_seconds": 7.97, "ok_per_cpu_second": 22906, "ok_per_second": 60854, "idle_rss_kib": 10640}
+{"requests_per_second": 37832, "completed": 113497, "2xx": 113489, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 136, "p99_us": 992, "max_us": 5888, "server": "drogon-memory", "workload": "put 16B, 8 conn, keep-alive", "round": 1, "probe_ms": 1.39, "rss_kib": 75920, "cpu_seconds": 8.03, "ok_per_cpu_second": 14133, "ok_per_second": 37830, "idle_rss_kib": 10640}
+{"requests_per_second": 19859, "completed": 59600, "2xx": 59600, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2688, "p99_us": 6656, "max_us": 21504, "server": "drogon-durable", "workload": "get 64B, 64 conn, close", "round": 1, "probe_ms": null, "rss_kib": 66624, "cpu_seconds": 3.35, "ok_per_cpu_second": 17791, "ok_per_second": 19867, "idle_rss_kib": 10672}
+{"requests_per_second": 143650, "completed": 430962, "2xx": 430962, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 400, "p99_us": 1024, "max_us": 38912, "server": "drogon-durable", "workload": "get 64B, 64 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 66640, "cpu_seconds": 6.9, "ok_per_cpu_second": 62458, "ok_per_second": 143654, "idle_rss_kib": 10672}
+{"requests_per_second": 671, "completed": 2012, "2xx": 2012, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 10752, "p99_us": 28672, "max_us": 47104, "server": "drogon-durable", "workload": "get 1MiB, 8 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 73824, "cpu_seconds": 7.33, "ok_per_cpu_second": 274, "ok_per_second": 671, "idle_rss_kib": 10672}
+{"requests_per_second": 167, "completed": 501, "2xx": 437, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 360448, "p99_us": 720896, "max_us": 1048576, "server": "drogon-durable", "workload": "put 16B, 64 conn, keep-alive", "round": 1, "probe_ms": 0.97, "rss_kib": 73824, "cpu_seconds": 0.06, "ok_per_cpu_second": 7283, "ok_per_second": 146, "idle_rss_kib": 10672}
+{"requests_per_second": 90, "completed": 269, "2xx": 261, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 65536, "p99_us": 622592, "max_us": 819200, "server": "drogon-durable", "workload": "put 16B, 8 conn, keep-alive", "round": 1, "probe_ms": 2.89, "rss_kib": 73824, "cpu_seconds": 0.08, "ok_per_cpu_second": 3263, "ok_per_second": 87, "idle_rss_kib": 10672}
+{"requests_per_second": 20666, "completed": 62001, "2xx": 62001, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2688, "p99_us": 5120, "max_us": 13312, "server": "drogon-atomic", "workload": "get 64B, 64 conn, close", "round": 1, "probe_ms": null, "rss_kib": 68560, "cpu_seconds": 3.46, "ok_per_cpu_second": 17919, "ok_per_second": 20667, "idle_rss_kib": 10656}
+{"requests_per_second": 144301, "completed": 432907, "2xx": 432907, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 384, "p99_us": 928, "max_us": 8704, "server": "drogon-atomic", "workload": "get 64B, 64 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 68624, "cpu_seconds": 6.75, "ok_per_cpu_second": 64134, "ok_per_second": 144302, "idle_rss_kib": 10656}
+{"requests_per_second": 728, "completed": 2183, "2xx": 2183, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 10240, "p99_us": 24576, "max_us": 36864, "server": "drogon-atomic", "workload": "get 1MiB, 8 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 75776, "cpu_seconds": 7.72, "ok_per_cpu_second": 283, "ok_per_second": 728, "idle_rss_kib": 10656}
+{"requests_per_second": 92, "completed": 278, "2xx": 214, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 589824, "p99_us": 1441792, "max_us": 2031616, "server": "drogon-atomic", "workload": "put 16B, 64 conn, keep-alive", "round": 1, "probe_ms": 1.2, "rss_kib": 74736, "cpu_seconds": 0.05, "ok_per_cpu_second": 4280, "ok_per_second": 71, "idle_rss_kib": 10656}
+{"requests_per_second": 47, "completed": 145, "2xx": 137, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 110592, "p99_us": 1114112, "max_us": 1114112, "server": "drogon-atomic", "workload": "put 16B, 8 conn, keep-alive", "round": 1, "probe_ms": 4.72, "rss_kib": 74736, "cpu_seconds": 0.06, "ok_per_cpu_second": 2283, "ok_per_second": 46, "idle_rss_kib": 10656}
+{"requests_per_second": 23307, "completed": 69936, "2xx": 69936, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2688, "p99_us": 3840, "max_us": 4608, "server": "pure-serve", "workload": "get 64B, 64 conn, close", "round": 1, "probe_ms": null, "rss_kib": 2528, "cpu_seconds": 1.68, "ok_per_cpu_second": 41629, "ok_per_second": 23312, "idle_rss_kib": 2016}
+{"requests_per_second": 126572, "completed": 379715, "2xx": 379715, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 480, "p99_us": 640, "max_us": 2176, "server": "pure-serve", "workload": "get 64B, 64 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 2528, "cpu_seconds": 3.01, "ok_per_cpu_second": 126151, "ok_per_second": 126572, "idle_rss_kib": 2016}
+{"requests_per_second": 2799, "completed": 8397, "2xx": 8397, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2688, "p99_us": 4096, "max_us": 6144, "server": "pure-serve", "workload": "get 1MiB, 8 conn, keep-alive", "round": 1, "probe_ms": null, "rss_kib": 3792, "cpu_seconds": 2.99, "ok_per_cpu_second": 2808, "ok_per_second": 2799, "idle_rss_kib": 2016}
+{"requests_per_second": 2461, "completed": 7388, "2xx": 7324, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 17408, "p99_us": 94208, "max_us": 139264, "server": "pure-serve", "workload": "put 16B, 64 conn, keep-alive", "round": 1, "probe_ms": 1.49, "rss_kib": 3040, "cpu_seconds": 0.2, "ok_per_cpu_second": 36620, "ok_per_second": 2441, "idle_rss_kib": 2016}
+{"requests_per_second": 759, "completed": 2277, "2xx": 2269, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 6144, "p99_us": 81920, "max_us": 90112, "server": "pure-serve", "workload": "put 16B, 8 conn, keep-alive", "round": 1, "probe_ms": 1.53, "rss_kib": 2992, "cpu_seconds": 0.1, "ok_per_cpu_second": 22690, "ok_per_second": 756, "idle_rss_kib": 2016}
+{"requests_per_second": 20922, "completed": 62771, "2xx": 62771, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 5888, "max_us": 28672, "server": "axum-memory", "workload": "get 64B, 64 conn, close", "round": 2, "probe_ms": null, "rss_kib": 4048, "cpu_seconds": 3.4, "ok_per_cpu_second": 18462, "ok_per_second": 20924, "idle_rss_kib": 2704}
+{"requests_per_second": 120941, "completed": 362826, "2xx": 362826, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 496, "p99_us": 1152, "max_us": 6912, "server": "axum-memory", "workload": "get 64B, 64 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 5200, "cpu_seconds": 5.87, "ok_per_cpu_second": 61810, "ok_per_second": 120942, "idle_rss_kib": 2704}
+{"requests_per_second": 1362, "completed": 4087, "2xx": 4087, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 5632, "p99_us": 7936, "max_us": 10240, "server": "axum-memory", "workload": "get 1MiB, 8 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 8928, "cpu_seconds": 4.11, "ok_per_cpu_second": 994, "ok_per_second": 1362, "idle_rss_kib": 2704}
+{"requests_per_second": 61877, "completed": 185644, "2xx": 185580, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 992, "p99_us": 2048, "max_us": 6656, "server": "axum-memory", "workload": "put 16B, 64 conn, keep-alive", "round": 2, "probe_ms": 0.96, "rss_kib": 11600, "cpu_seconds": 7.08, "ok_per_cpu_second": 26212, "ok_per_second": 61860, "idle_rss_kib": 2704}
+{"requests_per_second": 32760, "completed": 98281, "2xx": 98273, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 184, "p99_us": 1024, "max_us": 13312, "server": "axum-memory", "workload": "put 16B, 8 conn, keep-alive", "round": 2, "probe_ms": 0.97, "rss_kib": 14352, "cpu_seconds": 6.24, "ok_per_cpu_second": 15749, "ok_per_second": 32758, "idle_rss_kib": 2704}
+{"requests_per_second": 22160, "completed": 66484, "2xx": 66484, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 4096, "max_us": 12288, "server": "axum-durable", "workload": "get 64B, 64 conn, close", "round": 2, "probe_ms": null, "rss_kib": 4576, "cpu_seconds": 3.53, "ok_per_cpu_second": 18834, "ok_per_second": 22161, "idle_rss_kib": 2736}
+{"requests_per_second": 124333, "completed": 373002, "2xx": 373002, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 496, "p99_us": 864, "max_us": 4608, "server": "axum-durable", "workload": "get 64B, 64 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 5488, "cpu_seconds": 6.07, "ok_per_cpu_second": 61450, "ok_per_second": 124334, "idle_rss_kib": 2736}
+{"requests_per_second": 1276, "completed": 3829, "2xx": 3829, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 5376, "p99_us": 13312, "max_us": 22528, "server": "axum-durable", "workload": "get 1MiB, 8 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 9328, "cpu_seconds": 3.96, "ok_per_cpu_second": 967, "ok_per_second": 1276, "idle_rss_kib": 2736}
+{"requests_per_second": 591, "completed": 1781, "2xx": 1717, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 102400, "p99_us": 294912, "max_us": 327680, "server": "axum-durable", "workload": "put 16B, 64 conn, keep-alive", "round": 2, "probe_ms": 1.22, "rss_kib": 14064, "cpu_seconds": 0.24, "ok_per_cpu_second": 7154, "ok_per_second": 572, "idle_rss_kib": 2736}
+{"requests_per_second": 104, "completed": 312, "2xx": 304, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 81920, "p99_us": 180224, "max_us": 294912, "server": "axum-durable", "workload": "put 16B, 8 conn, keep-alive", "round": 2, "probe_ms": 1.35, "rss_kib": 14064, "cpu_seconds": 0.11, "ok_per_cpu_second": 2764, "ok_per_second": 101, "idle_rss_kib": 2736}
+{"requests_per_second": 22309, "completed": 66955, "2xx": 66955, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2432, "p99_us": 4096, "max_us": 15360, "server": "axum-atomic", "workload": "get 64B, 64 conn, close", "round": 2, "probe_ms": null, "rss_kib": 5024, "cpu_seconds": 3.58, "ok_per_cpu_second": 18703, "ok_per_second": 22318, "idle_rss_kib": 2736}
+{"requests_per_second": 122047, "completed": 366143, "2xx": 366143, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 496, "p99_us": 1024, "max_us": 4864, "server": "axum-atomic", "workload": "get 64B, 64 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 5408, "cpu_seconds": 5.92, "ok_per_cpu_second": 61848, "ok_per_second": 122048, "idle_rss_kib": 2736}
+{"requests_per_second": 1438, "completed": 4314, "2xx": 4314, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 5376, "p99_us": 7936, "max_us": 11776, "server": "axum-atomic", "workload": "get 1MiB, 8 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 9136, "cpu_seconds": 4.12, "ok_per_cpu_second": 1047, "ok_per_second": 1438, "idle_rss_kib": 2736}
+{"requests_per_second": 438, "completed": 1319, "2xx": 1255, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 126976, "p99_us": 507904, "max_us": 1441792, "server": "axum-atomic", "workload": "put 16B, 64 conn, keep-alive", "round": 2, "probe_ms": 1.35, "rss_kib": 13888, "cpu_seconds": 0.24, "ok_per_cpu_second": 5229, "ok_per_second": 418, "idle_rss_kib": 2736}
+{"requests_per_second": 123, "completed": 370, "2xx": 362, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 45056, "p99_us": 262144, "max_us": 262144, "server": "axum-atomic", "workload": "put 16B, 8 conn, keep-alive", "round": 2, "probe_ms": 2.7, "rss_kib": 13888, "cpu_seconds": 0.1, "ok_per_cpu_second": 3620, "ok_per_second": 121, "idle_rss_kib": 2736}
+{"requests_per_second": 20900, "completed": 62730, "2xx": 62730, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 4864, "max_us": 23552, "server": "drogon-memory", "workload": "get 64B, 64 conn, close", "round": 2, "probe_ms": null, "rss_kib": 69232, "cpu_seconds": 3.4, "ok_per_cpu_second": 18450, "ok_per_second": 20910, "idle_rss_kib": 10656}
+{"requests_per_second": 145268, "completed": 435807, "2xx": 435807, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 400, "p99_us": 736, "max_us": 29696, "server": "drogon-memory", "workload": "get 64B, 64 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 69280, "cpu_seconds": 6.67, "ok_per_cpu_second": 65338, "ok_per_second": 145269, "idle_rss_kib": 10656}
+{"requests_per_second": 708, "completed": 2123, "2xx": 2123, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 10240, "p99_us": 26624, "max_us": 49152, "server": "drogon-memory", "workload": "get 1MiB, 8 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 76448, "cpu_seconds": 7.62, "ok_per_cpu_second": 279, "ok_per_second": 708, "idle_rss_kib": 10656}
+{"requests_per_second": 60503, "completed": 181511, "2xx": 181447, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 896, "p99_us": 4864, "max_us": 21504, "server": "drogon-memory", "workload": "put 16B, 64 conn, keep-alive", "round": 2, "probe_ms": 1.22, "rss_kib": 76480, "cpu_seconds": 6.89, "ok_per_cpu_second": 26335, "ok_per_second": 60482, "idle_rss_kib": 10656}
+{"requests_per_second": 37024, "completed": 111072, "2xx": 111064, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 144, "p99_us": 864, "max_us": 5376, "server": "drogon-memory", "workload": "put 16B, 8 conn, keep-alive", "round": 2, "probe_ms": 0.96, "rss_kib": 78288, "cpu_seconds": 8.32, "ok_per_cpu_second": 13349, "ok_per_second": 37021, "idle_rss_kib": 10656}
+{"requests_per_second": 20458, "completed": 61375, "2xx": 61375, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2688, "p99_us": 4864, "max_us": 15360, "server": "drogon-durable", "workload": "get 64B, 64 conn, close", "round": 2, "probe_ms": null, "rss_kib": 68064, "cpu_seconds": 3.44, "ok_per_cpu_second": 17842, "ok_per_second": 20458, "idle_rss_kib": 10672}
+{"requests_per_second": 142278, "completed": 426846, "2xx": 426846, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 400, "p99_us": 1024, "max_us": 18432, "server": "drogon-durable", "workload": "get 64B, 64 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 68112, "cpu_seconds": 6.77, "ok_per_cpu_second": 63050, "ok_per_second": 142282, "idle_rss_kib": 10672}
+{"requests_per_second": 692, "completed": 2076, "2xx": 2076, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 9216, "p99_us": 23552, "max_us": 73728, "server": "drogon-durable", "workload": "get 1MiB, 8 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 75280, "cpu_seconds": 7.84, "ok_per_cpu_second": 265, "ok_per_second": 692, "idle_rss_kib": 10672}
+{"requests_per_second": 162, "completed": 488, "2xx": 424, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 344064, "p99_us": 753664, "max_us": 851968, "server": "drogon-durable", "workload": "put 16B, 64 conn, keep-alive", "round": 2, "probe_ms": 1.21, "rss_kib": 75280, "cpu_seconds": 0.06, "ok_per_cpu_second": 7067, "ok_per_second": 141, "idle_rss_kib": 10672}
+{"requests_per_second": 92, "completed": 276, "2xx": 268, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 36864, "p99_us": 557056, "max_us": 720896, "server": "drogon-durable", "workload": "put 16B, 8 conn, keep-alive", "round": 2, "probe_ms": 2.06, "rss_kib": 75280, "cpu_seconds": 0.07, "ok_per_cpu_second": 3829, "ok_per_second": 89, "idle_rss_kib": 10672}
+{"requests_per_second": 20454, "completed": 61385, "2xx": 61385, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2688, "p99_us": 5632, "max_us": 18432, "server": "drogon-atomic", "workload": "get 64B, 64 conn, close", "round": 2, "probe_ms": null, "rss_kib": 68208, "cpu_seconds": 3.36, "ok_per_cpu_second": 18269, "ok_per_second": 20462, "idle_rss_kib": 10672}
+{"requests_per_second": 146697, "completed": 440107, "2xx": 440107, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 400, "p99_us": 640, "max_us": 6400, "server": "drogon-atomic", "workload": "get 64B, 64 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 68224, "cpu_seconds": 6.93, "ok_per_cpu_second": 63508, "ok_per_second": 146702, "idle_rss_kib": 10672}
+{"requests_per_second": 707, "completed": 2123, "2xx": 2123, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 8704, "p99_us": 20480, "max_us": 32768, "server": "drogon-atomic", "workload": "get 1MiB, 8 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 75376, "cpu_seconds": 8.22, "ok_per_cpu_second": 258, "ok_per_second": 708, "idle_rss_kib": 10672}
+{"requests_per_second": 104, "completed": 320, "2xx": 256, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 524288, "p99_us": 1179648, "max_us": 1966080, "server": "drogon-atomic", "workload": "put 16B, 64 conn, keep-alive", "round": 2, "probe_ms": 0.96, "rss_kib": 75376, "cpu_seconds": 0.06, "ok_per_cpu_second": 4267, "ok_per_second": 85, "idle_rss_kib": 10672}
+{"requests_per_second": 44, "completed": 131, "2xx": 123, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 118784, "p99_us": 983040, "max_us": 983040, "server": "drogon-atomic", "workload": "put 16B, 8 conn, keep-alive", "round": 2, "probe_ms": 3.73, "rss_kib": 75376, "cpu_seconds": 0.07, "ok_per_cpu_second": 1757, "ok_per_second": 41, "idle_rss_kib": 10672}
+{"requests_per_second": 22942, "completed": 68840, "2xx": 68840, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 3072, "p99_us": 4608, "max_us": 6144, "server": "pure-serve", "workload": "get 64B, 64 conn, close", "round": 2, "probe_ms": null, "rss_kib": 2528, "cpu_seconds": 1.67, "ok_per_cpu_second": 41222, "ok_per_second": 22947, "idle_rss_kib": 2016}
+{"requests_per_second": 127763, "completed": 383291, "2xx": 383291, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 480, "p99_us": 576, "max_us": 2048, "server": "pure-serve", "workload": "get 64B, 64 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 2528, "cpu_seconds": 2.99, "ok_per_cpu_second": 128191, "ok_per_second": 127764, "idle_rss_kib": 2016}
+{"requests_per_second": 2794, "completed": 8382, "2xx": 8382, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2688, "p99_us": 3968, "max_us": 6144, "server": "pure-serve", "workload": "get 1MiB, 8 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 3792, "cpu_seconds": 3.0, "ok_per_cpu_second": 2794, "ok_per_second": 2794, "idle_rss_kib": 2016}
+{"requests_per_second": 2142, "completed": 6530, "2xx": 6466, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 16384, "p99_us": 118784, "max_us": 147456, "server": "pure-serve", "workload": "put 16B, 64 conn, keep-alive", "round": 2, "probe_ms": 0.96, "rss_kib": 3184, "cpu_seconds": 0.17, "ok_per_cpu_second": 38035, "ok_per_second": 2155, "idle_rss_kib": 2016}
+{"requests_per_second": 233, "completed": 699, "2xx": 691, "4xx": 8, "5xx": 0, "errors": 0, "p50_us": 6400, "p99_us": 1376256, "max_us": 1376256, "server": "pure-serve", "workload": "put 16B, 8 conn, keep-alive", "round": 2, "probe_ms": 2.5, "rss_kib": 3056, "cpu_seconds": 0.03, "ok_per_cpu_second": 23033, "ok_per_second": 230, "idle_rss_kib": 2016}
+{"requests_per_second": 22813, "completed": 68459, "2xx": 68459, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 2560, "p99_us": 4608, "max_us": 13824, "server": "pure-serve-3", "workload": "get 64B, 64 conn, close", "round": 2, "probe_ms": null, "rss_kib": 3664, "cpu_seconds": 1.91, "ok_per_cpu_second": 35842, "ok_per_second": 22820, "idle_rss_kib": 2576}
+{"requests_per_second": 149487, "completed": 448484, "2xx": 448484, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 400, "p99_us": 672, "max_us": 7168, "server": "pure-serve-3", "workload": "get 64B, 64 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 3664, "cpu_seconds": 4.57, "ok_per_cpu_second": 98137, "ok_per_second": 149495, "idle_rss_kib": 2576}
+{"requests_per_second": 1871, "completed": 5616, "2xx": 5616, "4xx": 0, "5xx": 0, "errors": 0, "p50_us": 3968, "p99_us": 7168, "max_us": 11264, "server": "pure-serve-3", "workload": "get 1MiB, 8 conn, keep-alive", "round": 2, "probe_ms": null, "rss_kib": 6704, "cpu_seconds": 4.94, "ok_per_cpu_second": 1137, "ok_per_second": 1872, "idle_rss_kib": 2576}
+{"requests_per_second": 1834, "completed": 5576, "2xx": 5512, "4xx": 64, "5xx": 0, "errors": 0, "p50_us": 9728, "p99_us": 1376256, "max_us": 1376256, "server": "pure-serve-3", "workload": "put 16B, 64 conn, keep-alive", "round": 2, "probe_ms": 1.49, "rss_kib": 4960, "cpu_seconds": 0.16, "ok_per_cpu_second": 34450, "ok_per_second": 1837, "idle_rss_kib": 2576}
+{"requests_per_second": 554, "completed": 1661, "2xx": 1652, "4xx": 9, "5xx": 0, "errors": 0, "p50_us": 7168, "p99_us": 73728, "max_us": 786432, "server": "pure-serve-3", "workload": "put 16B, 8 conn, keep-alive", "round": 2, "probe_ms": 2.71, "rss_kib": 4656, "cpu_seconds": 0.12, "ok_per_cpu_second": 13767, "ok_per_second": 551, "idle_rss_kib": 2576}
diff --git a/research/experiments/011-http-frameworks/README.md b/research/experiments/011-http-frameworks/README.md
new file mode 100644
index 0000000..2b21595
--- /dev/null
+++ b/research/experiments/011-http-frameworks/README.md
@@ -0,0 +1,7 @@
+# 011 — HTTP 프레임워크 비교 원시 결과
+
+[docs/research/075](../../../docs/research/075-http-host-against-axum.md)의 5단계 표의 원시 값이다.
+`benchmarks/http/run.py --rounds 3 --seconds 3`(서버 순서를 라운드마다 회전)으로 Pure `156e1ad`,
+axum 0.8.9, drogon 1.9.0을 같은 Raspberry Pi 5(서버 CPU 0–2, 부하 CPU 3, 저장소 ext4 SD)에서 쟀다.
+한 줄이 (서버, 작업, 라운드) 하나이며 `ok_per_cpu_second`는 서버 CPU 시간(모든 스레드, user+system)
+1초당 성공 응답 수다.