Skip to content

Commit a5c5b81

Browse files
committed
Update benchmarks with complete input/output combinations and fresh results
1 parent cde8cc0 commit a5c5b81

2 files changed

Lines changed: 96 additions & 46 deletions

File tree

README.md

Lines changed: 59 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -116,39 +116,70 @@ json = Torque.encode_to_iodata(%{id: "abc"})
116116

117117
## Benchmarks
118118

119-
1.2 KB OpenRTB payload, Apple M2 Pro, OTP 28, Elixir 1.19:
119+
Apple M2 Pro, OTP 28, Elixir 1.19:
120120

121-
### Decode
121+
### Decode (1.2 KB OpenRTB)
122122

123-
| Library | ips | mean | median | p95 | p99 | memory |
124-
|---|---|---|---|---|---|---|
125-
| torque | **255.8K** | **3.91 us** | **3.58 us** | **4.54 us** | **9.21 us** | **1.56 KB** |
126-
| simdjsone | 185.9K | 5.38 us | 5.00 us | 6.38 us | 12.67 us | 1.59 KB |
127-
| jiffy | 152.4K | 6.56 us | 5.83 us | 8.58 us | 15.75 us | **1.56 KB** |
128-
| otp json | 130.9K | 7.64 us | 7.17 us | 9.33 us | 16.50 us | 7.73 KB |
129-
| jason | 109.1K | 9.17 us | 8.54 us | 11.04 us | 18.13 us | 9.54 KB |
123+
| Library | ips | mean | median | p99 | memory |
124+
|---|---|---|---|---|---|
125+
| torque | **255.3K** | **3.92 μs** | **3.71 μs** | **8.58 μs** | **1.56 KB** |
126+
| simdjsone | 186.8K | 5.35 μs | 5.08 μs | 9.83 μs | 1.59 KB |
127+
| jiffy | 147.4K | 6.78 μs | 6.04 μs | 21.17 μs | **1.56 KB** |
128+
| otp json | 127.5K | 7.84 μs | 7.50 μs | 13.54 μs | 7.73 KB |
129+
| jason | 104.1K | 9.61 μs | 8.92 μs | 18.96 μs | 9.54 KB |
130130

131131
### Parse + Get (bidder hot path, 26 fields)
132132

133-
| Library | ips | mean | median | p95 | p99 | memory |
134-
|---|---|---|---|---|---|---|
135-
| torque parse+get_many_nil | **205.8K** | **4.86 us** | **4.29 us** | 5.54 us | **8.88 us** | 1.59 KB |
136-
| torque parse+get_many | 201.2K | 4.97 us | 4.38 us | **5.50 us** | 10.54 us | **1.58 KB** |
137-
| torque parse+get | 159.2K | 6.28 us | 5.67 us | 7.83 us | 13.46 us | 2.80 KB |
138-
| simdjsone parse+get | 126.4K | 7.91 us | 5.88 us | 10.33 us | 30.67 us | 2.28 KB |
139-
140-
### Encode
141-
142-
| Library | ips | mean | median | p95 | p99 | memory |
143-
|---|---|---|---|---|---|---|
144-
| torque encode (proplist) | **869.6K** | **1.15 us** | 1.04 us | 1.29 us | **1.42 us** | 88 B |
145-
| torque iodata (proplist) | 854.7K | 1.17 us | 1.08 us | 1.33 us | 1.46 us | **64 B** |
146-
| torque iodata (map) | 775.2K | 1.29 us | 1.17 us | 1.46 us | 1.63 us | **64 B** |
147-
| torque encode (map) | 800.0K | 1.25 us | 1.17 us | **1.25 us** | 1.50 us | 88 B |
148-
| otp json (iodata) | 735.3K | 1.36 us | **0.83 us** | **1.25 us** | 13.54 us | 3928 B |
149-
| jiffy | 537.6K | 1.86 us | 1.63 us | 2.00 us | 2.29 us | 120 B |
150-
| otp json (binary) | 448.4K | 2.23 us | 1.58 us | 2.63 us | 15.00 us | 3992 B |
151-
| jason | 284.9K | 3.51 us | 2.42 us | 14.63 us | 16.63 us | 3912 B |
133+
| Library | ips | mean | median | p99 | memory |
134+
|---|---|---|---|---|---|
135+
| torque parse+get_many_nil | **207.7K** | **4.82 μs** | **4.38 μs** | **8.71 μs** | 1.59 KB |
136+
| torque parse+get_many | 200.2K | 5.00 μs | 4.46 μs | 10.21 μs | **1.58 KB** |
137+
| torque parse+get | 158.0K | 6.33 μs | 5.75 μs | 13.79 μs | 2.80 KB |
138+
| simdjsone parse+get | 124.5K | 8.03 μs | 6.00 μs | 29.29 μs | 2.28 KB |
139+
140+
### Encode (1.2 KB OpenRTB)
141+
142+
| Library | ips | mean | median | p99 | memory |
143+
|---|---|---|---|---|---|
144+
| otp json: map => iodata | **1078.6K** | **0.93 μs** | **0.88 μs** | 1.42 μs | 3928 B |
145+
| torque: proplist => iodata | 918.3K | 1.09 μs | 1.00 μs | **1.33 μs** | **64 B** |
146+
| torque: proplist => binary | 916.1K | 1.09 μs | 1.00 μs | **1.33 μs** | 88 B |
147+
| torque: map => iodata | 796.2K | 1.26 μs | 1.17 μs | 1.54 μs | **64 B** |
148+
| torque: map => binary | 737.2K | 1.36 μs | 1.21 μs | 1.71 μs | 88 B |
149+
| jason: map => iodata | 606.5K | 1.65 μs | 1.50 μs | 3.04 μs | 3848 B |
150+
| otp json: map => binary | 574.8K | 1.74 μs | 1.54 μs | 4.04 μs | 3992 B |
151+
| jiffy: proplist => iodata | 568.6K | 1.76 μs | 1.54 μs | 2.33 μs | 120 B |
152+
| jiffy: map => iodata | 486.9K | 2.05 μs | 1.88 μs | 2.67 μs | 824 B |
153+
| simdjsone: proplist => iodata | 413.8K | 2.42 μs | 2.13 μs | 3.29 μs | 184 B |
154+
| jason: map => binary | 374.8K | 2.67 μs | 2.38 μs | 6.29 μs | 3912 B |
155+
| simdjsone: map => iodata | 344.9K | 2.90 μs | 2.50 μs | 6.33 μs | 888 B |
156+
157+
### Decode (~758 KB)
158+
159+
| Library | ips | mean | median | p99 | memory |
160+
|---|---|---|---|---|---|
161+
| torque | **485.3** | **2.06 ms** | **1.59 ms** | 3.11 ms | **1.56 KB** |
162+
| simdjsone | 466.6 | 2.14 ms | 1.81 ms | **3.10 ms** | **1.56 KB** |
163+
| otp json | 194.9 | 5.13 ms | 5.19 ms | 5.87 ms | 2.49 MB |
164+
| jason | 135.5 | 7.38 ms | 7.15 ms | 8.76 ms | 3.55 MB |
165+
| jiffy | 108.1 | 9.25 ms | 9.49 ms | 10.24 ms | 5.53 MB |
166+
167+
### Encode (~758 KB)
168+
169+
| Library | ips | mean | median | p99 | memory |
170+
|---|---|---|---|---|---|
171+
| torque: proplist => iodata | **709.9** | **1.41 ms** | **1.40 ms** | **1.53 ms** | **64 B** |
172+
| torque: proplist => binary | 709.4 | **1.41 ms** | 1.41 ms | **1.53 ms** | 88 B |
173+
| torque: map => binary | 637.9 | 1.57 ms | 1.57 ms | 1.69 ms | 88 B |
174+
| torque: map => iodata | 637.5 | 1.57 ms | 1.56 ms | 1.70 ms | **64 B** |
175+
| otp json: map => iodata | 557.6 | 1.79 ms | 1.77 ms | 2.11 ms | 5.40 MB |
176+
| jiffy: proplist => iodata | 328.7 | 3.04 ms | 2.79 ms | 4.01 ms | 37.5 KB |
177+
| jiffy: map => iodata | 289.1 | 3.46 ms | 3.21 ms | 4.48 ms | 1.06 MB |
178+
| otp json: map => binary | 286.8 | 3.49 ms | 3.32 ms | 4.88 ms | 5.40 MB |
179+
| jason: map => iodata | 285.1 | 3.51 ms | 3.49 ms | 4.88 ms | 4.96 MB |
180+
| simdjsone: proplist => iodata | 250.9 | 3.99 ms | 3.75 ms | 4.94 ms | 37.6 KB |
181+
| simdjsone: map => iodata | 232.5 | 4.30 ms | 4.18 ms | 4.84 ms | 1.06 MB |
182+
| jason: map => binary | 191.7 | 5.22 ms | 5.18 ms | 6.90 ms | 4.96 MB |
152183

153184
Run benchmarks locally:
154185

bench/torque_bench.exs

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -210,18 +210,18 @@ IO.puts("\n=== ENCODE BENCHMARK ===\n")
210210

211211
Benchee.run(
212212
%{
213-
"torque encode (map)" => fn -> Torque.encode!(bid_response) end,
214-
"torque encode (proplist)" => fn -> Torque.encode!(bid_response_proplist) end,
215-
"torque iodata (map)" => fn -> Torque.encode_to_iodata(bid_response) end,
216-
"torque iodata (proplist)" => fn -> Torque.encode_to_iodata(bid_response_proplist) end,
217-
"jiffy encode (proplist)" => fn -> :jiffy.encode(bid_response_proplist, [:force_utf8]) end,
218-
"jiffy encode (map)" => fn -> :jiffy.encode(bid_response) end,
219-
"jason encode (map)" => fn -> Jason.encode!(bid_response) end,
220-
"simdjsone encode (map)" => fn -> :simdjson.encode(bid_response) end,
221-
"otp json encode (iodata)" => fn -> :json.encode(bid_response) end,
222-
"otp json encode (binary)" => fn -> :erlang.iolist_to_binary(:json.encode(bid_response)) end,
223-
"simdjsone encode (proplist)" => fn -> :simdjson.encode(bid_response_proplist) end,
224-
"simdjson encode (map)" => fn -> :simdjson.encode(bid_response) end
213+
"torque: map => binary" => fn -> Torque.encode!(bid_response) end,
214+
"torque: proplist => binary" => fn -> Torque.encode!(bid_response_proplist) end,
215+
"torque: map => iodata" => fn -> Torque.encode_to_iodata(bid_response) end,
216+
"torque: proplist => iodata" => fn -> Torque.encode_to_iodata(bid_response_proplist) end,
217+
"jiffy: proplist => iodata" => fn -> :jiffy.encode(bid_response_proplist, [:force_utf8]) end,
218+
"jiffy: map => iodata" => fn -> :jiffy.encode(bid_response) end,
219+
"jason: map => binary" => fn -> Jason.encode!(bid_response) end,
220+
"jason: map => iodata" => fn -> Jason.encode_to_iodata!(bid_response) end,
221+
"simdjsone: map => iodata" => fn -> :simdjson.encode(bid_response) end,
222+
"simdjsone: proplist => iodata" => fn -> :simdjson.encode(bid_response_proplist) end,
223+
"otp json: map => iodata" => fn -> :json.encode(bid_response) end,
224+
"otp json: map => binary" => fn -> :erlang.iolist_to_binary(:json.encode(bid_response)) end
225225
},
226226
warmup: 2,
227227
time: 5,
@@ -365,14 +365,33 @@ IO.puts("\n=== LARGE JSON ENCODE BENCHMARK ===\n")
365365

366366
large_decoded_json = Torque.decode!(large_json)
367367

368+
# Convert to proplist format (binary keys) for libraries that support it
369+
to_proplist = fn f, v ->
370+
cond do
371+
is_map(v) -> {Enum.map(v, fn {k, val} -> {k, f.(f, val)} end)}
372+
is_list(v) -> Enum.map(v, &f.(f, &1))
373+
true -> v
374+
end
375+
end
376+
377+
large_decoded_proplist = to_proplist.(to_proplist, large_decoded_json)
378+
368379
Benchee.run(
369380
%{
370-
"torque encode (map)" => fn -> Torque.encode!(large_decoded_json) end,
371-
"torque iodata (map)" => fn -> Torque.encode_to_iodata(large_decoded_json) end,
372-
"jiffy encode (map)" => fn -> :jiffy.encode(large_decoded_json) end,
373-
"jason encode (map)" => fn -> Jason.encode!(large_decoded_json) end,
374-
"otp json encode (iodata)" => fn -> :json.encode(large_decoded_json) end,
375-
"simdjsone encode (map)" => fn -> :simdjson.encode(large_decoded_json) end
381+
"torque: map => binary" => fn -> Torque.encode!(large_decoded_json) end,
382+
"torque: proplist => binary" => fn -> Torque.encode!(large_decoded_proplist) end,
383+
"torque: map => iodata" => fn -> Torque.encode_to_iodata(large_decoded_json) end,
384+
"torque: proplist => iodata" => fn -> Torque.encode_to_iodata(large_decoded_proplist) end,
385+
"jiffy: proplist => iodata" => fn -> :jiffy.encode(large_decoded_proplist) end,
386+
"jiffy: map => iodata" => fn -> :jiffy.encode(large_decoded_json) end,
387+
"jason: map => binary" => fn -> Jason.encode!(large_decoded_json) end,
388+
"jason: map => iodata" => fn -> Jason.encode_to_iodata!(large_decoded_json) end,
389+
"simdjsone: map => iodata" => fn -> :simdjson.encode(large_decoded_json) end,
390+
"simdjsone: proplist => iodata" => fn -> :simdjson.encode(large_decoded_proplist) end,
391+
"otp json: map => iodata" => fn -> :json.encode(large_decoded_json) end,
392+
"otp json: map => binary" => fn ->
393+
:erlang.iolist_to_binary(:json.encode(large_decoded_json))
394+
end
376395
},
377396
warmup: 2,
378397
time: 5,

0 commit comments

Comments
 (0)