Skip to content

Commit 6eb24dc

Browse files
committed
Add benches for nats-client
Signed-off-by: Casper Beyer <[email protected]>
1 parent a5dc995 commit 6eb24dc

File tree

3 files changed

+194
-0
lines changed

3 files changed

+194
-0
lines changed

nats-client/benches/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Benchmarks for nats-client package."""
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""Benchmarks for NATS client operations."""
2+
3+
import asyncio
4+
import threading
5+
6+
import pytest
7+
8+
from nats.client import connect
9+
from nats.server import run
10+
11+
12+
@pytest.mark.parametrize(
13+
"size",
14+
[
15+
1,
16+
2,
17+
4,
18+
8,
19+
16,
20+
32,
21+
64,
22+
128,
23+
256,
24+
512,
25+
1024,
26+
2048,
27+
4096,
28+
8192,
29+
16384,
30+
32768,
31+
],
32+
)
33+
def test_bench_publish(benchmark, size):
34+
"""Benchmark publish with various payload sizes."""
35+
subject = "bench.publish"
36+
payload = b"x" * size
37+
38+
# Adjust count based on message size to keep total data volume consistent
39+
# Target ~10MB total per benchmark run
40+
target_bytes = 10 * 1024 * 1024
41+
count = max(1, target_bytes // max(1, size))
42+
43+
def setup():
44+
loop = asyncio.new_event_loop()
45+
asyncio.set_event_loop(loop)
46+
server = loop.run_until_complete(run(port=0))
47+
client = loop.run_until_complete(connect(server.client_url))
48+
return ((loop, server, client), {})
49+
50+
def execute(loop, server, client):
51+
async def publish_n():
52+
for _ in range(count):
53+
await client.publish(subject, payload)
54+
55+
loop.run_until_complete(publish_n())
56+
57+
def teardown(loop, server, client):
58+
loop.run_until_complete(client.close())
59+
loop.run_until_complete(server.shutdown())
60+
loop.close()
61+
asyncio.set_event_loop(None)
62+
63+
benchmark.extra_info["message_size"] = size
64+
benchmark.extra_info["message_count"] = count
65+
66+
result = benchmark.pedantic(execute, setup=setup, teardown=teardown, iterations=1, rounds=1)
67+
return result
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
"""Benchmarks for NATS protocol encoding operations."""
2+
3+
import pytest
4+
5+
from nats.client.protocol import command
6+
7+
8+
def test_bench_encode_connect(benchmark):
9+
"""Benchmark encoding CONNECT command with basic connection info."""
10+
connect_info = {
11+
"verbose": False,
12+
"pedantic": False,
13+
"tls_required": False,
14+
"name": "test-client",
15+
"lang": "python",
16+
"version": "1.0.0",
17+
"protocol": 1,
18+
}
19+
20+
benchmark(command.encode_connect, connect_info)
21+
22+
23+
@pytest.mark.parametrize("size", [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192])
24+
def test_bench_encode_pub_with_payload(benchmark, size):
25+
"""Benchmark encoding PUB command with various payload sizes."""
26+
subject = "test.subject"
27+
payload = b"x" * size
28+
29+
benchmark(command.encode_pub, subject, payload)
30+
31+
32+
def test_bench_encode_pub_with_reply(benchmark):
33+
"""Benchmark encoding PUB command with reply subject."""
34+
subject = "test.subject"
35+
payload = b"hello world"
36+
reply_to = "reply.subject"
37+
38+
benchmark(command.encode_pub, subject, payload, reply_to=reply_to)
39+
40+
41+
def test_bench_encode_hpub_single_header(benchmark):
42+
"""Benchmark encoding HPUB command with single header."""
43+
subject = "test.subject"
44+
payload = b"hello world"
45+
headers = {"X-Custom": "value"}
46+
47+
benchmark(command.encode_hpub, subject, payload, headers=headers)
48+
49+
50+
def test_bench_encode_hpub_multiple_headers(benchmark):
51+
"""Benchmark encoding HPUB command with multiple headers."""
52+
subject = "test.subject"
53+
payload = b"hello world"
54+
headers = {
55+
"X-Custom-1": "value1",
56+
"X-Custom-2": "value2",
57+
"X-Custom-3": "value3",
58+
"Content-Type": "application/json",
59+
"X-Request-ID": "12345-67890-abcdef",
60+
}
61+
62+
benchmark(command.encode_hpub, subject, payload, headers=headers)
63+
64+
65+
def test_bench_encode_hpub_multivalue_headers(benchmark):
66+
"""Benchmark encoding HPUB command with multi-value headers."""
67+
subject = "test.subject"
68+
payload = b"hello world"
69+
headers = {
70+
"X-Custom": ["value1", "value2", "value3"],
71+
"X-Tags": ["tag1", "tag2", "tag3", "tag4"],
72+
}
73+
74+
benchmark(command.encode_hpub, subject, payload, headers=headers)
75+
76+
77+
def test_bench_encode_hpub_with_reply(benchmark):
78+
"""Benchmark encoding HPUB command with reply subject and headers."""
79+
subject = "test.subject"
80+
payload = b"hello world"
81+
reply_to = "reply.subject"
82+
headers = {"X-Custom": "value"}
83+
84+
benchmark(command.encode_hpub, subject, payload, reply_to=reply_to, headers=headers)
85+
86+
87+
def test_bench_encode_sub(benchmark):
88+
"""Benchmark encoding SUB command."""
89+
subject = "test.subject"
90+
sid = "1"
91+
92+
benchmark(command.encode_sub, subject, sid)
93+
94+
95+
def test_bench_encode_sub_with_queue(benchmark):
96+
"""Benchmark encoding SUB command with queue group."""
97+
subject = "test.subject"
98+
sid = "1"
99+
queue_group = "test-queue"
100+
101+
benchmark(command.encode_sub, subject, sid, queue_group)
102+
103+
104+
def test_bench_encode_unsub(benchmark):
105+
"""Benchmark encoding UNSUB command."""
106+
sid = "1"
107+
108+
benchmark(command.encode_unsub, sid)
109+
110+
111+
def test_bench_encode_unsub_with_max(benchmark):
112+
"""Benchmark encoding UNSUB command with max_msgs."""
113+
sid = "1"
114+
max_msgs = 100
115+
116+
benchmark(command.encode_unsub, sid, max_msgs)
117+
118+
119+
def test_bench_encode_ping(benchmark):
120+
"""Benchmark encoding PING command."""
121+
benchmark(command.encode_ping)
122+
123+
124+
def test_bench_encode_pong(benchmark):
125+
"""Benchmark encoding PONG command."""
126+
benchmark(command.encode_pong)

0 commit comments

Comments
 (0)