Benchmarks
Procedures to compare NATS.jl performance with go
implementation.
Prerequisites:
- start nats-server
docker run -p 4222:4222 nats:latest
- enusre
nats
CLI tool is installed
Request-Reply latency
Native go
latency
Start reply service
> nats reply foo "This is a reply" 2> /dev/null > /dev/null
Run benchmark with 1 publisher
> nats bench foo --pub 1 --request --msgs 1000
13:25:53 Benchmark in request-reply mode
13:25:53 Starting request-reply benchmark [subject=foo, multisubject=false, multisubjectmax=0, request=true, reply=false, msgs=1,000, msgsize=128 B, pubs=1, subs=0, pubsleep=0s, subsleep=0s]
13:25:53 Starting publisher, publishing 1,000 messages
Finished 0s [================] 100%
Pub stats: 1,676 msgs/sec ~ 209.57 KB/sec
Run benchmark with 10 publishers
> nats bench foo --pub 10 --request --msgs 10000
13:30:52 Benchmark in request-reply mode
13:30:52 Starting request-reply benchmark [subject=foo, multisubject=false, multisubjectmax=0, request=true, reply=false, msgs=10,000, msgsize=128 B, pubs=10, subs=0, pubsleep=0s, subsleep=0s]
13:30:52 Starting publisher, publishing 1,000 messages
13:30:52 Starting publisher, publishing 1,000 messages
13:30:52 Starting publisher, publishing 1,000 messages
13:30:52 Starting publisher, publishing 1,000 messages
13:30:52 Starting publisher, publishing 1,000 messages
13:30:52 Starting publisher, publishing 1,000 messages
13:30:52 Starting publisher, publishing 1,000 messages
13:30:52 Starting publisher, publishing 1,000 messages
13:30:52 Starting publisher, publishing 1,000 messages
13:30:52 Starting publisher, publishing 1,000 messages
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Pub stats: 11,522 msgs/sec ~ 1.41 MB/sec
[1] 1,158 msgs/sec ~ 144.85 KB/sec (1000 msgs)
[2] 1,158 msgs/sec ~ 144.84 KB/sec (1000 msgs)
[3] 1,158 msgs/sec ~ 144.79 KB/sec (1000 msgs)
[4] 1,157 msgs/sec ~ 144.73 KB/sec (1000 msgs)
[5] 1,157 msgs/sec ~ 144.68 KB/sec (1000 msgs)
[6] 1,156 msgs/sec ~ 144.62 KB/sec (1000 msgs)
[7] 1,154 msgs/sec ~ 144.36 KB/sec (1000 msgs)
[8] 1,153 msgs/sec ~ 144.22 KB/sec (1000 msgs)
[9] 1,153 msgs/sec ~ 144.13 KB/sec (1000 msgs)
[10] 1,152 msgs/sec ~ 144.03 KB/sec (1000 msgs)
min 1,152 | avg 1,155 | max 1,158 | stddev 2 msgs
NATS.jl latency
Start reply service
julia> using NATS
julia> nc = NATS.connect();
julia> reply(nc, "foo") do
"This is a reply."
end
NATS.Sub("foo", nothing, "PDrH5FOxIgBpcnLO4xHD")
Run benchmark with 1 publisher:
> nats bench foo --pub 1 --request --msgs 1000
13:28:56 Benchmark in request-reply mode
13:28:56 Starting request-reply benchmark [subject=foo, multisubject=false, multisubjectmax=0, request=true, reply=false, msgs=1,000, msgsize=128 B, pubs=1, subs=0, pubsleep=0s, subsleep=0s]
13:28:56 Starting publisher, publishing 1,000 messages
Finished 0s [================] 100%
Pub stats: 1,565 msgs/sec ~ 195.64 KB/sec
Run benchmark with 10 publishers:
nats bench foo --pub 10 --request --msgs 10000
13:29:51 Benchmark in request-reply mode
13:29:51 Starting request-reply benchmark [subject=foo, multisubject=false, multisubjectmax=0, request=true, reply=false, msgs=10,000, msgsize=128 B, pubs=10, subs=0, pubsleep=0s, subsleep=0s]
13:29:51 Starting publisher, publishing 1,000 messages
13:29:51 Starting publisher, publishing 1,000 messages
13:29:51 Starting publisher, publishing 1,000 messages
13:29:51 Starting publisher, publishing 1,000 messages
13:29:51 Starting publisher, publishing 1,000 messages
13:29:51 Starting publisher, publishing 1,000 messages
13:29:51 Starting publisher, publishing 1,000 messages
13:29:51 Starting publisher, publishing 1,000 messages
13:29:51 Starting publisher, publishing 1,000 messages
13:29:51 Starting publisher, publishing 1,000 messages
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Finished 0s [================] 100%
Pub stats: 11,880 msgs/sec ~ 1.45 MB/sec
[1] 1,204 msgs/sec ~ 150.62 KB/sec (1000 msgs)
[2] 1,198 msgs/sec ~ 149.85 KB/sec (1000 msgs)
[3] 1,197 msgs/sec ~ 149.70 KB/sec (1000 msgs)
[4] 1,194 msgs/sec ~ 149.31 KB/sec (1000 msgs)
[5] 1,193 msgs/sec ~ 149.20 KB/sec (1000 msgs)
[6] 1,192 msgs/sec ~ 149.09 KB/sec (1000 msgs)
[7] 1,192 msgs/sec ~ 149.06 KB/sec (1000 msgs)
[8] 1,191 msgs/sec ~ 148.91 KB/sec (1000 msgs)
[9] 1,191 msgs/sec ~ 148.88 KB/sec (1000 msgs)
[10] 1,188 msgs/sec ~ 148.50 KB/sec (1000 msgs)
min 1,188 | avg 1,194 | max 1,204 | stddev 4 msgs
Results show 1,155 msgs/s for native go library and 1,194 msgs/s NATS.jl, we are good here.
Publish-Subscribe benchmarks
Run nats CLI benchmarks
> nats bench foo --pub 1 --sub 1 --size 16
13:43:05 Starting Core NATS pub/sub benchmark [subject=foo, multisubject=false, multisubjectmax=0, msgs=100,000, msgsize=16 B, pubs=1, subs=1, pubsleep=0s, subsleep=0s]
13:43:05 Starting subscriber, expecting 100,000 messages
13:43:05 Starting publisher, publishing 100,000 messages
Finished 0s [================] 100%
Finished 0s [================] 100%
NATS Pub/Sub stats: 2,251,521 msgs/sec ~ 34.36 MB/sec
Pub stats: 1,215,686 msgs/sec ~ 18.55 MB/sec
Sub stats: 1,154,802 msgs/sec ~ 17.62 MB/sec
Benchmark NATS.jl publish
julia> using NATS
julia> nc = NATS.connect();
Threads.threadid() =
julia>
julia> Threads.threadid() = 1
Threads.threadid() = 1
julia>
julia> while true
for i in 1:100000
publish(nc, "foo", "This is a payload")
end
sleep(0.001)
end
> > nats bench foo --sub 1 --size 16
13:46:23 Starting Core NATS pub/sub benchmark [subject=foo, multisubject=false, multisubjectmax=0, msgs=100,000, msgsize=16 B, pubs=0, subs=1, pubsleep=0s, subsleep=0s]
13:46:23 Starting subscriber, expecting 100,000 messages
Finished 0s [================] 100%
Sub stats: 904,350 msgs/sec ~ 13.80 MB/sec
0.9M msgs vs 1.2M messages, I think all good here, received messages are buffered and async processed in separate task.
Benchmark NATS.jl subscribe
Supress warnings
julia> using Logging
julia> Logging.LogLevel(Error)
Error
using NATS
nc = NATS.connect(send_buffer_limit = 1000000000)
function subscribe_until_timeout(nc::NATS.Connection, timeout = 1.0)
tm = Timer(timeout)
counter = 0
start = nothing
sub = subscribe(nc, "foo") do
if isnothing(start)
start = time()
end
counter += 1
end
wait(tm)
unsubscribe(nc, sub)
if counter == 0
@info "No messages"
else
@info "Processed $counter messages in $(time() - start) s. $(counter / (time() - start)) msgs/sec)"
end
counter
end
bench_task = @async begin
sub_task = Threads.@spawn :default subscribe_until_timeout(nc, 10.0)
Threads.@spawn :default while !istaskdone(sub_task)
publish(nc, "foo", "This is payload!")
end
wait(sub_task)
sub_task.result
end
_, tm = @timed wait(bench_task);
received_messages = bench_task.result
@info "$(received_messages / tm) msgs / sec"
Start publisher:
> nats bench foo --pub 1 --size 16 --msgs 20000000
13:50:56 Starting Core NATS pub/sub benchmark [subject=foo, multisubject=false, multisubjectmax=0, msgs=20,000,000, msgsize=16 B, pubs=1, subs=0, pubsleep=0s, subsleep=0s]
13:50:56 Starting publisher, publishing 20,000,000 messages
Publishing 3s [==========>-----] 68%
julia> subscribe_for_one_second()
[ Info: Processed 1680882 messages in 0.9680750370025635 s.
1,68M messages in NATS.jl vs 1.7M messages by go client.