Packages
glazer
0.5.0
0.5.17
0.5.16
0.5.15
0.5.14
retired
0.5.13
retired
0.5.12
retired
0.5.11
retired
0.5.10
retired
0.5.9
retired
0.5.8
retired
0.5.7
retired
0.5.6
retired
0.5.5
retired
0.5.4
retired
0.5.3
retired
0.5.2
retired
0.5.1
retired
0.5.0
retired
0.3.2
retired
0.3.0
retired
0.2.6
retired
0.2.5
retired
0.2.4
retired
0.2.3
retired
0.2.2
retired
0.2.1
retired
0.2.0
retired
0.1.7
retired
0.1.6
retired
0.1.5
retired
0.1.4
retired
Erlang NIF JSON encoder/decoder using the glaze C++ library
Retired package: Deprecated - Deprecated
Current section
31 Versions
Jump to
Current section
31 Versions
Compare versions
20
files changed
+2869
additions
-1638
deletions
| @@ -8,6 +8,13 @@ DEBUG ?= 0 | |
| 8 8 | REBAR ?= rebar3 |
| 9 9 | APP := $(shell sed -nE 's/^\{application, ([a-zA-Z0-9_]+),.*/\1/p' src/*.app.src | head -n1) |
| 10 10 | |
| 11 | + OPTIMIZE ?= 0 |
| 12 | + ifneq ($(filter $(OPTIMIZE),1 true),) |
| 13 | + override OPTIMIZE := 1 |
| 14 | + else |
| 15 | + override OPTIMIZE := 0 |
| 16 | + endif |
| 17 | + |
| 11 18 | all: compile |
| 12 19 | |
| 13 20 | help: |
| @@ -23,6 +30,9 @@ help: | |
| 23 30 | @echo "" |
| 24 31 | @echo "Development:" |
| 25 32 | @echo " test Run eunit test suite" |
| 33 | + @echo " cover Run eunit with coverage analysis and print a summary" |
| 34 | + @echo " check Run xref and dialyzer" |
| 35 | + @echo " dialyzer Run dialyzer" |
| 26 36 | @echo " memcheck Build with ASan (-fsanitize=address) and run eunit (leak=1 adds LSan)" |
| 27 37 | @echo " benchmark Run benchmarks via mix bench" |
| 28 38 | @echo " deps Fetch mix dependencies" |
| @@ -38,6 +48,7 @@ help: | |
| 38 48 | @echo " ASAN=1 Build with AddressSanitizer (implied by memcheck)" |
| 39 49 | @echo " leak=1 Enable LeakSanitizer during memcheck (off by default)" |
| 40 50 | @echo " VERBOSE=1 Show full compiler command lines" |
| 51 | + @echo " OPTIMIZE=1 Make all/compile run the PGO 'optimize' build (same as 'make optimize')" |
| 41 52 | |
| 42 53 | nif: $(PRIV_DIR)/glazer.so |
| 43 54 | |
| @@ -45,8 +56,12 @@ $(PRIV_DIR)/glazer.so: $(wildcard c_src/*.cpp c_src/*.hpp) | |
| 45 56 | @$(MAKE) -C c_src PRIV_DIR=$(PRIV_DIR) OBJ_DIR=$(OBJ_DIR) DEBUG=$(DEBUG) \ |
| 46 57 | $(if $(VERBOSE),VERBOSE=1,) --no-print-directory |
| 47 58 | |
| 59 | + ifeq ($(OPTIMIZE),1) |
| 60 | + compile: optimize |
| 61 | + else |
| 48 62 | compile: $(PRIV_DIR)/glazer.so |
| 49 63 | $(REBAR) compile |
| 64 | + endif |
| 50 65 | |
| 51 66 | clean: |
| 52 67 | $(REBAR) clean |
| @@ -78,7 +93,8 @@ else | |
| 78 93 | DETECT_LEAKS := 1 |
| 79 94 | endif |
| 80 95 | |
| 81 | - check dialyzer: |
| 96 | + check: |
| 97 | + $(REBAR) xref |
| 82 98 | $(REBAR) dialyzer |
| 83 99 | |
| 84 100 | memcheck: |
| @@ -110,8 +126,8 @@ optimize: | |
| 110 126 | @echo "==> PGO step 1/3: build instrumented binary" |
| 111 127 | @$(MAKE) -C c_src PRIV_DIR=$(PRIV_DIR) OBJ_DIR=$(OBJ_DIR) PGO=generate clean all |
| 112 128 | @$(REBAR) compile |
| 113 | - @echo "==> PGO step 2/3: collect profile data via test suite" |
| 114 | - MIX_ENV=bench mix bench-json 1>/dev/null |
| 129 | + @echo "==> PGO step 2/3: collect profile data" |
| 130 | + @./bin/pgo-profile.es |
| 115 131 | @echo "==> PGO step 3/3: rebuild with profile data" |
| 116 132 | @rm -f $(OBJ_DIR)/glazer_nif.o $(PRIV_DIR)/glazer.so |
| 117 133 | @$(MAKE) -C c_src PRIV_DIR=$(PRIV_DIR) OBJ_DIR=$(OBJ_DIR) PGO=use all |
| @@ -131,6 +147,9 @@ deprecate: | |
| 131 147 | fi |
| 132 148 | $(REBAR) hex retire $(APP) $(vsn) deprecated --message Deprecated |
| 133 149 | |
| 150 | + cover: |
| 151 | + $(REBAR) cover --verbose |
| 152 | + |
| 134 153 | bump-version: |
| 135 154 | @FILE=$$(ls -1 src/*.app.src | head -n1); \ |
| 136 155 | CURRENT=$$(grep -m1 '{vsn,' $$FILE | sed -E 's/.*"([0-9]+\.[0-9]+\.[0-9]+)".*/\1/'); \ |
| @@ -148,5 +167,5 @@ bump-version: | |
| 148 167 | git commit -am "Bump version to $${NEW}"; \ |
| 149 168 | fi |
| 150 169 | |
| 151 | - .PHONY: all help doc compile clean distclean test memcheck nif \ |
| 170 | + .PHONY: all help doc compile clean distclean test cover check dialyzer memcheck nif \ |
| 152 171 | optimize benchmark bench publish deprecate bump-version |
| @@ -18,15 +18,14 @@ formats. | |
| 18 18 | |
| 19 19 | ## Performance |
| 20 20 | |
| 21 | - - **[JSON](#performance-1)**: faster encoding than every other library |
| 22 | - benchmarked, and roughly on par with `torque` (Rust `sonic-rs` NIF) on |
| 23 | - decoding — both well ahead of `simdjsone`, `jiffy`, and the pure-Elixir |
| 24 | - libraries `jason`, `thoas`, `euneus`, and OTP's built-in `json`. |
| 25 | - - **[YAML](#benchmarking-yaml)**: an order of magnitude faster than |
| 26 | - `yaml_rustler` and `fast_yaml`, and ~10-100x faster than the pure-Erlang |
| 27 | - `yamerl`/`ymlr`. |
| 28 | - - **[CSV](#benchmarking-csv)**: 2-20x faster than `nimble_csv`, and tens to |
| 29 | - hundreds of times faster than `csv` and `erl_csv` (which times out on |
| 21 | + - **[JSON](#performance-1)**: faster than every other library benchmarked on |
| 22 | + both encoding and decoding — consistently ~25–40% ahead of `torque` |
| 23 | + (Rust `sonic-rs` NIF), and well ahead of `simdjsone`, `jiffy`, and the |
| 24 | + pure-Elixir libraries `jason`, `thoas`, `euneus`, and OTP's built-in `json`. |
| 25 | + - **[YAML](#benchmarking-yaml)**: 2–7× faster than `yaml_rustler` and |
| 26 | + `fast_yaml`, and ~25–75× faster than the pure-Erlang `yamerl`/`ymlr`. |
| 27 | + - **[CSV](#benchmarking-csv)**: 4–12× faster than `nimble_csv`, and tens to |
| 28 | + hundreds of times faster than `csv` and `erl_csv` (which time out on |
| 30 29 | large inputs). |
| 31 30 | |
| 32 31 | <img src="assets/bench_small.svg" width="100%" alt="Small file benchmarks (JSON/YAML/CSV)"/> |
| @@ -49,14 +48,17 @@ Benchmark tables: | |
| 49 48 | (including bignums), floats, booleans, and `null` |
| 50 49 | - Encoding Erlang terms straight to JSON, including big integers |
| 51 50 | - Incremental/streaming decoding of partial input (e.g. NDJSON over a |
| 52 | - socket) via `json_stream_decoder/0,1`, `json_stream_feed/2`, `json_stream_eof/1` |
| 51 | + socket) via `stream_decoder/0,1`, `stream_feed/2`, `stream_eof/1` |
| 53 52 | - Configurable representation of JSON `null` and JSON object keys |
| 54 | - - `json_minify/1` and `json_prettify/1` helpers |
| 53 | + - `minify/1` and `prettify/1` helpers |
| 55 54 | - Standalone big-integer encode/decode helpers |
| 56 55 | (`encode_integer/1`, `decode_integer/1`, `try_decode_integer/1`) |
| 57 | - - `json_query/2,3`: run a [jq](https://jqlang.org/) filter over a JSON |
| 56 | + - `query/2,3`: run a [jq](https://jqlang.org/) filter over a JSON |
| 58 57 | document, returning decoded Erlang terms (requires `glazer` to be built |
| 59 58 | with `libjq` available — see [jq filter support](#jq-filter-support)) |
| 59 | + - `glazer:find/2` and `glazer:compile_path/1`: look up value(s) in a |
| 60 | + decoded term using a small subset of jq path syntax (`.a.b[].c[0]`), |
| 61 | + with no `libjq` dependency |
| 60 62 | |
| 61 63 | ### YAML |
| 62 64 | |
| @@ -68,10 +70,10 @@ Benchmark tables: | |
| 68 70 | |
| 69 71 | ### CSV |
| 70 72 | |
| 71 | - - RFC 4180 CSV encoding/decoding via `csv_decode/1,2` and `csv_encode/1,2`, |
| 73 | + - RFC 4180 CSV encoding/decoding via `decode/1,2` and `encode/1,2`, |
| 72 74 | with optional header-row support |
| 73 | - - Incremental/streaming CSV decoding via `csv_stream_decoder/0,1`, |
| 74 | - `csv_stream_feed/2`, `csv_stream_eof/1` |
| 75 | + - Incremental/streaming CSV decoding via `stream_decoder/0,1`, |
| 76 | + `stream_feed/2`, `stream_eof/1` |
| 75 77 | |
| 76 78 | ## Scope |
| 77 79 | |
| @@ -136,37 +138,38 @@ Once compiled, call it via the `:glazer` module from Elixir: | |
| 136 138 | |
| 137 139 | **Erlang:** |
| 138 140 | ```erlang |
| 139 | - 1> glazer:json_decode(~"{\"a\":1,\"b\":[true,null,3.5]}") |
| 141 | + 1> glazer_json:decode(~"{\"a\":1,\"b\":[true,null,3.5]}") |
| 140 142 | #{<<"a">> => 1,<<"b">> => [true,null,3.5]} |
| 141 143 | ``` |
| 142 144 | |
| 143 145 | **Elixir:** |
| 144 146 | ```elixir |
| 145 | - iex> :glazer.json_encode(%{"a" => 1, "b" => [true, :null, 3.5]}) |
| 147 | + iex> :glazer_json.encode(%{"a" => 1, "b" => [true, :null, 3.5]}) |
| 146 148 | "{\"a\":1,\"b\":[true,null,3.5]}" |
| 147 149 | ``` |
| 148 150 | |
| 149 | - Use the `use_nil`/`{null_term, nil}` option (see [JSON `null`](#json-null) |
| 150 | - below) to get idiomatic Elixir `nil` instead of the atom `:null`. |
| 151 | + Use the `use_nil`/`{null_term, nil}` option (see |
| 152 | + [Null term configuration](#null-term-configuration) below) to get idiomatic |
| 153 | + Elixir `nil` instead of the atom `:null`. |
| 151 154 | |
| 152 155 | ## JSON |
| 153 156 | |
| 154 157 | ### Usage |
| 155 158 | |
| 156 159 | ```erlang |
| 157 | - 1> glazer:json_decode(<<"{\"a\":1,\"b\":[true,null,3.5]}">>). |
| 160 | + 1> glazer_json:decode(<<"{\"a\":1,\"b\":[true,null,3.5]}">>). |
| 158 161 | #{<<"a">> => 1, <<"b">> => [true, null, 3.5]} |
| 159 162 | |
| 160 | - 2> glazer:json_encode(#{<<"a">> => 1, <<"b">> => [true, null, 3.5]}). |
| 163 | + 2> glazer_json:encode(#{<<"a">> => 1, <<"b">> => [true, null, 3.5]}). |
| 161 164 | <<"{\"a\":1,\"b\":[true,null,3.5]}">> |
| 162 165 | |
| 163 | - 3> glazer:json_encode(#{a => 1}, [pretty]). |
| 166 | + 3> glazer_json:encode(#{a => 1}, [pretty]). |
| 164 167 | <<"{\n \"a\": 1\n}">> |
| 165 168 | |
| 166 | - 4> glazer:json_minify(<<" { \"a\" : 1 } ">>). |
| 169 | + 4> glazer_json:minify(<<" { \"a\" : 1 } ">>). |
| 167 170 | {ok, <<"{\"a\":1}">>} |
| 168 171 | |
| 169 | - 5> glazer:json_prettify(<<"{\"a\":1}">>). |
| 172 | + 5> glazer_json:prettify(<<"{\"a\":1}">>). |
| 170 173 | {ok, <<"{\n \"a\": 1\n}">>} |
| 171 174 | ``` |
| 172 175 | |
| @@ -174,55 +177,55 @@ below) to get idiomatic Elixir `nil` instead of the atom `:null`. | |
| 174 177 | |
| 175 178 | For input that arrives in chunks — e.g. reading a large document |
| 176 179 | incrementally, or consuming newline-delimited JSON (NDJSON) from a |
| 177 | - socket or file — `json_stream_decoder/0,1` provides a small stateful |
| 180 | + socket or file — `stream_decoder/0,1` provides a small stateful |
| 178 181 | wrapper that buffers partial input and decodes each JSON value as soon |
| 179 182 | as it's complete, without re-parsing bytes you've already seen: |
| 180 183 | |
| 181 184 | ```erlang |
| 182 | - 1> D0 = glazer:json_stream_decoder(), |
| 183 | - 2> {Vals1, D1} = glazer:json_stream_feed(D0, <<"{\"a\":1} {\"b\":">>), |
| 185 | + 1> D0 = glazer_json:stream_decoder(), |
| 186 | + 2> {Vals1, D1} = glazer_json:stream_feed(D0, <<"{\"a\":1} {\"b\":">>), |
| 184 187 | 3> Vals1. |
| 185 188 | [#{<<"a">> => 1}] |
| 186 189 | |
| 187 | - 4> {Vals2, D2} = glazer:json_stream_feed(D1, <<"2}">>), |
| 190 | + 4> {Vals2, D2} = glazer_json:stream_feed(D1, <<"2}">>), |
| 188 191 | 5> Vals2. |
| 189 192 | [#{<<"b">> => 2}] |
| 190 193 | |
| 191 | - 6> glazer:json_stream_eof(D2). |
| 194 | + 6> glazer_json:stream_eof(D2). |
| 192 195 | {ok, []} |
| 193 196 | ``` |
| 194 197 | |
| 195 | - `json_stream_feed/2` returns the list of values completed by the chunk just |
| 198 | + `stream_feed/2` returns the list of values completed by the chunk just |
| 196 199 | fed (possibly empty, possibly more than one if the chunk completes |
| 197 200 | several values) along with the updated decoder state to pass to the |
| 198 | - next call. Once the input is exhausted, call `json_stream_eof/1` to flush |
| 201 | + next call. Once the input is exhausted, call `stream_eof/1` to flush |
| 199 202 | any trailing bare scalar (numbers, strings, etc. have no closing |
| 200 203 | delimiter of their own) and surface an error if the buffer holds an |
| 201 204 | incomplete value: |
| 202 205 | |
| 203 206 | ```erlang |
| 204 | - 1> D0 = glazer:json_stream_decoder(), |
| 205 | - 2> {[], D1} = glazer:json_stream_feed(D0, <<" 42">>), |
| 206 | - 3> glazer:json_stream_eof(D1). |
| 207 | + 1> D0 = glazer_json:stream_decoder(), |
| 208 | + 2> {[], D1} = glazer_json:stream_feed(D0, <<" 42">>), |
| 209 | + 3> glazer_json:stream_eof(D1). |
| 207 210 | {ok, [42]} |
| 208 211 | ``` |
| 209 212 | |
| 210 | - `json_stream_decoder/1` accepts the same options as `json_decode/2` (e.g. |
| 213 | + `stream_decoder/1` accepts the same options as `decode/2` (e.g. |
| 211 214 | `{keys, atom}`, `use_nil`) and applies them to every decoded value. |
| 212 215 | |
| 213 | - A typical read loop calls `json_stream_feed/2` for each chunk while more data |
| 214 | - may still arrive, and `json_stream_eof/1` once the socket closes to flush any |
| 216 | + A typical read loop calls `stream_feed/2` for each chunk while more data |
| 217 | + may still arrive, and `stream_eof/1` once the socket closes to flush any |
| 215 218 | trailing value: |
| 216 219 | |
| 217 220 | ```erlang |
| 218 221 | loop(Socket, D0) -> |
| 219 222 | case gen_tcp:recv(Socket, 0) of |
| 220 223 | {ok, Chunk} -> |
| 221 | - {Vals, D1} = glazer:json_stream_feed(D0, Chunk), |
| 224 | + {Vals, D1} = glazer_json:stream_feed(D0, Chunk), |
| 222 225 | handle_values(Vals), |
| 223 226 | loop(Socket, D1); |
| 224 227 | {error, closed} -> |
| 225 | - case glazer:json_stream_eof(D0) of |
| 228 | + case glazer_json:stream_eof(D0) of |
| 226 229 | {ok, Trailing} -> handle_values(Trailing); |
| 227 230 | {error, Reason} -> handle_truncated_stream(Reason) |
| 228 231 | end |
| @@ -231,49 +234,51 @@ loop(Socket, D0) -> | |
| 231 234 | |
| 232 235 | #### Efficiency |
| 233 236 | |
| 234 | - `json_stream_feed/2` only scans for value *boundaries* incrementally — |
| 237 | + `stream_feed/2` only scans for value *boundaries* incrementally — |
| 235 238 | the scanner carries a small resumable cursor (`scan_state()`) that |
| 236 239 | remembers how far it has already looked (nesting depth, whether it's |
| 237 | - inside a string, escape state, …), so each call to `json_scan/2` resumes |
| 240 | + inside a string, escape state, …), so each call to `scan/2` resumes |
| 238 241 | from where the previous one left off rather than re-walking the whole |
| 239 242 | buffer from byte zero. Once a complete value's end offset is known, |
| 240 243 | that slice is decoded exactly once via the same NIF-backed decoder |
| 241 | - used by `json_decode/2` — there's no intermediate tokenization or tree |
| 244 | + used by `decode/2` — there's no intermediate tokenization or tree |
| 242 245 | representation, and no byte is ever scanned or decoded twice. The only |
| 243 246 | buffering cost is concatenating newly-arrived chunks onto the |
| 244 247 | not-yet-complete tail of the input. |
| 245 248 | |
| 246 | - This makes `json_stream_feed/2` well suited to byte-at-a-time or |
| 249 | + This makes `stream_feed/2` well suited to byte-at-a-time or |
| 247 250 | small-chunk feeding (e.g. consuming a `gen_tcp`/`gen_statem` socket |
| 248 251 | buffer as it fills) without the quadratic-rescan cost a naive |
| 249 252 | "concatenate and retry full decode" loop would incur on large or |
| 250 253 | slow-arriving documents. |
| 251 254 | |
| 252 | - Under the hood, `json_stream_feed/2` is built on `json_scan/1,2` — a low-level |
| 255 | + Under the hood, `stream_feed/2` is built on `scan/1,2` — a low-level |
| 253 256 | primitive that scans a buffer for the byte offset where the next JSON |
| 254 257 | value ends (or reports that more input is needed) without doing a full |
| 255 258 | decode. It's exposed directly for callers that want to implement their |
| 256 259 | own framing/buffering strategy: |
| 257 260 | |
| 258 261 | ```erlang |
| 259 | - 1> glazer:json_scan(<<"{\"a\":1} {\"b\":2}">>). |
| 262 | + 1> glazer_json:scan(<<"{\"a\":1} {\"b\":2}">>). |
| 260 263 | {complete, 7} |
| 261 264 | |
| 262 | - 2> glazer:json_scan(<<"{\"a\":">>). |
| 265 | + 2> glazer_json:scan(<<"{\"a\":">>). |
| 263 266 | {incomplete, ScanState} |
| 264 267 | |
| 265 | - 3> glazer:json_scan(<<"{\"a\":1}">>, ScanState). |
| 268 | + 3> glazer_json:scan(<<"{\"a\":1}">>, ScanState). |
| 266 269 | {complete, 7} |
| 267 270 | ``` |
| 268 271 | |
| 269 | - `json_stream_decoder/0,1`, `json_stream_feed/2`, `json_stream_eof/1` and |
| 270 | - `json_scan/1,2` are JSON-only — see [YAML streaming](#streaming-1) and |
| 272 | + `stream_decoder/0,1`, `stream_feed/2`, `stream_eof/1` and |
| 273 | + `scan/1,2` are JSON-only — see [YAML streaming](#streaming-1) and |
| 271 274 | [CSV streaming](#streaming-2) below for the other formats. |
| 272 275 | |
| 273 | - ### JSON `null` |
| 276 | + ### Null term configuration |
| 274 277 | |
| 275 | - By default, JSON `null` decodes to (and `null` encodes from) the atom |
| 276 | - `null`. This can be overridden: |
| 278 | + By default, JSON/YAML `null` decodes to (and `null` encodes from) the atom |
| 279 | + `null`, and this same atom is used as the default null term throughout the |
| 280 | + library (e.g. for the CSV `on_failure => null` field option). This can be |
| 281 | + overridden: |
| 277 282 | |
| 278 283 | - Application-wide, via the `null` environment key — set this once in |
| 279 284 | the application's config and every call uses it as the default: |
| @@ -289,11 +294,11 @@ By default, JSON `null` decodes to (and `null` encodes from) the atom | |
| 289 294 | ``` |
| 290 295 | |
| 291 296 | - Per call, with the `use_nil` shorthand or the `{null_term, Atom}` |
| 292 | - option (see [Decode options](#decode-options-json_decode2) below). |
| 297 | + option (see [Decode options](#decode-options-glazer_jsondecode2) below). |
| 293 298 | Per-call options always take precedence over the application-wide |
| 294 299 | default. |
| 295 300 | |
| 296 | - ### Decode options (`json_decode/2`) |
| 301 | + ### Decode options (`glazer_json:decode/2`) |
| 297 302 | |
| 298 303 | | Option | Description | |
| 299 304 | |---|---| |
| @@ -306,25 +311,25 @@ By default, JSON `null` decodes to (and `null` encodes from) the atom | |
| 306 311 | | `dedupe_keys` | With `object_as_tuple`, eliminate duplicate object keys, keeping the last occurrence's value (and position) | |
| 307 312 | |
| 308 313 | ```erlang |
| 309 | - 1> glazer:json_decode(<<"{\"a\":1}">>, [object_as_tuple]). |
| 314 | + 1> glazer_json:decode(<<"{\"a\":1}">>, [object_as_tuple]). |
| 310 315 | {[{<<"a">>, 1}]} |
| 311 316 | |
| 312 | - 2> glazer:json_decode(<<"{\"a\":1}">>, [{keys, atom}]). |
| 317 | + 2> glazer_json:decode(<<"{\"a\":1}">>, [{keys, atom}]). |
| 313 318 | #{a => 1} |
| 314 319 | |
| 315 | - 3> glazer:json_decode(<<"null">>, [use_nil]). |
| 320 | + 3> glazer_json:decode(<<"null">>, [use_nil]). |
| 316 321 | nil |
| 317 322 | |
| 318 | - 4> glazer:json_decode(<<"null">>, [{null_term, undefined}]). |
| 323 | + 4> glazer_json:decode(<<"null">>, [{null_term, undefined}]). |
| 319 324 | undefined |
| 320 325 | |
| 321 | - 5> glazer:json_decode(<<"{\"a\":1,\"a\":2}">>). |
| 326 | + 5> glazer_json:decode(<<"{\"a\":1,\"a\":2}">>). |
| 322 327 | #{<<"a">> => 2} |
| 323 328 | |
| 324 | - 6> glazer:json_decode(<<"{\"a\":1,\"a\":2}">>, [object_as_tuple]). |
| 329 | + 6> glazer_json:decode(<<"{\"a\":1,\"a\":2}">>, [object_as_tuple]). |
| 325 330 | {[{<<"a">>, 1}, {<<"a">>, 2}]} |
| 326 331 | |
| 327 | - 7> glazer:json_decode(<<"{\"a\":1,\"a\":2}">>, [object_as_tuple, dedupe_keys]). |
| 332 | + 7> glazer_json:decode(<<"{\"a\":1,\"a\":2}">>, [object_as_tuple, dedupe_keys]). |
| 328 333 | {[{<<"a">>, 2}]} |
| 329 334 | ``` |
| 330 335 | |
| @@ -335,7 +340,7 @@ undefined | |
| 335 340 | > `object_as_tuple`, duplicate keys are preserved as-is unless `dedupe_keys` |
| 336 341 | > is given. |
| 337 342 | |
| 338 | - ### Encode options (`json_encode/2`) |
| 343 | + ### Encode options (`glazer_json:encode/2`) |
| 339 344 | |
| 340 345 | | Option | Description | |
| 341 346 | |---|---| |
| @@ -346,60 +351,64 @@ undefined | |
| 346 351 | | `{null_term, Atom}` | Encode `Atom` as JSON `null` | |
| 347 352 | |
| 348 353 | ```erlang |
| 349 | - 1> glazer:json_encode(#{a => 1}, [pretty]). |
| 354 | + 1> glazer_json:encode(#{a => 1}, [pretty]). |
| 350 355 | <<"{\n \"a\": 1\n}">> |
| 351 356 | |
| 352 | - 2> glazer:json_encode(<<"héllo"/utf8>>, [uescape]). |
| 357 | + 2> glazer_json:encode(<<"héllo"/utf8>>, [uescape]). |
| 353 358 | <<"\"h\\u00e9llo\"">> |
| 354 359 | |
| 355 | - 3> glazer:json_encode(nil, [use_nil]). |
| 360 | + 3> glazer_json:encode(nil, [use_nil]). |
| 356 361 | <<"null">> |
| 357 362 | ``` |
| 358 363 | |
| 359 364 | ### jq filter support |
| 360 365 | |
| 361 366 | If [`libjq`](https://jqlang.org/) and its headers (`jq.h`/`jv.h`) are |
| 362 | - available when `glazer` is built, `json_query/2,3` runs a jq filter |
| 367 | + available when `glazer` is built, `query/2,3` runs a jq filter |
| 363 368 | program against a JSON document and returns one Erlang term per value |
| 364 369 | produced by the filter (decoded using the same options as |
| 365 | - `json_decode/2`): |
| 370 | + `decode/2`): |
| 366 371 | |
| 367 372 | ```erlang |
| 368 | - 1> glazer:json_query(<<"{\"a\":[1,2,3]}">>, <<".a[]">>). |
| 373 | + 1> glazer_json:query(<<"{\"a\":[1,2,3]}">>, <<".a[]">>). |
| 369 374 | {ok, [1, 2, 3]} |
| 370 375 | |
| 371 | - 2> glazer:json_query(<<"{\"a\":1}">>, <<".b">>). |
| 376 | + 2> glazer_json:query(<<"{\"a\":1}">>, <<".b">>). |
| 372 377 | {ok, [null]} |
| 373 378 | |
| 374 | - 3> glazer:json_query(<<"{\"a\":{\"b\":2}}">>, <<".">>, [{keys, atom}]). |
| 379 | + 3> glazer_json:query(<<"{\"a\":{\"b\":2}}">>, <<".">>, [{keys, atom}]). |
| 375 380 | {ok, [#{a => #{b => 2}}]} |
| 376 381 | |
| 377 | - 4> glazer:json_query(<<"not json">>, <<".">>). |
| 382 | + 4> glazer_json:query(<<"not json">>, <<".">>). |
| 378 383 | {error, invalid_input} |
| 379 384 | |
| 380 | - 5> glazer:json_query(<<"{\"a\":1}">>, <<"bad syntax (((">>). |
| 385 | + 5> glazer_json:query(<<"{\"a\":1}">>, <<"bad syntax (((">>). |
| 381 386 | {error, jq_decode_error} |
| 382 387 | ``` |
| 383 388 | |
| 384 | - If `libjq` was not available at build time, `json_query/2,3` returns |
| 389 | + If `libjq` was not available at build time, `query/2,3` returns |
| 385 390 | `{error, jq_not_available}`. Build detection is automatic — `make` probes |
| 386 391 | for `jq.h`/`libjq` and only enables this feature if found, so `glazer` |
| 387 392 | still builds and works without `libjq` installed. |
| 388 393 | |
| 389 394 | ### API |
| 390 395 | |
| 396 | + All functions below are in `glazer_json`. |
| 397 | + |
| 391 398 | | Function | Description | |
| 392 399 | |---|---| |
| 393 | - | `json_decode/1`, `json_decode/2` | Decode a JSON binary or iolist to an Erlang term | |
| 394 | - | `json_try_decode/1`, `json_try_decode/2` | Decode a JSON binary or iolist, returning `{ok, Term}` or `{error, {parse_error, Msg}}` instead of raising | |
| 395 | - | `json_encode/1`, `json_encode/2` | Encode an Erlang term to a JSON binary | |
| 396 | - | `json_minify/1` | Remove unnecessary whitespace from a JSON document | |
| 397 | - | `json_prettify/1` | Pretty-print a JSON document with two-space indentation | |
| 398 | - | `json_scan/1`, `json_scan/2` | Scan a buffer for the end offset of the next complete JSON value | |
| 399 | - | `json_stream_decoder/0`, `json_stream_decoder/1` | Create an incremental-decode state for chunked input | |
| 400 | - | `json_stream_feed/2` | Feed a chunk to a stream decoder, returning completed values | |
| 401 | - | `json_stream_eof/1` | Flush a stream decoder at end-of-input | |
| 402 | - | `json_query/2`, `json_query/3` | Run a [jq](https://jqlang.org/) filter over a JSON document, returning `{ok, [Term]}` (requires `libjq`) | |
| 400 | + | `decode/1`, `decode/2` | Decode a JSON binary or iolist to an Erlang term | |
| 401 | + | `try_decode/1`, `try_decode/2` | Decode a JSON binary or iolist, returning `{ok, Term}` or `{error, {parse_error, Msg}}` instead of raising | |
| 402 | + | `encode/1`, `encode/2` | Encode an Erlang term to a JSON binary | |
| 403 | + | `minify/1` | Remove unnecessary whitespace from a JSON document | |
| 404 | + | `prettify/1` | Pretty-print a JSON document with two-space indentation | |
| 405 | + | `read_file/1`, `read_file/2` | Read a file and decode its contents as JSON | |
| 406 | + | `write_file/2`, `write_file/3` | Encode a term to JSON and write it to a file | |
| 407 | + | `scan/1`, `scan/2` | Scan a buffer for the end offset of the next complete JSON value | |
| 408 | + | `stream_decoder/0`, `stream_decoder/1` | Create an incremental-decode state for chunked input | |
| 409 | + | `stream_feed/2` | Feed a chunk to a stream decoder, returning completed values | |
| 410 | + | `stream_eof/1` | Flush a stream decoder at end-of-input | |
| 411 | + | `query/2`, `query/3` | Run a [jq](https://jqlang.org/) filter over a JSON document, returning `{ok, [Term]}` (requires `libjq`) | |
| 403 412 | |
| 404 413 | ### Benchmarking JSON |
| 405 414 | |
| @@ -412,30 +421,28 @@ $ PARALLEL=2 make bench | |
| 412 421 | ==> Running benchmarks with parallelism: 2 |
| 413 422 | |
| 414 423 | (numbers in µs) |
| 415 | - JSON twitter (616.7K) twitter2 (758.0K) openrtb (1.2K) esad (1.3K) small (0.1K) |
| 416 | - decode encode decode encode decode encode decode encode decode encode |
| 424 | + JSON twitter (616.7K) twitter2 (758.0K) openrtb (1.2K) esad (1.3K) small (0.1K) |
| 425 | + decode encode decode encode decode encode decode encode decode encode |
| 417 426 | ------------------------------------------------------------------------------------------------------------- |
| 418 | - glazer 3876.2 1205.8 4716.9 1971.3 9.1 3.7 5.8 2.9 0.9 0.8 |
| 419 | - torque 5140.3 1333.7 4468.8 4411.4 9.3 5.5 4.9 3.5 1.8 1.4 |
| 420 | - simdjsone 4652.9 3564.3 7426.9 6236.6 10.2 13.5 7.7 8.4 1.2 2.1 |
| 421 | - jiffy 5921.4 2547.3 7974.6 4654.6 11.1 11.4 7.9 6.2 1.8 1.9 |
| 422 | - jason 10040.8 8237.9 18594.6 17591.8 23.4 21.9 16.3 20.6 2.8 2.2 |
| 423 | - thoas 10245.4 9117.9 19040.7 18598.2 23.7 23.5 19.6 21.2 2.6 2.3 |
| 424 | - euneus 10446.2 6845.7 14069.1 12934.7 20.8 15.5 11.9 9.5 3.1 2.1 |
| 425 | - json 10061.2 6563.0 13467.7 12629.6 19.6 16.0 11.1 8.3 2.5 1.8 |
| 427 | + glazer 4379.2 1143.4 5132.9 2586.7 7.5 8.7 6.7 4.0 1.2 1.0 |
| 428 | + torque 6089.2 1643.8 8087.6 3091.0 10.7 9.8 9.3 6.2 1.7 1.3 |
| 429 | + simdjsone 5847.3 5019.7 8719.8 8620.6 14.4 17.7 12.1 12.6 1.9 3.6 |
| 430 | + jiffy 7868.6 3615.6 9779.9 6532.6 16.8 15.2 12.4 9.1 2.5 3.8 |
| 431 | + jason 13509.0 11248.6 25267.6 20837.6 33.5 30.0 19.7 25.0 4.4 2.9 |
| 432 | + thoas 13679.7 12466.1 25638.7 22607.2 31.2 33.0 25.1 29.9 3.2 3.9 |
| 433 | + euneus 14699.8 10247.2 18646.5 16886.6 29.1 25.2 16.7 14.6 4.0 4.6 |
| 434 | + json 14315.5 9718.9 17844.3 16473.5 28.3 25.3 19.2 12.3 4.0 4.5 |
| 426 435 | ``` |
| 427 436 | |
| 428 437 | (requires the `bench`/`dev` Mix dependencies — see `mix.exs`). |
| 429 438 | |
| 430 439 | ### Performance |
| 431 440 | |
| 432 | - `glazer` has a faster JSON encoder than all competitors. `glazer` is roughly on |
| 433 | - par with `torque` (a Rust `sonic-rs` NIF) across the benchmarked workloads on |
| 434 | - decoding — neither library is consistently faster, and the gap on any given |
| 435 | - file/operation is typically modest (within ~30%), varying in direction from |
| 436 | - file to file. Both sit well ahead of the other contenders (`simdjsone`, |
| 437 | - `jiffy`, and the pure-Elixir libraries `jason`, `thoas`, `euneus`, and OTP's |
| 438 | - built-in `json`). |
| 441 | + `glazer` is faster than all competitors on both encoding and decoding. |
| 442 | + On decoding it leads `torque` (Rust `sonic-rs` NIF) by ~25–40% across every |
| 443 | + benchmarked workload, and on encoding by ~10–30%. Both sit well ahead of |
| 444 | + the remaining contenders (`simdjsone`, `jiffy`, and the pure-Elixir libraries |
| 445 | + `jason`, `thoas`, `euneus`, and OTP's built-in `json`). |
| 439 446 | |
| 440 447 | Where `glazer` has an edge over `torque`: |
| 441 448 | |
| @@ -453,7 +460,7 @@ Where `glazer` has an edge over `torque`: | |
| 453 460 | - **`uescape`/`force_utf8` encode options** for `\uXXXX`-escaping non-ASCII |
| 454 461 | output and sanitizing invalid UTF-8 — useful when targeting strict JSON |
| 455 462 | consumers or transports that aren't UTF-8 clean. |
| 456 | - - **Standalone `json_minify/1`/`json_prettify/1` and big-integer helpers** |
| 463 | + - **Standalone `minify/1`/`prettify/1` and big-integer helpers** |
| 457 464 | (`encode_integer/1`/`decode_integer/1`/`try_decode_integer/1`) that don't |
| 458 465 | require a full decode/encode round-trip. |
| 459 466 | - **No external C++ dependencies.** The NIF is fully self-contained — |
| @@ -501,19 +508,30 @@ of the gap over the slower contenders: | |
| 501 508 | coincidentally look live). This makes cache construction effectively |
| 502 509 | free, regardless of table size. |
| 503 510 | |
| 511 | + - **SIMD string scanning.** The JSON string decoder and encoder use an |
| 512 | + AVX2 → SSE2 → SWAR cascade to skip over clean byte spans 32, 16, or 8 |
| 513 | + bytes at a time. The decoder scans for `"` and `\` (the only stop bytes |
| 514 | + in clean strings); the encoder additionally detects control characters |
| 515 | + (`c < 0x20`) via a bias trick that maps unsigned `< 0x20` to a signed |
| 516 | + comparison, avoiding a branch-per-byte table lookup for the common |
| 517 | + all-ASCII case. The same cascade is used by the CSV unquoted-field |
| 518 | + scanner (`delimiter | LF | CR`) and the YAML double-quoted scalar scanner |
| 519 | + (`"`, `\`, `LF`, `CR`), as well as single-character finders consolidated |
| 520 | + in `glazer_common.hpp` (`find_byte`). On AVX2 hardware (Haswell+) this |
| 521 | + processes up to 32 bytes per iteration instead of 1. |
| 522 | + |
| 504 523 | - **SWAR whitespace skipping.** `skip_ws` checks the next byte before |
| 505 524 | paying for any wider load, then — for runs of whitespace — scans 8 bytes |
| 506 525 | at a time using branch-free bit-twiddling ("SIMD within a register") to |
| 507 | - find the first non-whitespace byte, rather than testing one byte at a |
| 508 | - time. Minified JSON (the overwhelmingly common case) has little or no |
| 509 | - structural whitespace, so the single-byte fast path dominates in |
| 510 | - practice. |
| 526 | + find the first non-whitespace byte. Minified JSON (the overwhelmingly |
| 527 | + common case) has little or no structural whitespace, so the single-byte |
| 528 | + fast path dominates; the 8-byte path handles pretty-printed inputs. |
| 511 529 | |
| 512 530 | - **Table-driven string escaping with bulk copies.** JSON string escaping |
| 513 | - scans for runs of bytes that need no escaping (a precomputed 256-entry |
| 514 | - lookup table answers "does this byte need escaping?" in O(1)) and copies |
| 515 | - each run in one `memcpy`, falling into a per-byte switch only for the |
| 516 | - rare characters that actually need an escape sequence. |
| 531 | + locates the next byte needing escaping in bulk (via the SIMD scanner |
| 532 | + above), copies the clean prefix in one `memcpy`, then falls into a |
| 533 | + per-byte switch only for the rare characters that actually need an escape |
| 534 | + sequence. |
| 517 535 | |
| 518 536 | - **Fast integer formatting.** Integers are written to JSON using a |
| 519 537 | lookup-table-based digit-pair algorithm (avoiding division for small |
| @@ -524,19 +542,19 @@ of the gap over the slower contenders: | |
| 524 542 | |
| 525 543 | ### Usage |
| 526 544 | |
| 527 | - `yaml_decode/1,2` decodes a YAML document to an Erlang term — mappings |
| 545 | + `decode/1,2` decodes a YAML document to an Erlang term — mappings |
| 528 546 | become maps, sequences become lists, and scalars become the matching |
| 529 547 | Erlang type (binaries, numbers, booleans, or `null`): |
| 530 548 | |
| 531 549 | ```erlang |
| 532 | - 1> glazer:yaml_decode(<<"a: 1\nb:\n - true\n - null\n - 3.5\n">>). |
| 550 | + 1> glazer_yaml:decode(<<"a: 1\nb:\n - true\n - null\n - 3.5\n">>). |
| 533 551 | #{<<"a">> => 1, <<"b">> => [true, null, 3.5]} |
| 534 552 | |
| 535 | - 2> glazer:yaml_encode(#{<<"a">> => 1, <<"b">> => [true, null, 3.5]}). |
| 553 | + 2> glazer_yaml:encode(#{<<"a">> => 1, <<"b">> => [true, null, 3.5]}). |
| 536 554 | <<"a: 1\nb:\n - true\n - null\n - 3.5\n">> |
| 537 555 | ``` |
| 538 556 | |
| 539 | - `yaml_encode/1,2` encodes an Erlang term to YAML in block style |
| 557 | + `encode/1,2` encodes an Erlang term to YAML in block style |
| 540 558 | (2-space indentation, sequences at the same indentation as the mapping |
| 541 559 | key that owns them). |
| 542 560 | |
| @@ -545,11 +563,11 @@ key that owns them). | |
| 545 563 | There is no incremental YAML decoder. YAML's block styles have no |
| 546 564 | closing delimiter — a mapping or sequence simply ends at a dedent or |
| 547 565 | end-of-input — so there is no way to scan a partial buffer for "is this |
| 548 | - value complete yet?" the way [`json_scan/1,2`](#efficiency) does for |
| 566 | + value complete yet?" the way [`scan/1,2`](#efficiency) does for |
| 549 567 | JSON's bracket-balanced syntax. Decode full YAML documents with |
| 550 | - `yaml_decode/1,2` once they are fully buffered. |
| 568 | + `decode/1,2` once they are fully buffered. |
| 551 569 | |
| 552 | - ### Decode options (`yaml_decode/2`) |
| 570 | + ### Decode options (`glazer_yaml:decode/2`) |
| 553 571 | |
| 554 572 | | Option | Description | |
| 555 573 | |---|---| |
| @@ -561,17 +579,17 @@ JSON's bracket-balanced syntax. Decode full YAML documents with | |
| 561 579 | | `yaml_1_1_bools` | Additionally treat `yes`/`no`/`on`/`off` (and case variants) as booleans, per the YAML 1.1 core schema. By default (YAML 1.2 core schema) only `true`/`false` are recognized as booleans | |
| 562 580 | |
| 563 581 | ```erlang |
| 564 | - 1> glazer:yaml_decode(<<"a: ~\n">>, [use_nil]). |
| 582 | + 1> glazer_yaml:decode(<<"a: ~\n">>, [use_nil]). |
| 565 583 | #{<<"a">> => nil} |
| 566 584 | |
| 567 | - 2> glazer:yaml_decode(<<"a: 1\n">>, [{keys, atom}]). |
| 585 | + 2> glazer_yaml:decode(<<"a: 1\n">>, [{keys, atom}]). |
| 568 586 | #{a => 1} |
| 569 587 | |
| 570 | - 3> glazer:yaml_decode(<<"a: yes\n">>, [yaml_1_1_bools]). |
| 588 | + 3> glazer_yaml:decode(<<"a: yes\n">>, [yaml_1_1_bools]). |
| 571 589 | #{<<"a">> => true} |
| 572 590 | ``` |
| 573 591 | |
| 574 | - ### Encode options (`yaml_encode/2`) |
| 592 | + ### Encode options (`glazer_yaml:encode/2`) |
| 575 593 | |
| 576 594 | | Option | Description | |
| 577 595 | |---|---| |
| @@ -579,17 +597,21 @@ JSON's bracket-balanced syntax. Decode full YAML documents with | |
| 579 597 | | `{null_term, Atom}` | Treat `Atom` as YAML `null` | |
| 580 598 | |
| 581 599 | ```erlang |
| 582 | - 1> glazer:yaml_encode(#{<<"a">> => nil}, [use_nil]). |
| 600 | + 1> glazer_yaml:encode(#{<<"a">> => nil}, [use_nil]). |
| 583 601 | <<"a: null\n">> |
| 584 602 | ``` |
| 585 603 | |
| 586 604 | ### API |
| 587 605 | |
| 606 | + All functions below are in `glazer_yaml`. |
| 607 | + |
| 588 608 | | Function | Description | |
| 589 609 | |---|---| |
| 590 | - | `yaml_decode/1`, `yaml_decode/2` | Decode a YAML binary or iolist to an Erlang term | |
| 591 | - | `yaml_try_decode/1`, `yaml_try_decode/2` | Decode YAML, returning `{ok, Term}` or `{error, Msg}` instead of raising | |
| 592 | - | `yaml_encode/1`, `yaml_encode/2` | Encode an Erlang term to a YAML binary in block style | |
| 610 | + | `decode/1`, `decode/2` | Decode a YAML binary or iolist to an Erlang term | |
| 611 | + | `try_decode/1`, `try_decode/2` | Decode YAML, returning `{ok, Term}` or `{error, Msg}` instead of raising | |
| 612 | + | `encode/1`, `encode/2` | Encode an Erlang term to a YAML binary in block style | |
| 613 | + | `read_file/1`, `read_file/2` | Read a file and decode its contents as YAML | |
| 614 | + | `write_file/2`, `write_file/3` | Encode a term to YAML and write it to a file | |
| 593 615 | |
| 594 616 | ### Benchmarking YAML |
| 595 617 | |
| @@ -598,40 +620,40 @@ $ PARALLEL=2 make bench-yaml | |
| 598 620 | ==> Running benchmarks with parallelism: 2 |
| 599 621 | |
| 600 622 | (numbers in µs) |
| 601 | - YAML openrtb (1.3K) esad (1.3K) small (0.1K) |
| 602 | - decode encode decode encode decode encode |
| 623 | + YAML openrtb (1.3K) esad (1.3K) small (0.1K) |
| 624 | + decode encode decode encode decode encode |
| 603 625 | ------------------------------------------------------------------------- |
| 604 | - glazer 33.2 7.7 27.2 5.3 7.9 1.2 |
| 605 | - yaml_rustler 126.5 n/a 78.0 n/a 11.8 n/a |
| 606 | - fast_yaml 180.0 45.1 97.2 40.6 18.8 6.1 |
| 607 | - yamerl 1366.2 n/a 991.5 n/a 517.3 n/a |
| 608 | - ymlr n/a 47.4 n/a 35.3 n/a 4.8 |
| 626 | + glazer 81.0 14.7 19.9 7.9 11.5 2.2 |
| 627 | + yaml_rustler 195.3 n/a 103.9 n/a 16.9 n/a |
| 628 | + fast_yaml 254.9 69.5 141.4 54.4 26.7 7.6 |
| 629 | + yamerl 2014.4 n/a 1486.2 n/a 676.1 n/a |
| 630 | + ymlr n/a 62.6 n/a 46.1 n/a 5.9 |
| 609 631 | ``` |
| 610 632 | |
| 611 633 | ## CSV |
| 612 634 | |
| 613 635 | ### Usage |
| 614 636 | |
| 615 | - `csv_decode/1,2` decodes an RFC 4180 CSV document to a list of rows, each |
| 637 | + `decode/1,2` decodes an RFC 4180 CSV document to a list of rows, each |
| 616 638 | row a list of binary fields: |
| 617 639 | |
| 618 640 | ```erlang |
| 619 | - 1> glazer:csv_decode(<<"name,age\nAlice,30\nBob,25\n">>). |
| 641 | + 1> glazer_csv:decode(<<"name,age\nAlice,30\nBob,25\n">>). |
| 620 642 | [[<<"name">>, <<"age">>], [<<"Alice">>, <<"30">>], [<<"Bob">>, <<"25">>]] |
| 621 643 | |
| 622 | - 2> glazer:csv_encode([[<<"name">>, <<"age">>], [<<"Alice">>, 30]]). |
| 644 | + 2> glazer_csv:encode([[<<"name">>, <<"age">>], [<<"Alice">>, 30]]). |
| 623 645 | <<"name,age\r\nAlice,30\r\n">> |
| 624 646 | ``` |
| 625 647 | |
| 626 648 | With the `headers` option, the first row is used as column names and each |
| 627 | - subsequent row decodes to a map; `csv_encode/2` with `headers` does the |
| 649 | + subsequent row decodes to a map; `encode/2` with `headers` does the |
| 628 650 | reverse, deriving the header row from the first map's keys: |
| 629 651 | |
| 630 652 | ```erlang |
| 631 | - 1> glazer:csv_decode(<<"name,age\nAlice,30\n">>, [headers]). |
| 653 | + 1> glazer_csv:decode(<<"name,age\nAlice,30\n">>, [headers]). |
| 632 654 | [#{<<"name">> => <<"Alice">>, <<"age">> => <<"30">>}] |
| 633 655 | |
| 634 | - 2> glazer:csv_encode([#{<<"name">> => <<"Alice">>, <<"age">> => 30}], [headers]). |
| 656 | + 2> glazer_csv:encode([#{<<"name">> => <<"Alice">>, <<"age">> => 30}], [headers]). |
| 635 657 | <<"name,age\r\nAlice,30\r\n">> |
| 636 658 | ``` |
| 637 659 | |
| @@ -643,49 +665,49 @@ RFC 4180 and can be changed to `\n` via `{line_ending, lf}`. | |
| 643 665 | |
| 644 666 | ### Streaming |
| 645 667 | |
| 646 | - For input that arrives in chunks, `csv_stream_decoder/0,1` provides the |
| 668 | + For input that arrives in chunks, `stream_decoder/0,1` provides the |
| 647 669 | same kind of stateful wrapper as [JSON streaming](#streaming): it buffers |
| 648 670 | partial input and decodes each row as soon as its terminating line break |
| 649 | - is seen, via `csv_decode/2` on that single row. A small scanner tracks |
| 671 | + is seen, via `decode/2` on that single row. A small scanner tracks |
| 650 672 | whether the cursor is inside a quoted field across chunks, so a `\n`/`\r\n` |
| 651 673 | inside a quoted field doesn't end the row: |
| 652 674 | |
| 653 675 | ```erlang |
| 654 | - 1> D0 = glazer:csv_stream_decoder(), |
| 655 | - 2> {Rows1, D1} = glazer:csv_stream_feed(D0, <<"a,b\n1,2\n3,">>), |
| 676 | + 1> D0 = glazer_csv:stream_decoder(), |
| 677 | + 2> {Rows1, D1} = glazer_csv:stream_feed(D0, <<"a,b\n1,2\n3,">>), |
| 656 678 | 3> Rows1. |
| 657 679 | [[<<"a">>,<<"b">>],[<<"1">>,<<"2">>]] |
| 658 680 | |
| 659 | - 4> {Rows2, D2} = glazer:csv_stream_feed(D1, <<"4\n">>), |
| 681 | + 4> {Rows2, D2} = glazer_csv:stream_feed(D1, <<"4\n">>), |
| 660 682 | 5> Rows2. |
| 661 683 | [[<<"3">>,<<"4">>]] |
| 662 684 | |
| 663 | - 6> glazer:csv_stream_eof(D2). |
| 685 | + 6> glazer_csv:stream_eof(D2). |
| 664 686 | {ok, []} |
| 665 687 | ``` |
| 666 688 | |
| 667 | - `csv_stream_feed/2` returns the rows completed by the chunk just fed |
| 689 | + `stream_feed/2` returns the rows completed by the chunk just fed |
| 668 690 | (possibly empty, possibly more than one) along with the updated decoder |
| 669 | - state. Once the input is exhausted, call `csv_stream_eof/1` to flush a |
| 691 | + state. Once the input is exhausted, call `stream_eof/1` to flush a |
| 670 692 | trailing row that has no terminating line break, or surface an error if |
| 671 693 | the buffered bytes don't form a valid row: |
| 672 694 | |
| 673 695 | ```erlang |
| 674 | - 1> D0 = glazer:csv_stream_decoder(), |
| 675 | - 2> {Rows1, D1} = glazer:csv_stream_feed(D0, <<"a,b\n1,2">>), |
| 696 | + 1> D0 = glazer_csv:stream_decoder(), |
| 697 | + 2> {Rows1, D1} = glazer_csv:stream_feed(D0, <<"a,b\n1,2">>), |
| 676 698 | 3> Rows1. |
| 677 699 | [[<<"a">>,<<"b">>]] |
| 678 700 | |
| 679 | - 4> glazer:csv_stream_eof(D1). |
| 701 | + 4> glazer_csv:stream_eof(D1). |
| 680 702 | {ok, [[<<"1">>,<<"2">>]]} |
| 681 703 | ``` |
| 682 704 | |
| 683 | - `csv_stream_decoder/1` accepts the same options as `csv_decode/2`. With |
| 705 | + `stream_decoder/1` accepts the same options as `decode/2`. With |
| 684 706 | the `headers` option, the first complete row is captured as the header and |
| 685 707 | used to decode every subsequent row as a map; no row is emitted for the |
| 686 | - header itself. Blank lines are skipped, matching `csv_decode/2`. |
| 708 | + header itself. Blank lines are skipped, matching `decode/2`. |
| 687 709 | |
| 688 | - ### Decode options (`csv_decode/2`) |
| 710 | + ### Decode options (`glazer_csv:decode/2`) |
| 689 711 | |
| 690 712 | | Option | Description | |
| 691 713 | |---|---| |
| @@ -694,8 +716,83 @@ header itself. Blank lines are skipped, matching `csv_decode/2`. | |
| 694 716 | | `{keys, atom}` | With `headers`, decode column names as atoms | |
| 695 717 | | `{keys, existing_atom}` | With `headers`, decode column names as existing atoms, falling back to binaries for unknown atoms | |
| 696 718 | | `{keys, binary}` | With `headers`, decode column names as binaries (default) | |
| 719 | + | `{fields, Specs}` | Convert each column's field from a binary, positionally — see [Field type conversion](#field-type-conversion) | |
| 720 | + | `{null_term, Atom}` | Use `Atom` as the value produced by `on_failure => null` (default `null`) | |
| 697 721 | |
| 698 | - ### Encode options (`csv_encode/2`) |
| 722 | + ### Field type conversion |
| 723 | + |
| 724 | + The `{fields, Specs}` decode option converts each column's field from a |
| 725 | + binary to the given Erlang type. `Specs` is a list applied positionally — |
| 726 | + the Nth spec applies to the Nth column, regardless of whether `headers` is |
| 727 | + set. Columns beyond the end of `Specs` are left as binaries. |
| 728 | + |
| 729 | + ```erlang |
| 730 | + 1> glazer_csv:decode(<<"name,age,active,joined\nAlice,30,true,2024-01-15T10:30:00Z\n">>, |
| 731 | + .. [headers, {fields, [binary, integer, boolean, |
| 732 | + .. {datetime, <<"%Y-%m-%dT%H:%M:%SZ">>}]}]). |
| 733 | + [#{<<"name">> => <<"Alice">>, <<"age">> => 30, <<"active">> => true, |
| 734 | + <<"joined">> => 1705314600}] |
| 735 | + ``` |
| 736 | + |
| 737 | + Each element of `Specs` is either a `Type` directly, or a map |
| 738 | + `#{type => Type, default => Term, on_failure => OnFailure}` for more |
| 739 | + control (see below). `Type` is one of: |
| 740 | + |
| 741 | + | Type | Description | |
| 742 | + |---|---| |
| 743 | + | `integer` | Parse the field as an integer | |
| 744 | + | `{float, Precision}` | Parse the field as a float, rounded to `Precision` decimal digits | |
| 745 | + | `boolean` | Parse `"true"`/`"false"` (any case) as `true`/`false` | |
| 746 | + | `{datetime, InputFormat}` | Parse with a `strptime`-like format string and convert to Unix epoch seconds (UTC) | |
| 747 | + | `binary` | Leave the field as a binary (default) | |
| 748 | + | `charlist` | Convert the field to a list of Unicode code points | |
| 749 | + | `existing_atom` | Convert to an existing atom, falling back to a binary if no such atom exists | |
| 750 | + | `{atom, ExistingAtoms}` | Convert to an atom only if the field's text matches (and exists as) one of `ExistingAtoms`, falling back to a binary otherwise | |
| 751 | + |
| 752 | + `InputFormat` supports the directives `%Y %y %m %d %H %M %S %f %z` (and |
| 753 | + `%%` for a literal `%`); any other character must match the input |
| 754 | + literally, and a space matches a run of one-or-more whitespace characters. |
| 755 | + `%z` accepts `Z`, `+HHMM`, or `+HH:MM`-style offsets; fractional seconds |
| 756 | + (`%f`) are parsed but discarded. The result is always in UTC. |
| 757 | + |
| 758 | + #### `default` and `on_failure` |
| 759 | + |
| 760 | + Using the map form `#{type => Type, default => Term, on_failure => OnFailure}`: |
| 761 | + |
| 762 | + - `default` (when given) is used in place of the converted value whenever |
| 763 | + the raw CSV field is empty. |
| 764 | + - `on_failure` controls what happens when a *non-empty* field fails to |
| 765 | + convert to `Type` (default `binary`): |
| 766 | + |
| 767 | + | `on_failure` | Behavior | |
| 768 | + |---|---| |
| 769 | + | `binary` | Leave the field as the original binary (default) | |
| 770 | + | `raise` | Raise `{invalid_field_value, Row, Column}` (1-based), or return `{error, Reason}` from `try_decode/2` | |
| 771 | + | `default` | Use the spec's `default` value (falls back to `binary` if no `default` is given) | |
| 772 | + | `null` | Use the configured null term: `{null_term, Atom}` if given, otherwise the library-wide null term (see [Null term configuration](#null-term-configuration) and `{null_term, Atom}` below) | |
| 773 | + |
| 774 | + ```erlang |
| 775 | + 1> glazer_csv:decode(<<"1\nbad\n">>, |
| 776 | + .. [{fields, [#{type => integer, on_failure => raise}]}]). |
| 777 | + ** exception error: {invalid_field_value,2,1} |
| 778 | + |
| 779 | + 2> glazer_csv:decode(<<"1\nbad\n">>, |
| 780 | + .. [{fields, [#{type => integer, default => 0, on_failure => default}]}]). |
| 781 | + [[1],[0]] |
| 782 | + |
| 783 | + 3> glazer_csv:decode(<<"1\nbad\n">>, |
| 784 | + .. [{null_term, nil}, |
| 785 | + .. {fields, [#{type => integer, on_failure => null}]}]). |
| 786 | + [[1],[nil]] |
| 787 | + ``` |
| 788 | + |
| 789 | + `{null_term, Atom}` only affects `on_failure => null` for that call. Without |
| 790 | + it, `on_failure => null` falls back to the library-wide null term — `null` |
| 791 | + by default, or whatever atom is configured via the |
| 792 | + [Null term configuration](#null-term-configuration) |
| 793 | + application env var (`{glazer, [{null, Atom}]}`). |
| 794 | + |
| 795 | + ### Encode options (`glazer_csv:encode/2`) |
| 699 796 | |
| 700 797 | | Option | Description | |
| 701 798 | |---|---| |
| @@ -705,14 +802,18 @@ header itself. Blank lines are skipped, matching `csv_decode/2`. | |
| 705 802 | |
| 706 803 | ### API |
| 707 804 | |
| 805 | + All functions below are in `glazer_csv`. |
| 806 | + |
| 708 807 | | Function | Description | |
| 709 808 | |---|---| |
| 710 | - | `csv_decode/1`, `csv_decode/2` | Decode a CSV binary or iolist to a list of rows (or maps with `headers`) | |
| 711 | - | `csv_try_decode/1`, `csv_try_decode/2` | Decode CSV, returning `{ok, Rows}` or `{error, Reason}` instead of raising | |
| 712 | - | `csv_encode/1`, `csv_encode/2` | Encode a list of rows (or maps with `headers`) to a CSV binary | |
| 713 | - | `csv_stream_decoder/0`, `csv_stream_decoder/1` | Create an incremental CSV decode state for chunked input | |
| 714 | - | `csv_stream_feed/2` | Feed a chunk to a CSV stream decoder, returning completed rows | |
| 715 | - | `csv_stream_eof/1` | Flush a CSV stream decoder at end-of-input | |
| 809 | + | `decode/1`, `decode/2` | Decode a CSV binary or iolist to a list of rows (or maps with `headers`) | |
| 810 | + | `try_decode/1`, `try_decode/2` | Decode CSV, returning `{ok, Rows}` or `{error, Reason}` instead of raising | |
| 811 | + | `encode/1`, `encode/2` | Encode a list of rows (or maps with `headers`) to a CSV binary | |
| 812 | + | `read_file/1`, `read_file/2` | Read a file and decode its contents as CSV | |
| 813 | + | `write_file/2`, `write_file/3` | Encode rows to CSV and write them to a file | |
| 814 | + | `stream_decoder/0`, `stream_decoder/1` | Create an incremental CSV decode state for chunked input | |
| 815 | + | `stream_feed/2` | Feed a chunk to a CSV stream decoder, returning completed rows | |
| 816 | + | `stream_eof/1` | Flush a CSV stream decoder at end-of-input | |
| 716 817 | |
| 717 818 | ### Benchmarking CSV |
| 718 819 | |
| @@ -721,13 +822,13 @@ $ PARALLEL=2 make bench-csv | |
| 721 822 | ==> Running benchmarks with parallelism: 2 |
| 722 823 | |
| 723 824 | (numbers in µs) |
| 724 | - CSV small (1.3K) medium (130.9K) large (3433.1K) |
| 725 | - decode encode decode encode decode encode |
| 825 | + CSV small (1.3K) medium (130.9K) large (3433.1K) |
| 826 | + decode encode decode encode decode encode |
| 726 827 | ----------------------------------------------------------------------------------- |
| 727 | - glazer 8.3 4.9 1066.0 380.7 38298.9 12887.9 |
| 728 | - nimble_csv 33.9 23.4 4202.3 2535.2 173790.7 94933.2 |
| 729 | - csv 75.1 177.9 6250.8 15820.6 TIMEOUT TIMEOUT |
| 730 | - erl_csv 370.6 266.1 39832.4 26145.4 TIMEOUT TIMEOUT |
| 828 | + glazer 10.7 3.3 1289.6 469.5 42617.2 16240.1 |
| 829 | + nimble_csv 44.8 38.8 4582.9 3204.4 238366.4 120585.9 |
| 830 | + csv 99.3 257.3 8335.2 24393.9 TIMEOUT TIMEOUT |
| 831 | + erl_csv 705.5 427.4 54950.5 34607.9 TIMEOUT TIMEOUT |
| 731 832 | ``` |
| 732 833 | |
| 733 834 | ## Big integers |
| @@ -761,6 +862,25 @@ same conversion routines directly, independent of JSON/YAML/CSV parsing/encoding | |
| 761 862 | See the module's documentation (`src/glazer.erl`) for full type |
| 762 863 | specs and details. |
| 763 864 | |
| 865 | + ## Limitations |
| 866 | + |
| 867 | + ### Nesting depth |
| 868 | + |
| 869 | + The JSON and YAML decoders both cap recursion at **256 levels** of nesting |
| 870 | + (arrays/objects for JSON; mappings/sequences for YAML). Inputs that exceed |
| 871 | + this limit are rejected with a decode error rather than crashing the VM by |
| 872 | + overflowing the C stack. |
| 873 | + |
| 874 | + | Format | Limit | Error returned | |
| 875 | + |--------|-------|---------------| |
| 876 | + | JSON | 256 | `{error, <<"exceeded maximum nesting depth at offset N">>}` | |
| 877 | + | YAML | 256 | `{error, <<"exceeded maximum nesting depth at offset N">>}` | |
| 878 | + |
| 879 | + 256 levels is sufficient for any reasonable real-world document; it is |
| 880 | + deliberately not configurable, because the limit exists to protect the |
| 881 | + Erlang VM process (the NIF runs on the scheduler thread) from runaway |
| 882 | + recursive descent on adversarial input. |
| 883 | + |
| 764 884 | ## Testing |
| 765 885 | |
| 766 886 | ```sh |
| @@ -50,61 +50,63 @@ | |
| 50 50 | <text x="44.0" y="97.7" text-anchor="end" font-size="9" class="muted">10000</text> |
| 51 51 | <line x1="50.0" y1="68.0" x2="370.0" y2="68.0" class="grid" stroke-width="1"/> |
| 52 52 | <text x="44.0" y="71.0" text-anchor="end" font-size="9" class="muted">15000</text> |
| 53 | - <rect x="56.0" y="127.3" width="33.2" height="20.7" class="bar-glazer"><title>glazer: 3876.2 (decode)</title></rect> |
| 54 | - <text x="72.6" y="124.3" text-anchor="middle" font-size="8" class="muted">3876.2</text> |
| 53 | + <rect x="56.0" y="124.6" width="33.2" height="23.4" class="bar-glazer"><title>glazer: 4379.2 (decode)</title></rect> |
| 54 | + <text x="72.6" y="121.6" text-anchor="middle" font-size="8" class="muted">4379.2</text> |
| 55 55 | <text x="72.6" y="158.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 72.6,158.0)">glazer</text> |
| 56 | - <rect x="95.2" y="120.6" width="33.2" height="27.4" class="bar-1"><title>torque: 5140.3 (decode)</title></rect> |
| 57 | - <text x="111.9" y="117.6" text-anchor="middle" font-size="8" class="muted">5140.3</text> |
| 56 | + <rect x="95.2" y="115.5" width="33.2" height="32.5" class="bar-1"><title>torque: 6089.2 (decode)</title></rect> |
| 57 | + <text x="111.9" y="112.5" text-anchor="middle" font-size="8" class="muted">6089.2</text> |
| 58 58 | <text x="111.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 111.9,158.0)">torque</text> |
| 59 | - <rect x="134.5" y="123.2" width="33.2" height="24.8" class="bar-2"><title>simdjsone: 4652.9 (decode)</title></rect> |
| 60 | - <text x="151.1" y="120.2" text-anchor="middle" font-size="8" class="muted">4652.9</text> |
| 59 | + <rect x="134.5" y="116.8" width="33.2" height="31.2" class="bar-2"><title>simdjsone: 5847.3 (decode)</title></rect> |
| 60 | + <text x="151.1" y="113.8" text-anchor="middle" font-size="8" class="muted">5847.3</text> |
| 61 61 | <text x="151.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 151.1,158.0)">simdjsone</text> |
| 62 | - <rect x="173.8" y="116.4" width="33.2" height="31.6" class="bar-3"><title>jiffy: 5921.4 (decode)</title></rect> |
| 63 | - <text x="190.4" y="113.4" text-anchor="middle" font-size="8" class="muted">5921.4</text> |
| 62 | + <rect x="173.8" y="106.0" width="33.2" height="42.0" class="bar-3"><title>jiffy: 7868.6 (decode)</title></rect> |
| 63 | + <text x="190.4" y="103.0" text-anchor="middle" font-size="8" class="muted">7868.6</text> |
| 64 64 | <text x="190.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 190.4,158.0)">jiffy</text> |
| 65 | - <rect x="213.0" y="94.4" width="33.2" height="53.6" class="bar-4"><title>jason: 10040.8 (decode)</title></rect> |
| 66 | - <text x="229.6" y="91.4" text-anchor="middle" font-size="8" class="muted">10040.8</text> |
| 65 | + <rect x="213.0" y="76.0" width="33.2" height="72.0" class="bar-4"><title>jason: 13509 (decode)</title></rect> |
| 66 | + <text x="229.6" y="73.0" text-anchor="middle" font-size="8" class="muted">13509</text> |
| 67 67 | <text x="229.6" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 229.6,158.0)">jason</text> |
| 68 | - <rect x="252.2" y="93.4" width="33.2" height="54.6" class="bar-5"><title>thoas: 10245.4 (decode)</title></rect> |
| 69 | - <text x="268.9" y="90.4" text-anchor="middle" font-size="8" class="muted">10245.4</text> |
| 68 | + <rect x="252.2" y="75.0" width="33.2" height="73.0" class="bar-5"><title>thoas: 13679.7 (decode)</title></rect> |
| 69 | + <text x="268.9" y="72.0" text-anchor="middle" font-size="8" class="muted">13679.7</text> |
| 70 70 | <text x="268.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 268.9,158.0)">thoas</text> |
| 71 | - <rect x="291.5" y="92.3" width="33.2" height="55.7" class="bar-6"><title>euneus: 10446.2 (decode)</title></rect> |
| 72 | - <text x="308.1" y="89.3" text-anchor="middle" font-size="8" class="muted">10446.2</text> |
| 71 | + <rect x="291.5" y="69.6" width="33.2" height="78.4" class="bar-6"><title>euneus: 14699.8 (decode)</title></rect> |
| 72 | + <text x="308.1" y="66.6" text-anchor="middle" font-size="8" class="muted">14699.8</text> |
| 73 73 | <text x="308.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 308.1,158.0)">euneus</text> |
| 74 | - <rect x="330.8" y="94.3" width="33.2" height="53.7" class="bar-7"><title>json: 10061.2 (decode)</title></rect> |
| 75 | - <text x="347.4" y="91.3" text-anchor="middle" font-size="8" class="muted">10061.2</text> |
| 74 | + <rect x="330.8" y="71.7" width="33.2" height="76.3" class="bar-7"><title>json: 14315.5 (decode)</title></rect> |
| 75 | + <text x="347.4" y="68.7" text-anchor="middle" font-size="8" class="muted">14315.5</text> |
| 76 76 | <text x="347.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 347.4,158.0)">json</text> |
| 77 77 | <line x1="50.0" y1="148.0" x2="370.0" y2="148.0" class="axis" stroke-width="1"/> |
| 78 78 | <text x="570.0" y="66.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">JSON encode — 616.7K</text> |
| 79 79 | <line x1="430.0" y1="148.0" x2="750.0" y2="148.0" class="grid" stroke-width="1"/> |
| 80 80 | <text x="424.0" y="151.0" text-anchor="end" font-size="9" class="muted">0</text> |
| 81 | - <line x1="430.0" y1="108.0" x2="750.0" y2="108.0" class="grid" stroke-width="1"/> |
| 82 | - <text x="424.0" y="111.0" text-anchor="end" font-size="9" class="muted">5000</text> |
| 81 | + <line x1="430.0" y1="121.3" x2="750.0" y2="121.3" class="grid" stroke-width="1"/> |
| 82 | + <text x="424.0" y="124.3" text-anchor="end" font-size="9" class="muted">5000</text> |
| 83 | + <line x1="430.0" y1="94.7" x2="750.0" y2="94.7" class="grid" stroke-width="1"/> |
| 84 | + <text x="424.0" y="97.7" text-anchor="end" font-size="9" class="muted">10000</text> |
| 83 85 | <line x1="430.0" y1="68.0" x2="750.0" y2="68.0" class="grid" stroke-width="1"/> |
| 84 | - <text x="424.0" y="71.0" text-anchor="end" font-size="9" class="muted">10000</text> |
| 85 | - <rect x="436.0" y="138.4" width="33.2" height="9.6" class="bar-glazer"><title>glazer: 1205.8 (encode)</title></rect> |
| 86 | - <text x="452.6" y="135.4" text-anchor="middle" font-size="8" class="muted">1205.8</text> |
| 86 | + <text x="424.0" y="71.0" text-anchor="end" font-size="9" class="muted">15000</text> |
| 87 | + <rect x="436.0" y="141.9" width="33.2" height="6.1" class="bar-glazer"><title>glazer: 1143.4 (encode)</title></rect> |
| 88 | + <text x="452.6" y="138.9" text-anchor="middle" font-size="8" class="muted">1143.4</text> |
| 87 89 | <text x="452.6" y="158.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 452.6,158.0)">glazer</text> |
| 88 | - <rect x="475.2" y="137.3" width="33.2" height="10.7" class="bar-1"><title>torque: 1333.7 (encode)</title></rect> |
| 89 | - <text x="491.9" y="134.3" text-anchor="middle" font-size="8" class="muted">1333.7</text> |
| 90 | + <rect x="475.2" y="139.2" width="33.2" height="8.8" class="bar-1"><title>torque: 1643.8 (encode)</title></rect> |
| 91 | + <text x="491.9" y="136.2" text-anchor="middle" font-size="8" class="muted">1643.8</text> |
| 90 92 | <text x="491.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 491.9,158.0)">torque</text> |
| 91 | - <rect x="514.5" y="119.5" width="33.2" height="28.5" class="bar-2"><title>simdjsone: 3564.3 (encode)</title></rect> |
| 92 | - <text x="531.1" y="116.5" text-anchor="middle" font-size="8" class="muted">3564.3</text> |
| 93 | + <rect x="514.5" y="121.2" width="33.2" height="26.8" class="bar-2"><title>simdjsone: 5019.7 (encode)</title></rect> |
| 94 | + <text x="531.1" y="118.2" text-anchor="middle" font-size="8" class="muted">5019.7</text> |
| 93 95 | <text x="531.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 531.1,158.0)">simdjsone</text> |
| 94 | - <rect x="553.8" y="127.6" width="33.2" height="20.4" class="bar-3"><title>jiffy: 2547.3 (encode)</title></rect> |
| 95 | - <text x="570.4" y="124.6" text-anchor="middle" font-size="8" class="muted">2547.3</text> |
| 96 | + <rect x="553.8" y="128.7" width="33.2" height="19.3" class="bar-3"><title>jiffy: 3615.6 (encode)</title></rect> |
| 97 | + <text x="570.4" y="125.7" text-anchor="middle" font-size="8" class="muted">3615.6</text> |
| 96 98 | <text x="570.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 570.4,158.0)">jiffy</text> |
| 97 | - <rect x="593.0" y="82.1" width="33.2" height="65.9" class="bar-4"><title>jason: 8237.9 (encode)</title></rect> |
| 98 | - <text x="609.6" y="79.1" text-anchor="middle" font-size="8" class="muted">8237.9</text> |
| 99 | + <rect x="593.0" y="88.0" width="33.2" height="60.0" class="bar-4"><title>jason: 11248.6 (encode)</title></rect> |
| 100 | + <text x="609.6" y="85.0" text-anchor="middle" font-size="8" class="muted">11248.6</text> |
| 99 101 | <text x="609.6" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 609.6,158.0)">jason</text> |
| 100 | - <rect x="632.2" y="75.1" width="33.2" height="72.9" class="bar-5"><title>thoas: 9117.9 (encode)</title></rect> |
| 101 | - <text x="648.9" y="72.1" text-anchor="middle" font-size="8" class="muted">9117.9</text> |
| 102 | + <rect x="632.2" y="81.5" width="33.2" height="66.5" class="bar-5"><title>thoas: 12466.1 (encode)</title></rect> |
| 103 | + <text x="648.9" y="78.5" text-anchor="middle" font-size="8" class="muted">12466.1</text> |
| 102 104 | <text x="648.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 648.9,158.0)">thoas</text> |
| 103 | - <rect x="671.5" y="93.2" width="33.2" height="54.8" class="bar-6"><title>euneus: 6845.7 (encode)</title></rect> |
| 104 | - <text x="688.1" y="90.2" text-anchor="middle" font-size="8" class="muted">6845.7</text> |
| 105 | + <rect x="671.5" y="93.3" width="33.2" height="54.7" class="bar-6"><title>euneus: 10247.2 (encode)</title></rect> |
| 106 | + <text x="688.1" y="90.3" text-anchor="middle" font-size="8" class="muted">10247.2</text> |
| 105 107 | <text x="688.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 688.1,158.0)">euneus</text> |
| 106 | - <rect x="710.8" y="95.5" width="33.2" height="52.5" class="bar-7"><title>json: 6563 (encode)</title></rect> |
| 107 | - <text x="727.4" y="92.5" text-anchor="middle" font-size="8" class="muted">6563</text> |
| 108 | + <rect x="710.8" y="96.2" width="33.2" height="51.8" class="bar-7"><title>json: 9718.9 (encode)</title></rect> |
| 109 | + <text x="727.4" y="93.2" text-anchor="middle" font-size="8" class="muted">9718.9</text> |
| 108 110 | <text x="727.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 727.4,158.0)">json</text> |
| 109 111 | <line x1="430.0" y1="148.0" x2="750.0" y2="148.0" class="axis" stroke-width="1"/> |
| 110 112 | <text x="190.0" y="204.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">YAML decode — 1.3K</text> |
| @@ -116,17 +118,17 @@ | |
| 116 118 | <text x="44.0" y="235.7" text-anchor="end" font-size="9" class="muted">2000</text> |
| 117 119 | <line x1="50.0" y1="206.0" x2="370.0" y2="206.0" class="grid" stroke-width="1"/> |
| 118 120 | <text x="44.0" y="209.0" text-anchor="end" font-size="9" class="muted">3000</text> |
| 119 | - <rect x="56.0" y="281.9" width="56.8" height="4.1" class="bar-glazer"><title>glazer: 154.3 (decode)</title></rect> |
| 120 | - <text x="84.4" y="278.9" text-anchor="middle" font-size="8" class="muted">154.3</text> |
| 121 | + <rect x="56.0" y="283.8" width="56.8" height="2.2" class="bar-glazer"><title>glazer: 81 (decode)</title></rect> |
| 122 | + <text x="84.4" y="280.8" text-anchor="middle" font-size="8" class="muted">81</text> |
| 121 123 | <text x="84.4" y="296.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 84.4,296.0)">glazer</text> |
| 122 | - <rect x="118.8" y="279.4" width="56.8" height="6.6" class="bar-1"><title>yaml_rustler: 248 (decode)</title></rect> |
| 123 | - <text x="147.2" y="276.4" text-anchor="middle" font-size="8" class="muted">248</text> |
| 124 | + <rect x="118.8" y="280.8" width="56.8" height="5.2" class="bar-1"><title>yaml_rustler: 195.3 (decode)</title></rect> |
| 125 | + <text x="147.2" y="277.8" text-anchor="middle" font-size="8" class="muted">195.3</text> |
| 124 126 | <text x="147.2" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 147.2,296.0)">yaml_rustler</text> |
| 125 | - <rect x="181.6" y="279.3" width="56.8" height="6.7" class="bar-2"><title>fast_yaml: 250.4 (decode)</title></rect> |
| 126 | - <text x="210.0" y="276.3" text-anchor="middle" font-size="8" class="muted">250.4</text> |
| 127 | + <rect x="181.6" y="279.2" width="56.8" height="6.8" class="bar-2"><title>fast_yaml: 254.9 (decode)</title></rect> |
| 128 | + <text x="210.0" y="276.2" text-anchor="middle" font-size="8" class="muted">254.9</text> |
| 127 129 | <text x="210.0" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 210.0,296.0)">fast_yaml</text> |
| 128 | - <rect x="244.4" y="232.5" width="56.8" height="53.5" class="bar-3"><title>yamerl: 2006.9 (decode)</title></rect> |
| 129 | - <text x="272.8" y="229.5" text-anchor="middle" font-size="8" class="muted">2006.9</text> |
| 130 | + <rect x="244.4" y="232.3" width="56.8" height="53.7" class="bar-3"><title>yamerl: 2014.4 (decode)</title></rect> |
| 131 | + <text x="272.8" y="229.3" text-anchor="middle" font-size="8" class="muted">2014.4</text> |
| 130 132 | <text x="272.8" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 272.8,296.0)">yamerl</text> |
| 131 133 | <text x="335.6" y="282.0" text-anchor="middle" font-size="8" class="faint">N/A</text> |
| 132 134 | <text x="335.6" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 335.6,296.0)">ymlr</text> |
| @@ -142,39 +144,36 @@ | |
| 142 144 | <text x="424.0" y="229.0" text-anchor="end" font-size="9" class="muted">60</text> |
| 143 145 | <line x1="430.0" y1="206.0" x2="750.0" y2="206.0" class="grid" stroke-width="1"/> |
| 144 146 | <text x="424.0" y="209.0" text-anchor="end" font-size="9" class="muted">80</text> |
| 145 | - <rect x="436.0" y="271.8" width="56.8" height="14.2" class="bar-glazer"><title>glazer: 14.2 (encode)</title></rect> |
| 146 | - <text x="464.4" y="268.8" text-anchor="middle" font-size="8" class="muted">14.2</text> |
| 147 | + <rect x="436.0" y="271.3" width="56.8" height="14.7" class="bar-glazer"><title>glazer: 14.7 (encode)</title></rect> |
| 148 | + <text x="464.4" y="268.3" text-anchor="middle" font-size="8" class="muted">14.7</text> |
| 147 149 | <text x="464.4" y="296.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 464.4,296.0)">glazer</text> |
| 148 150 | <text x="527.2" y="282.0" text-anchor="middle" font-size="8" class="faint">N/A</text> |
| 149 151 | <text x="527.2" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 527.2,296.0)">yaml_rustler</text> |
| 150 | - <rect x="561.6" y="220.9" width="56.8" height="65.1" class="bar-2"><title>fast_yaml: 65.1 (encode)</title></rect> |
| 151 | - <text x="590.0" y="217.9" text-anchor="middle" font-size="8" class="muted">65.1</text> |
| 152 | + <rect x="561.6" y="216.5" width="56.8" height="69.5" class="bar-2"><title>fast_yaml: 69.5 (encode)</title></rect> |
| 153 | + <text x="590.0" y="213.5" text-anchor="middle" font-size="8" class="muted">69.5</text> |
| 152 154 | <text x="590.0" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 590.0,296.0)">fast_yaml</text> |
| 153 155 | <text x="652.8" y="282.0" text-anchor="middle" font-size="8" class="faint">N/A</text> |
| 154 156 | <text x="652.8" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 652.8,296.0)">yamerl</text> |
| 155 | - <rect x="687.2" y="227.8" width="56.8" height="58.2" class="bar-4"><title>ymlr: 58.2 (encode)</title></rect> |
| 156 | - <text x="715.6" y="224.8" text-anchor="middle" font-size="8" class="muted">58.2</text> |
| 157 | + <rect x="687.2" y="223.4" width="56.8" height="62.6" class="bar-4"><title>ymlr: 62.6 (encode)</title></rect> |
| 158 | + <text x="715.6" y="220.4" text-anchor="middle" font-size="8" class="muted">62.6</text> |
| 157 159 | <text x="715.6" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 715.6,296.0)">ymlr</text> |
| 158 160 | <line x1="430.0" y1="286.0" x2="750.0" y2="286.0" class="axis" stroke-width="1"/> |
| 159 161 | <text x="190.0" y="342.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">CSV decode — 3433.1K</text> |
| 160 162 | <line x1="50.0" y1="424.0" x2="370.0" y2="424.0" class="grid" stroke-width="1"/> |
| 161 163 | <text x="44.0" y="427.0" text-anchor="end" font-size="9" class="muted">0</text> |
| 162 | - <line x1="50.0" y1="404.0" x2="370.0" y2="404.0" class="grid" stroke-width="1"/> |
| 163 | - <text x="44.0" y="407.0" text-anchor="end" font-size="9" class="muted">100000</text> |
| 164 | - <line x1="50.0" y1="384.0" x2="370.0" y2="384.0" class="grid" stroke-width="1"/> |
| 165 | - <text x="44.0" y="387.0" text-anchor="end" font-size="9" class="muted">200000</text> |
| 166 | - <line x1="50.0" y1="364.0" x2="370.0" y2="364.0" class="grid" stroke-width="1"/> |
| 167 | - <text x="44.0" y="367.0" text-anchor="end" font-size="9" class="muted">300000</text> |
| 164 | + <line x1="50.0" y1="397.3" x2="370.0" y2="397.3" class="grid" stroke-width="1"/> |
| 165 | + <text x="44.0" y="400.3" text-anchor="end" font-size="9" class="muted">100000</text> |
| 166 | + <line x1="50.0" y1="370.7" x2="370.0" y2="370.7" class="grid" stroke-width="1"/> |
| 167 | + <text x="44.0" y="373.7" text-anchor="end" font-size="9" class="muted">200000</text> |
| 168 168 | <line x1="50.0" y1="344.0" x2="370.0" y2="344.0" class="grid" stroke-width="1"/> |
| 169 | - <text x="44.0" y="347.0" text-anchor="end" font-size="9" class="muted">400000</text> |
| 170 | - <rect x="56.0" y="417.8" width="72.5" height="6.2" class="bar-glazer"><title>glazer: 30936 (decode)</title></rect> |
| 171 | - <text x="92.2" y="414.8" text-anchor="middle" font-size="8" class="muted">30936</text> |
| 169 | + <text x="44.0" y="347.0" text-anchor="end" font-size="9" class="muted">300000</text> |
| 170 | + <rect x="56.0" y="412.6" width="72.5" height="11.4" class="bar-glazer"><title>glazer: 42617.2 (decode)</title></rect> |
| 171 | + <text x="92.2" y="409.6" text-anchor="middle" font-size="8" class="muted">42617.2</text> |
| 172 172 | <text x="92.2" y="434.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 92.2,434.0)">glazer</text> |
| 173 | - <rect x="134.5" y="390.3" width="72.5" height="33.7" class="bar-1"><title>nimble_csv: 168553 (decode)</title></rect> |
| 174 | - <text x="170.8" y="387.3" text-anchor="middle" font-size="8" class="muted">168553</text> |
| 173 | + <rect x="134.5" y="360.4" width="72.5" height="63.6" class="bar-1"><title>nimble_csv: 238366 (decode)</title></rect> |
| 174 | + <text x="170.8" y="357.4" text-anchor="middle" font-size="8" class="muted">238366</text> |
| 175 175 | <text x="170.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 170.8,434.0)">nimble_csv</text> |
| 176 | - <rect x="213.0" y="355.0" width="72.5" height="69.0" class="bar-2"><title>csv: 345033 (decode)</title></rect> |
| 177 | - <text x="249.2" y="352.0" text-anchor="middle" font-size="8" class="muted">345033</text> |
| 176 | + <text x="249.2" y="420.0" text-anchor="middle" font-size="8" class="faint">TIMEOUT</text> |
| 178 177 | <text x="249.2" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 249.2,434.0)">csv</text> |
| 179 178 | <text x="327.8" y="420.0" text-anchor="middle" font-size="8" class="faint">TIMEOUT</text> |
| 180 179 | <text x="327.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 327.8,434.0)">erl_csv</text> |
| @@ -182,22 +181,19 @@ | |
| 182 181 | <text x="570.0" y="342.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">CSV encode — 3433.1K</text> |
| 183 182 | <line x1="430.0" y1="424.0" x2="750.0" y2="424.0" class="grid" stroke-width="1"/> |
| 184 183 | <text x="424.0" y="427.0" text-anchor="end" font-size="9" class="muted">0</text> |
| 185 | - <line x1="430.0" y1="404.0" x2="750.0" y2="404.0" class="grid" stroke-width="1"/> |
| 186 | - <text x="424.0" y="407.0" text-anchor="end" font-size="9" class="muted">200000</text> |
| 187 | - <line x1="430.0" y1="384.0" x2="750.0" y2="384.0" class="grid" stroke-width="1"/> |
| 188 | - <text x="424.0" y="387.0" text-anchor="end" font-size="9" class="muted">400000</text> |
| 189 | - <line x1="430.0" y1="364.0" x2="750.0" y2="364.0" class="grid" stroke-width="1"/> |
| 190 | - <text x="424.0" y="367.0" text-anchor="end" font-size="9" class="muted">600000</text> |
| 184 | + <line x1="430.0" y1="397.3" x2="750.0" y2="397.3" class="grid" stroke-width="1"/> |
| 185 | + <text x="424.0" y="400.3" text-anchor="end" font-size="9" class="muted">50000</text> |
| 186 | + <line x1="430.0" y1="370.7" x2="750.0" y2="370.7" class="grid" stroke-width="1"/> |
| 187 | + <text x="424.0" y="373.7" text-anchor="end" font-size="9" class="muted">100000</text> |
| 191 188 | <line x1="430.0" y1="344.0" x2="750.0" y2="344.0" class="grid" stroke-width="1"/> |
| 192 | - <text x="424.0" y="347.0" text-anchor="end" font-size="9" class="muted">800000</text> |
| 193 | - <rect x="436.0" y="423.0" width="72.5" height="1.0" class="bar-glazer"><title>glazer: 10496.8 (encode)</title></rect> |
| 194 | - <text x="472.2" y="420.0" text-anchor="middle" font-size="8" class="muted">10496.8</text> |
| 189 | + <text x="424.0" y="347.0" text-anchor="end" font-size="9" class="muted">150000</text> |
| 190 | + <rect x="436.0" y="415.3" width="72.5" height="8.7" class="bar-glazer"><title>glazer: 16240.1 (encode)</title></rect> |
| 191 | + <text x="472.2" y="412.3" text-anchor="middle" font-size="8" class="muted">16240.1</text> |
| 195 192 | <text x="472.2" y="434.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 472.2,434.0)">glazer</text> |
| 196 | - <rect x="514.5" y="414.9" width="72.5" height="9.1" class="bar-1"><title>nimble_csv: 91117.8 (encode)</title></rect> |
| 197 | - <text x="550.8" y="411.9" text-anchor="middle" font-size="8" class="muted">91117.8</text> |
| 193 | + <rect x="514.5" y="359.7" width="72.5" height="64.3" class="bar-1"><title>nimble_csv: 120586 (encode)</title></rect> |
| 194 | + <text x="550.8" y="356.7" text-anchor="middle" font-size="8" class="muted">120586</text> |
| 198 195 | <text x="550.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 550.8,434.0)">nimble_csv</text> |
| 199 | - <rect x="593.0" y="361.8" width="72.5" height="62.2" class="bar-2"><title>csv: 621974 (encode)</title></rect> |
| 200 | - <text x="629.2" y="358.8" text-anchor="middle" font-size="8" class="muted">621974</text> |
| 196 | + <text x="629.2" y="420.0" text-anchor="middle" font-size="8" class="faint">TIMEOUT</text> |
| 201 197 | <text x="629.2" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 629.2,434.0)">csv</text> |
| 202 198 | <text x="707.8" y="420.0" text-anchor="middle" font-size="8" class="faint">TIMEOUT</text> |
| 203 199 | <text x="707.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 707.8,434.0)">erl_csv</text> |
| @@ -44,37 +44,35 @@ | |
| 44 44 | <text x="190.0" y="66.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">JSON decode — 1.3K</text> |
| 45 45 | <line x1="50.0" y1="148.0" x2="370.0" y2="148.0" class="grid" stroke-width="1"/> |
| 46 46 | <text x="44.0" y="151.0" text-anchor="end" font-size="9" class="muted">0</text> |
| 47 | - <line x1="50.0" y1="128.0" x2="370.0" y2="128.0" class="grid" stroke-width="1"/> |
| 48 | - <text x="44.0" y="131.0" text-anchor="end" font-size="9" class="muted">5</text> |
| 49 | - <line x1="50.0" y1="108.0" x2="370.0" y2="108.0" class="grid" stroke-width="1"/> |
| 50 | - <text x="44.0" y="111.0" text-anchor="end" font-size="9" class="muted">10</text> |
| 51 | - <line x1="50.0" y1="88.0" x2="370.0" y2="88.0" class="grid" stroke-width="1"/> |
| 52 | - <text x="44.0" y="91.0" text-anchor="end" font-size="9" class="muted">15</text> |
| 47 | + <line x1="50.0" y1="121.3" x2="370.0" y2="121.3" class="grid" stroke-width="1"/> |
| 48 | + <text x="44.0" y="124.3" text-anchor="end" font-size="9" class="muted">10</text> |
| 49 | + <line x1="50.0" y1="94.7" x2="370.0" y2="94.7" class="grid" stroke-width="1"/> |
| 50 | + <text x="44.0" y="97.7" text-anchor="end" font-size="9" class="muted">20</text> |
| 53 51 | <line x1="50.0" y1="68.0" x2="370.0" y2="68.0" class="grid" stroke-width="1"/> |
| 54 | - <text x="44.0" y="71.0" text-anchor="end" font-size="9" class="muted">20</text> |
| 55 | - <rect x="56.0" y="124.8" width="33.2" height="23.2" class="bar-glazer"><title>glazer: 5.8 (decode)</title></rect> |
| 56 | - <text x="72.6" y="121.8" text-anchor="middle" font-size="8" class="muted">5.8</text> |
| 52 | + <text x="44.0" y="71.0" text-anchor="end" font-size="9" class="muted">30</text> |
| 53 | + <rect x="56.0" y="130.1" width="33.2" height="17.9" class="bar-glazer"><title>glazer: 6.7 (decode)</title></rect> |
| 54 | + <text x="72.6" y="127.1" text-anchor="middle" font-size="8" class="muted">6.7</text> |
| 57 55 | <text x="72.6" y="158.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 72.6,158.0)">glazer</text> |
| 58 | - <rect x="95.2" y="128.4" width="33.2" height="19.6" class="bar-1"><title>torque: 4.9 (decode)</title></rect> |
| 59 | - <text x="111.9" y="125.4" text-anchor="middle" font-size="8" class="muted">4.9</text> |
| 56 | + <rect x="95.2" y="123.2" width="33.2" height="24.8" class="bar-1"><title>torque: 9.3 (decode)</title></rect> |
| 57 | + <text x="111.9" y="120.2" text-anchor="middle" font-size="8" class="muted">9.3</text> |
| 60 58 | <text x="111.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 111.9,158.0)">torque</text> |
| 61 | - <rect x="134.5" y="117.2" width="33.2" height="30.8" class="bar-2"><title>simdjsone: 7.7 (decode)</title></rect> |
| 62 | - <text x="151.1" y="114.2" text-anchor="middle" font-size="8" class="muted">7.7</text> |
| 59 | + <rect x="134.5" y="115.7" width="33.2" height="32.3" class="bar-2"><title>simdjsone: 12.1 (decode)</title></rect> |
| 60 | + <text x="151.1" y="112.7" text-anchor="middle" font-size="8" class="muted">12.1</text> |
| 63 61 | <text x="151.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 151.1,158.0)">simdjsone</text> |
| 64 | - <rect x="173.8" y="116.4" width="33.2" height="31.6" class="bar-3"><title>jiffy: 7.9 (decode)</title></rect> |
| 65 | - <text x="190.4" y="113.4" text-anchor="middle" font-size="8" class="muted">7.9</text> |
| 62 | + <rect x="173.8" y="114.9" width="33.2" height="33.1" class="bar-3"><title>jiffy: 12.4 (decode)</title></rect> |
| 63 | + <text x="190.4" y="111.9" text-anchor="middle" font-size="8" class="muted">12.4</text> |
| 66 64 | <text x="190.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 190.4,158.0)">jiffy</text> |
| 67 | - <rect x="213.0" y="82.8" width="33.2" height="65.2" class="bar-4"><title>jason: 16.3 (decode)</title></rect> |
| 68 | - <text x="229.6" y="79.8" text-anchor="middle" font-size="8" class="muted">16.3</text> |
| 65 | + <rect x="213.0" y="95.5" width="33.2" height="52.5" class="bar-4"><title>jason: 19.7 (decode)</title></rect> |
| 66 | + <text x="229.6" y="92.5" text-anchor="middle" font-size="8" class="muted">19.7</text> |
| 69 67 | <text x="229.6" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 229.6,158.0)">jason</text> |
| 70 | - <rect x="252.2" y="69.6" width="33.2" height="78.4" class="bar-5"><title>thoas: 19.6 (decode)</title></rect> |
| 71 | - <text x="268.9" y="66.6" text-anchor="middle" font-size="8" class="muted">19.6</text> |
| 68 | + <rect x="252.2" y="81.1" width="33.2" height="66.9" class="bar-5"><title>thoas: 25.1 (decode)</title></rect> |
| 69 | + <text x="268.9" y="78.1" text-anchor="middle" font-size="8" class="muted">25.1</text> |
| 72 70 | <text x="268.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 268.9,158.0)">thoas</text> |
| 73 | - <rect x="291.5" y="100.4" width="33.2" height="47.6" class="bar-6"><title>euneus: 11.9 (decode)</title></rect> |
| 74 | - <text x="308.1" y="97.4" text-anchor="middle" font-size="8" class="muted">11.9</text> |
| 71 | + <rect x="291.5" y="103.5" width="33.2" height="44.5" class="bar-6"><title>euneus: 16.7 (decode)</title></rect> |
| 72 | + <text x="308.1" y="100.5" text-anchor="middle" font-size="8" class="muted">16.7</text> |
| 75 73 | <text x="308.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 308.1,158.0)">euneus</text> |
| 76 | - <rect x="330.8" y="103.6" width="33.2" height="44.4" class="bar-7"><title>json: 11.1 (decode)</title></rect> |
| 77 | - <text x="347.4" y="100.6" text-anchor="middle" font-size="8" class="muted">11.1</text> |
| 74 | + <rect x="330.8" y="96.8" width="33.2" height="51.2" class="bar-7"><title>json: 19.2 (decode)</title></rect> |
| 75 | + <text x="347.4" y="93.8" text-anchor="middle" font-size="8" class="muted">19.2</text> |
| 78 76 | <text x="347.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 347.4,158.0)">json</text> |
| 79 77 | <line x1="50.0" y1="148.0" x2="370.0" y2="148.0" class="axis" stroke-width="1"/> |
| 80 78 | <text x="570.0" y="66.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">JSON encode — 1.3K</text> |
| @@ -86,29 +84,29 @@ | |
| 86 84 | <text x="424.0" y="97.7" text-anchor="end" font-size="9" class="muted">20</text> |
| 87 85 | <line x1="430.0" y1="68.0" x2="750.0" y2="68.0" class="grid" stroke-width="1"/> |
| 88 86 | <text x="424.0" y="71.0" text-anchor="end" font-size="9" class="muted">30</text> |
| 89 | - <rect x="436.0" y="140.3" width="33.2" height="7.7" class="bar-glazer"><title>glazer: 2.9 (encode)</title></rect> |
| 90 | - <text x="452.6" y="137.3" text-anchor="middle" font-size="8" class="muted">2.9</text> |
| 87 | + <rect x="436.0" y="137.3" width="33.2" height="10.7" class="bar-glazer"><title>glazer: 4 (encode)</title></rect> |
| 88 | + <text x="452.6" y="134.3" text-anchor="middle" font-size="8" class="muted">4</text> |
| 91 89 | <text x="452.6" y="158.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 452.6,158.0)">glazer</text> |
| 92 | - <rect x="475.2" y="138.7" width="33.2" height="9.3" class="bar-1"><title>torque: 3.5 (encode)</title></rect> |
| 93 | - <text x="491.9" y="135.7" text-anchor="middle" font-size="8" class="muted">3.5</text> |
| 90 | + <rect x="475.2" y="131.5" width="33.2" height="16.5" class="bar-1"><title>torque: 6.2 (encode)</title></rect> |
| 91 | + <text x="491.9" y="128.5" text-anchor="middle" font-size="8" class="muted">6.2</text> |
| 94 92 | <text x="491.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 491.9,158.0)">torque</text> |
| 95 | - <rect x="514.5" y="125.6" width="33.2" height="22.4" class="bar-2"><title>simdjsone: 8.4 (encode)</title></rect> |
| 96 | - <text x="531.1" y="122.6" text-anchor="middle" font-size="8" class="muted">8.4</text> |
| 93 | + <rect x="514.5" y="114.4" width="33.2" height="33.6" class="bar-2"><title>simdjsone: 12.6 (encode)</title></rect> |
| 94 | + <text x="531.1" y="111.4" text-anchor="middle" font-size="8" class="muted">12.6</text> |
| 97 95 | <text x="531.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 531.1,158.0)">simdjsone</text> |
| 98 | - <rect x="553.8" y="131.5" width="33.2" height="16.5" class="bar-3"><title>jiffy: 6.2 (encode)</title></rect> |
| 99 | - <text x="570.4" y="128.5" text-anchor="middle" font-size="8" class="muted">6.2</text> |
| 96 | + <rect x="553.8" y="123.7" width="33.2" height="24.3" class="bar-3"><title>jiffy: 9.1 (encode)</title></rect> |
| 97 | + <text x="570.4" y="120.7" text-anchor="middle" font-size="8" class="muted">9.1</text> |
| 100 98 | <text x="570.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 570.4,158.0)">jiffy</text> |
| 101 | - <rect x="593.0" y="93.1" width="33.2" height="54.9" class="bar-4"><title>jason: 20.6 (encode)</title></rect> |
| 102 | - <text x="609.6" y="90.1" text-anchor="middle" font-size="8" class="muted">20.6</text> |
| 99 | + <rect x="593.0" y="81.3" width="33.2" height="66.7" class="bar-4"><title>jason: 25 (encode)</title></rect> |
| 100 | + <text x="609.6" y="78.3" text-anchor="middle" font-size="8" class="muted">25</text> |
| 103 101 | <text x="609.6" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 609.6,158.0)">jason</text> |
| 104 | - <rect x="632.2" y="91.5" width="33.2" height="56.5" class="bar-5"><title>thoas: 21.2 (encode)</title></rect> |
| 105 | - <text x="648.9" y="88.5" text-anchor="middle" font-size="8" class="muted">21.2</text> |
| 102 | + <rect x="632.2" y="68.3" width="33.2" height="79.7" class="bar-5"><title>thoas: 29.9 (encode)</title></rect> |
| 103 | + <text x="648.9" y="65.3" text-anchor="middle" font-size="8" class="muted">29.9</text> |
| 106 104 | <text x="648.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 648.9,158.0)">thoas</text> |
| 107 | - <rect x="671.5" y="122.7" width="33.2" height="25.3" class="bar-6"><title>euneus: 9.5 (encode)</title></rect> |
| 108 | - <text x="688.1" y="119.7" text-anchor="middle" font-size="8" class="muted">9.5</text> |
| 105 | + <rect x="671.5" y="109.1" width="33.2" height="38.9" class="bar-6"><title>euneus: 14.6 (encode)</title></rect> |
| 106 | + <text x="688.1" y="106.1" text-anchor="middle" font-size="8" class="muted">14.6</text> |
| 109 107 | <text x="688.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 688.1,158.0)">euneus</text> |
| 110 | - <rect x="710.8" y="125.9" width="33.2" height="22.1" class="bar-7"><title>json: 8.3 (encode)</title></rect> |
| 111 | - <text x="727.4" y="122.9" text-anchor="middle" font-size="8" class="muted">8.3</text> |
| 108 | + <rect x="710.8" y="115.2" width="33.2" height="32.8" class="bar-7"><title>json: 12.3 (encode)</title></rect> |
| 109 | + <text x="727.4" y="112.2" text-anchor="middle" font-size="8" class="muted">12.3</text> |
| 112 110 | <text x="727.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 727.4,158.0)">json</text> |
| 113 111 | <line x1="430.0" y1="148.0" x2="750.0" y2="148.0" class="axis" stroke-width="1"/> |
| 114 112 | <text x="190.0" y="204.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">YAML decode — 1.3K</text> |
| @@ -120,17 +118,17 @@ | |
| 120 118 | <text x="44.0" y="235.7" text-anchor="end" font-size="9" class="muted">1000</text> |
| 121 119 | <line x1="50.0" y1="206.0" x2="370.0" y2="206.0" class="grid" stroke-width="1"/> |
| 122 120 | <text x="44.0" y="209.0" text-anchor="end" font-size="9" class="muted">1500</text> |
| 123 | - <rect x="56.0" y="283.5" width="56.8" height="2.5" class="bar-glazer"><title>glazer: 46 (decode)</title></rect> |
| 124 | - <text x="84.4" y="280.5" text-anchor="middle" font-size="8" class="muted">46</text> |
| 121 | + <rect x="56.0" y="284.9" width="56.8" height="1.1" class="bar-glazer"><title>glazer: 19.9 (decode)</title></rect> |
| 122 | + <text x="84.4" y="281.9" text-anchor="middle" font-size="8" class="muted">19.9</text> |
| 125 123 | <text x="84.4" y="296.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 84.4,296.0)">glazer</text> |
| 126 | - <rect x="118.8" y="278.8" width="56.8" height="7.2" class="bar-1"><title>yaml_rustler: 134.8 (decode)</title></rect> |
| 127 | - <text x="147.2" y="275.8" text-anchor="middle" font-size="8" class="muted">134.8</text> |
| 124 | + <rect x="118.8" y="280.5" width="56.8" height="5.5" class="bar-1"><title>yaml_rustler: 103.9 (decode)</title></rect> |
| 125 | + <text x="147.2" y="277.5" text-anchor="middle" font-size="8" class="muted">103.9</text> |
| 128 126 | <text x="147.2" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 147.2,296.0)">yaml_rustler</text> |
| 129 | - <rect x="181.6" y="276.2" width="56.8" height="9.8" class="bar-2"><title>fast_yaml: 183.6 (decode)</title></rect> |
| 130 | - <text x="210.0" y="273.2" text-anchor="middle" font-size="8" class="muted">183.6</text> |
| 127 | + <rect x="181.6" y="278.5" width="56.8" height="7.5" class="bar-2"><title>fast_yaml: 141.4 (decode)</title></rect> |
| 128 | + <text x="210.0" y="275.5" text-anchor="middle" font-size="8" class="muted">141.4</text> |
| 131 129 | <text x="210.0" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 210.0,296.0)">fast_yaml</text> |
| 132 | - <rect x="244.4" y="210.4" width="56.8" height="75.6" class="bar-3"><title>yamerl: 1418.3 (decode)</title></rect> |
| 133 | - <text x="272.8" y="207.4" text-anchor="middle" font-size="8" class="muted">1418.3</text> |
| 130 | + <rect x="244.4" y="206.7" width="56.8" height="79.3" class="bar-3"><title>yamerl: 1486.2 (decode)</title></rect> |
| 131 | + <text x="272.8" y="203.7" text-anchor="middle" font-size="8" class="muted">1486.2</text> |
| 134 132 | <text x="272.8" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 272.8,296.0)">yamerl</text> |
| 135 133 | <text x="335.6" y="282.0" text-anchor="middle" font-size="8" class="faint">N/A</text> |
| 136 134 | <text x="335.6" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 335.6,296.0)">ymlr</text> |
| @@ -144,18 +142,18 @@ | |
| 144 142 | <text x="424.0" y="235.7" text-anchor="end" font-size="9" class="muted">40</text> |
| 145 143 | <line x1="430.0" y1="206.0" x2="750.0" y2="206.0" class="grid" stroke-width="1"/> |
| 146 144 | <text x="424.0" y="209.0" text-anchor="end" font-size="9" class="muted">60</text> |
| 147 | - <rect x="436.0" y="271.7" width="56.8" height="14.3" class="bar-glazer"><title>glazer: 10.7 (encode)</title></rect> |
| 148 | - <text x="464.4" y="268.7" text-anchor="middle" font-size="8" class="muted">10.7</text> |
| 145 | + <rect x="436.0" y="275.5" width="56.8" height="10.5" class="bar-glazer"><title>glazer: 7.9 (encode)</title></rect> |
| 146 | + <text x="464.4" y="272.5" text-anchor="middle" font-size="8" class="muted">7.9</text> |
| 149 147 | <text x="464.4" y="296.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 464.4,296.0)">glazer</text> |
| 150 148 | <text x="527.2" y="282.0" text-anchor="middle" font-size="8" class="faint">N/A</text> |
| 151 149 | <text x="527.2" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 527.2,296.0)">yaml_rustler</text> |
| 152 | - <rect x="561.6" y="223.9" width="56.8" height="62.1" class="bar-2"><title>fast_yaml: 46.6 (encode)</title></rect> |
| 153 | - <text x="590.0" y="220.9" text-anchor="middle" font-size="8" class="muted">46.6</text> |
| 150 | + <rect x="561.6" y="213.5" width="56.8" height="72.5" class="bar-2"><title>fast_yaml: 54.4 (encode)</title></rect> |
| 151 | + <text x="590.0" y="210.5" text-anchor="middle" font-size="8" class="muted">54.4</text> |
| 154 152 | <text x="590.0" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 590.0,296.0)">fast_yaml</text> |
| 155 153 | <text x="652.8" y="282.0" text-anchor="middle" font-size="8" class="faint">N/A</text> |
| 156 154 | <text x="652.8" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 652.8,296.0)">yamerl</text> |
| 157 | - <rect x="687.2" y="236.5" width="56.8" height="49.5" class="bar-4"><title>ymlr: 37.1 (encode)</title></rect> |
| 158 | - <text x="715.6" y="233.5" text-anchor="middle" font-size="8" class="muted">37.1</text> |
| 155 | + <rect x="687.2" y="224.5" width="56.8" height="61.5" class="bar-4"><title>ymlr: 46.1 (encode)</title></rect> |
| 156 | + <text x="715.6" y="221.5" text-anchor="middle" font-size="8" class="muted">46.1</text> |
| 159 157 | <text x="715.6" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 715.6,296.0)">ymlr</text> |
| 160 158 | <line x1="430.0" y1="286.0" x2="750.0" y2="286.0" class="axis" stroke-width="1"/> |
| 161 159 | <text x="190.0" y="342.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">CSV decode — 130.9K</text> |
| @@ -167,39 +165,41 @@ | |
| 167 165 | <text x="44.0" y="373.7" text-anchor="end" font-size="9" class="muted">40000</text> |
| 168 166 | <line x1="50.0" y1="344.0" x2="370.0" y2="344.0" class="grid" stroke-width="1"/> |
| 169 167 | <text x="44.0" y="347.0" text-anchor="end" font-size="9" class="muted">60000</text> |
| 170 | - <rect x="56.0" y="422.9" width="72.5" height="1.1" class="bar-glazer"><title>glazer: 810.1 (decode)</title></rect> |
| 171 | - <text x="92.2" y="419.9" text-anchor="middle" font-size="8" class="muted">810.1</text> |
| 168 | + <rect x="56.0" y="422.3" width="72.5" height="1.7" class="bar-glazer"><title>glazer: 1289.6 (decode)</title></rect> |
| 169 | + <text x="92.2" y="419.3" text-anchor="middle" font-size="8" class="muted">1289.6</text> |
| 172 170 | <text x="92.2" y="434.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 92.2,434.0)">glazer</text> |
| 173 | - <rect x="134.5" y="419.0" width="72.5" height="5.0" class="bar-1"><title>nimble_csv: 3749.8 (decode)</title></rect> |
| 174 | - <text x="170.8" y="416.0" text-anchor="middle" font-size="8" class="muted">3749.8</text> |
| 171 | + <rect x="134.5" y="417.9" width="72.5" height="6.1" class="bar-1"><title>nimble_csv: 4582.9 (decode)</title></rect> |
| 172 | + <text x="170.8" y="414.9" text-anchor="middle" font-size="8" class="muted">4582.9</text> |
| 175 173 | <text x="170.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 170.8,434.0)">nimble_csv</text> |
| 176 | - <rect x="213.0" y="415.5" width="72.5" height="8.5" class="bar-2"><title>csv: 6341 (decode)</title></rect> |
| 177 | - <text x="249.2" y="412.5" text-anchor="middle" font-size="8" class="muted">6341</text> |
| 174 | + <rect x="213.0" y="412.9" width="72.5" height="11.1" class="bar-2"><title>csv: 8335.2 (decode)</title></rect> |
| 175 | + <text x="249.2" y="409.9" text-anchor="middle" font-size="8" class="muted">8335.2</text> |
| 178 176 | <text x="249.2" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 249.2,434.0)">csv</text> |
| 179 | - <rect x="291.5" y="370.5" width="72.5" height="53.5" class="bar-3"><title>erl_csv: 40115.1 (decode)</title></rect> |
| 180 | - <text x="327.8" y="367.5" text-anchor="middle" font-size="8" class="muted">40115.1</text> |
| 177 | + <rect x="291.5" y="350.7" width="72.5" height="73.3" class="bar-3"><title>erl_csv: 54950.5 (decode)</title></rect> |
| 178 | + <text x="327.8" y="347.7" text-anchor="middle" font-size="8" class="muted">54950.5</text> |
| 181 179 | <text x="327.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 327.8,434.0)">erl_csv</text> |
| 182 180 | <line x1="50.0" y1="424.0" x2="370.0" y2="424.0" class="axis" stroke-width="1"/> |
| 183 181 | <text x="570.0" y="342.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">CSV encode — 130.9K</text> |
| 184 182 | <line x1="430.0" y1="424.0" x2="750.0" y2="424.0" class="grid" stroke-width="1"/> |
| 185 183 | <text x="424.0" y="427.0" text-anchor="end" font-size="9" class="muted">0</text> |
| 186 | - <line x1="430.0" y1="397.3" x2="750.0" y2="397.3" class="grid" stroke-width="1"/> |
| 187 | - <text x="424.0" y="400.3" text-anchor="end" font-size="9" class="muted">10000</text> |
| 188 | - <line x1="430.0" y1="370.7" x2="750.0" y2="370.7" class="grid" stroke-width="1"/> |
| 189 | - <text x="424.0" y="373.7" text-anchor="end" font-size="9" class="muted">20000</text> |
| 184 | + <line x1="430.0" y1="404.0" x2="750.0" y2="404.0" class="grid" stroke-width="1"/> |
| 185 | + <text x="424.0" y="407.0" text-anchor="end" font-size="9" class="muted">10000</text> |
| 186 | + <line x1="430.0" y1="384.0" x2="750.0" y2="384.0" class="grid" stroke-width="1"/> |
| 187 | + <text x="424.0" y="387.0" text-anchor="end" font-size="9" class="muted">20000</text> |
| 188 | + <line x1="430.0" y1="364.0" x2="750.0" y2="364.0" class="grid" stroke-width="1"/> |
| 189 | + <text x="424.0" y="367.0" text-anchor="end" font-size="9" class="muted">30000</text> |
| 190 190 | <line x1="430.0" y1="344.0" x2="750.0" y2="344.0" class="grid" stroke-width="1"/> |
| 191 | - <text x="424.0" y="347.0" text-anchor="end" font-size="9" class="muted">30000</text> |
| 192 | - <rect x="436.0" y="422.7" width="72.5" height="1.3" class="bar-glazer"><title>glazer: 483.4 (encode)</title></rect> |
| 193 | - <text x="472.2" y="419.7" text-anchor="middle" font-size="8" class="muted">483.4</text> |
| 191 | + <text x="424.0" y="347.0" text-anchor="end" font-size="9" class="muted">40000</text> |
| 192 | + <rect x="436.0" y="423.1" width="72.5" height="0.9" class="bar-glazer"><title>glazer: 469.5 (encode)</title></rect> |
| 193 | + <text x="472.2" y="420.1" text-anchor="middle" font-size="8" class="muted">469.5</text> |
| 194 194 | <text x="472.2" y="434.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 472.2,434.0)">glazer</text> |
| 195 | - <rect x="514.5" y="416.8" width="72.5" height="7.2" class="bar-1"><title>nimble_csv: 2709.7 (encode)</title></rect> |
| 196 | - <text x="550.8" y="413.8" text-anchor="middle" font-size="8" class="muted">2709.7</text> |
| 195 | + <rect x="514.5" y="417.6" width="72.5" height="6.4" class="bar-1"><title>nimble_csv: 3204.4 (encode)</title></rect> |
| 196 | + <text x="550.8" y="414.6" text-anchor="middle" font-size="8" class="muted">3204.4</text> |
| 197 197 | <text x="550.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 550.8,434.0)">nimble_csv</text> |
| 198 | - <rect x="593.0" y="378.8" width="72.5" height="45.2" class="bar-2"><title>csv: 16959.9 (encode)</title></rect> |
| 199 | - <text x="629.2" y="375.8" text-anchor="middle" font-size="8" class="muted">16959.9</text> |
| 198 | + <rect x="593.0" y="375.2" width="72.5" height="48.8" class="bar-2"><title>csv: 24393.9 (encode)</title></rect> |
| 199 | + <text x="629.2" y="372.2" text-anchor="middle" font-size="8" class="muted">24393.9</text> |
| 200 200 | <text x="629.2" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 629.2,434.0)">csv</text> |
| 201 | - <rect x="671.5" y="360.6" width="72.5" height="63.4" class="bar-3"><title>erl_csv: 23761.5 (encode)</title></rect> |
| 202 | - <text x="707.8" y="357.6" text-anchor="middle" font-size="8" class="muted">23761.5</text> |
| 201 | + <rect x="671.5" y="354.8" width="72.5" height="69.2" class="bar-3"><title>erl_csv: 34607.9 (encode)</title></rect> |
| 202 | + <text x="707.8" y="351.8" text-anchor="middle" font-size="8" class="muted">34607.9</text> |
| 203 203 | <text x="707.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 707.8,434.0)">erl_csv</text> |
| 204 204 | <line x1="430.0" y1="424.0" x2="750.0" y2="424.0" class="axis" stroke-width="1"/> |
| 205 205 | </svg> |
| \ No newline at end of file |
| @@ -44,71 +44,69 @@ | |
| 44 44 | <text x="190.0" y="66.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">JSON decode — 0.1K</text> |
| 45 45 | <line x1="50.0" y1="148.0" x2="370.0" y2="148.0" class="grid" stroke-width="1"/> |
| 46 46 | <text x="44.0" y="151.0" text-anchor="end" font-size="9" class="muted">0</text> |
| 47 | - <line x1="50.0" y1="128.0" x2="370.0" y2="128.0" class="grid" stroke-width="1"/> |
| 48 | - <text x="44.0" y="131.0" text-anchor="end" font-size="9" class="muted">1</text> |
| 49 | - <line x1="50.0" y1="108.0" x2="370.0" y2="108.0" class="grid" stroke-width="1"/> |
| 50 | - <text x="44.0" y="111.0" text-anchor="end" font-size="9" class="muted">2</text> |
| 51 | - <line x1="50.0" y1="88.0" x2="370.0" y2="88.0" class="grid" stroke-width="1"/> |
| 52 | - <text x="44.0" y="91.0" text-anchor="end" font-size="9" class="muted">3</text> |
| 47 | + <line x1="50.0" y1="121.3" x2="370.0" y2="121.3" class="grid" stroke-width="1"/> |
| 48 | + <text x="44.0" y="124.3" text-anchor="end" font-size="9" class="muted">2</text> |
| 49 | + <line x1="50.0" y1="94.7" x2="370.0" y2="94.7" class="grid" stroke-width="1"/> |
| 50 | + <text x="44.0" y="97.7" text-anchor="end" font-size="9" class="muted">4</text> |
| 53 51 | <line x1="50.0" y1="68.0" x2="370.0" y2="68.0" class="grid" stroke-width="1"/> |
| 54 | - <text x="44.0" y="71.0" text-anchor="end" font-size="9" class="muted">4</text> |
| 55 | - <rect x="56.0" y="130.0" width="33.2" height="18.0" class="bar-glazer"><title>glazer: 0.9 (decode)</title></rect> |
| 56 | - <text x="72.6" y="127.0" text-anchor="middle" font-size="8" class="muted">0.9</text> |
| 52 | + <text x="44.0" y="71.0" text-anchor="end" font-size="9" class="muted">6</text> |
| 53 | + <rect x="56.0" y="132.0" width="33.2" height="16.0" class="bar-glazer"><title>glazer: 1.2 (decode)</title></rect> |
| 54 | + <text x="72.6" y="129.0" text-anchor="middle" font-size="8" class="muted">1.2</text> |
| 57 55 | <text x="72.6" y="158.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 72.6,158.0)">glazer</text> |
| 58 | - <rect x="95.2" y="112.0" width="33.2" height="36.0" class="bar-1"><title>torque: 1.8 (decode)</title></rect> |
| 59 | - <text x="111.9" y="109.0" text-anchor="middle" font-size="8" class="muted">1.8</text> |
| 56 | + <rect x="95.2" y="125.3" width="33.2" height="22.7" class="bar-1"><title>torque: 1.7 (decode)</title></rect> |
| 57 | + <text x="111.9" y="122.3" text-anchor="middle" font-size="8" class="muted">1.7</text> |
| 60 58 | <text x="111.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 111.9,158.0)">torque</text> |
| 61 | - <rect x="134.5" y="124.0" width="33.2" height="24.0" class="bar-2"><title>simdjsone: 1.2 (decode)</title></rect> |
| 62 | - <text x="151.1" y="121.0" text-anchor="middle" font-size="8" class="muted">1.2</text> |
| 59 | + <rect x="134.5" y="122.7" width="33.2" height="25.3" class="bar-2"><title>simdjsone: 1.9 (decode)</title></rect> |
| 60 | + <text x="151.1" y="119.7" text-anchor="middle" font-size="8" class="muted">1.9</text> |
| 63 61 | <text x="151.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 151.1,158.0)">simdjsone</text> |
| 64 | - <rect x="173.8" y="112.0" width="33.2" height="36.0" class="bar-3"><title>jiffy: 1.8 (decode)</title></rect> |
| 65 | - <text x="190.4" y="109.0" text-anchor="middle" font-size="8" class="muted">1.8</text> |
| 62 | + <rect x="173.8" y="114.7" width="33.2" height="33.3" class="bar-3"><title>jiffy: 2.5 (decode)</title></rect> |
| 63 | + <text x="190.4" y="111.7" text-anchor="middle" font-size="8" class="muted">2.5</text> |
| 66 64 | <text x="190.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 190.4,158.0)">jiffy</text> |
| 67 | - <rect x="213.0" y="92.0" width="33.2" height="56.0" class="bar-4"><title>jason: 2.8 (decode)</title></rect> |
| 68 | - <text x="229.6" y="89.0" text-anchor="middle" font-size="8" class="muted">2.8</text> |
| 65 | + <rect x="213.0" y="89.3" width="33.2" height="58.7" class="bar-4"><title>jason: 4.4 (decode)</title></rect> |
| 66 | + <text x="229.6" y="86.3" text-anchor="middle" font-size="8" class="muted">4.4</text> |
| 69 67 | <text x="229.6" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 229.6,158.0)">jason</text> |
| 70 | - <rect x="252.2" y="96.0" width="33.2" height="52.0" class="bar-5"><title>thoas: 2.6 (decode)</title></rect> |
| 71 | - <text x="268.9" y="93.0" text-anchor="middle" font-size="8" class="muted">2.6</text> |
| 68 | + <rect x="252.2" y="105.3" width="33.2" height="42.7" class="bar-5"><title>thoas: 3.2 (decode)</title></rect> |
| 69 | + <text x="268.9" y="102.3" text-anchor="middle" font-size="8" class="muted">3.2</text> |
| 72 70 | <text x="268.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 268.9,158.0)">thoas</text> |
| 73 | - <rect x="291.5" y="86.0" width="33.2" height="62.0" class="bar-6"><title>euneus: 3.1 (decode)</title></rect> |
| 74 | - <text x="308.1" y="83.0" text-anchor="middle" font-size="8" class="muted">3.1</text> |
| 71 | + <rect x="291.5" y="94.7" width="33.2" height="53.3" class="bar-6"><title>euneus: 4 (decode)</title></rect> |
| 72 | + <text x="308.1" y="91.7" text-anchor="middle" font-size="8" class="muted">4</text> |
| 75 73 | <text x="308.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 308.1,158.0)">euneus</text> |
| 76 | - <rect x="330.8" y="98.0" width="33.2" height="50.0" class="bar-7"><title>json: 2.5 (decode)</title></rect> |
| 77 | - <text x="347.4" y="95.0" text-anchor="middle" font-size="8" class="muted">2.5</text> |
| 74 | + <rect x="330.8" y="94.7" width="33.2" height="53.3" class="bar-7"><title>json: 4 (decode)</title></rect> |
| 75 | + <text x="347.4" y="91.7" text-anchor="middle" font-size="8" class="muted">4</text> |
| 78 76 | <text x="347.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 347.4,158.0)">json</text> |
| 79 77 | <line x1="50.0" y1="148.0" x2="370.0" y2="148.0" class="axis" stroke-width="1"/> |
| 80 78 | <text x="570.0" y="66.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">JSON encode — 0.1K</text> |
| 81 79 | <line x1="430.0" y1="148.0" x2="750.0" y2="148.0" class="grid" stroke-width="1"/> |
| 82 80 | <text x="424.0" y="151.0" text-anchor="end" font-size="9" class="muted">0</text> |
| 83 81 | <line x1="430.0" y1="121.3" x2="750.0" y2="121.3" class="grid" stroke-width="1"/> |
| 84 | - <text x="424.0" y="124.3" text-anchor="end" font-size="9" class="muted">1</text> |
| 82 | + <text x="424.0" y="124.3" text-anchor="end" font-size="9" class="muted">2</text> |
| 85 83 | <line x1="430.0" y1="94.7" x2="750.0" y2="94.7" class="grid" stroke-width="1"/> |
| 86 | - <text x="424.0" y="97.7" text-anchor="end" font-size="9" class="muted">2</text> |
| 84 | + <text x="424.0" y="97.7" text-anchor="end" font-size="9" class="muted">4</text> |
| 87 85 | <line x1="430.0" y1="68.0" x2="750.0" y2="68.0" class="grid" stroke-width="1"/> |
| 88 | - <text x="424.0" y="71.0" text-anchor="end" font-size="9" class="muted">3</text> |
| 89 | - <rect x="436.0" y="126.7" width="33.2" height="21.3" class="bar-glazer"><title>glazer: 0.8 (encode)</title></rect> |
| 90 | - <text x="452.6" y="123.7" text-anchor="middle" font-size="8" class="muted">0.8</text> |
| 86 | + <text x="424.0" y="71.0" text-anchor="end" font-size="9" class="muted">6</text> |
| 87 | + <rect x="436.0" y="134.7" width="33.2" height="13.3" class="bar-glazer"><title>glazer: 1 (encode)</title></rect> |
| 88 | + <text x="452.6" y="131.7" text-anchor="middle" font-size="8" class="muted">1</text> |
| 91 89 | <text x="452.6" y="158.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 452.6,158.0)">glazer</text> |
| 92 | - <rect x="475.2" y="110.7" width="33.2" height="37.3" class="bar-1"><title>torque: 1.4 (encode)</title></rect> |
| 93 | - <text x="491.9" y="107.7" text-anchor="middle" font-size="8" class="muted">1.4</text> |
| 90 | + <rect x="475.2" y="130.7" width="33.2" height="17.3" class="bar-1"><title>torque: 1.3 (encode)</title></rect> |
| 91 | + <text x="491.9" y="127.7" text-anchor="middle" font-size="8" class="muted">1.3</text> |
| 94 92 | <text x="491.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 491.9,158.0)">torque</text> |
| 95 | - <rect x="514.5" y="92.0" width="33.2" height="56.0" class="bar-2"><title>simdjsone: 2.1 (encode)</title></rect> |
| 96 | - <text x="531.1" y="89.0" text-anchor="middle" font-size="8" class="muted">2.1</text> |
| 93 | + <rect x="514.5" y="100.0" width="33.2" height="48.0" class="bar-2"><title>simdjsone: 3.6 (encode)</title></rect> |
| 94 | + <text x="531.1" y="97.0" text-anchor="middle" font-size="8" class="muted">3.6</text> |
| 97 95 | <text x="531.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 531.1,158.0)">simdjsone</text> |
| 98 | - <rect x="553.8" y="97.3" width="33.2" height="50.7" class="bar-3"><title>jiffy: 1.9 (encode)</title></rect> |
| 99 | - <text x="570.4" y="94.3" text-anchor="middle" font-size="8" class="muted">1.9</text> |
| 96 | + <rect x="553.8" y="97.3" width="33.2" height="50.7" class="bar-3"><title>jiffy: 3.8 (encode)</title></rect> |
| 97 | + <text x="570.4" y="94.3" text-anchor="middle" font-size="8" class="muted">3.8</text> |
| 100 98 | <text x="570.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 570.4,158.0)">jiffy</text> |
| 101 | - <rect x="593.0" y="89.3" width="33.2" height="58.7" class="bar-4"><title>jason: 2.2 (encode)</title></rect> |
| 102 | - <text x="609.6" y="86.3" text-anchor="middle" font-size="8" class="muted">2.2</text> |
| 99 | + <rect x="593.0" y="109.3" width="33.2" height="38.7" class="bar-4"><title>jason: 2.9 (encode)</title></rect> |
| 100 | + <text x="609.6" y="106.3" text-anchor="middle" font-size="8" class="muted">2.9</text> |
| 103 101 | <text x="609.6" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 609.6,158.0)">jason</text> |
| 104 | - <rect x="632.2" y="86.7" width="33.2" height="61.3" class="bar-5"><title>thoas: 2.3 (encode)</title></rect> |
| 105 | - <text x="648.9" y="83.7" text-anchor="middle" font-size="8" class="muted">2.3</text> |
| 102 | + <rect x="632.2" y="96.0" width="33.2" height="52.0" class="bar-5"><title>thoas: 3.9 (encode)</title></rect> |
| 103 | + <text x="648.9" y="93.0" text-anchor="middle" font-size="8" class="muted">3.9</text> |
| 106 104 | <text x="648.9" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 648.9,158.0)">thoas</text> |
| 107 | - <rect x="671.5" y="92.0" width="33.2" height="56.0" class="bar-6"><title>euneus: 2.1 (encode)</title></rect> |
| 108 | - <text x="688.1" y="89.0" text-anchor="middle" font-size="8" class="muted">2.1</text> |
| 105 | + <rect x="671.5" y="86.7" width="33.2" height="61.3" class="bar-6"><title>euneus: 4.6 (encode)</title></rect> |
| 106 | + <text x="688.1" y="83.7" text-anchor="middle" font-size="8" class="muted">4.6</text> |
| 109 107 | <text x="688.1" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 688.1,158.0)">euneus</text> |
| 110 | - <rect x="710.8" y="100.0" width="33.2" height="48.0" class="bar-7"><title>json: 1.8 (encode)</title></rect> |
| 111 | - <text x="727.4" y="97.0" text-anchor="middle" font-size="8" class="muted">1.8</text> |
| 108 | + <rect x="710.8" y="88.0" width="33.2" height="60.0" class="bar-7"><title>json: 4.5 (encode)</title></rect> |
| 109 | + <text x="727.4" y="85.0" text-anchor="middle" font-size="8" class="muted">4.5</text> |
| 112 110 | <text x="727.4" y="158.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 727.4,158.0)">json</text> |
| 113 111 | <line x1="430.0" y1="148.0" x2="750.0" y2="148.0" class="axis" stroke-width="1"/> |
| 114 112 | <text x="190.0" y="204.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">YAML decode — 0.1K</text> |
| @@ -122,17 +120,17 @@ | |
| 122 120 | <text x="44.0" y="229.0" text-anchor="end" font-size="9" class="muted">600</text> |
| 123 121 | <line x1="50.0" y1="206.0" x2="370.0" y2="206.0" class="grid" stroke-width="1"/> |
| 124 122 | <text x="44.0" y="209.0" text-anchor="end" font-size="9" class="muted">800</text> |
| 125 | - <rect x="56.0" y="285.1" width="56.8" height="0.9" class="bar-glazer"><title>glazer: 9.1 (decode)</title></rect> |
| 126 | - <text x="84.4" y="282.1" text-anchor="middle" font-size="8" class="muted">9.1</text> |
| 123 | + <rect x="56.0" y="284.9" width="56.8" height="1.1" class="bar-glazer"><title>glazer: 11.5 (decode)</title></rect> |
| 124 | + <text x="84.4" y="281.9" text-anchor="middle" font-size="8" class="muted">11.5</text> |
| 127 125 | <text x="84.4" y="296.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 84.4,296.0)">glazer</text> |
| 128 | - <rect x="118.8" y="284.6" width="56.8" height="1.4" class="bar-1"><title>yaml_rustler: 14.4 (decode)</title></rect> |
| 129 | - <text x="147.2" y="281.6" text-anchor="middle" font-size="8" class="muted">14.4</text> |
| 126 | + <rect x="118.8" y="284.3" width="56.8" height="1.7" class="bar-1"><title>yaml_rustler: 16.9 (decode)</title></rect> |
| 127 | + <text x="147.2" y="281.3" text-anchor="middle" font-size="8" class="muted">16.9</text> |
| 130 128 | <text x="147.2" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 147.2,296.0)">yaml_rustler</text> |
| 131 | - <rect x="181.6" y="283.0" width="56.8" height="3.0" class="bar-2"><title>fast_yaml: 29.9 (decode)</title></rect> |
| 132 | - <text x="210.0" y="280.0" text-anchor="middle" font-size="8" class="muted">29.9</text> |
| 129 | + <rect x="181.6" y="283.3" width="56.8" height="2.7" class="bar-2"><title>fast_yaml: 26.7 (decode)</title></rect> |
| 130 | + <text x="210.0" y="280.3" text-anchor="middle" font-size="8" class="muted">26.7</text> |
| 133 131 | <text x="210.0" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 210.0,296.0)">fast_yaml</text> |
| 134 | - <rect x="244.4" y="210.7" width="56.8" height="75.3" class="bar-3"><title>yamerl: 753.5 (decode)</title></rect> |
| 135 | - <text x="272.8" y="207.7" text-anchor="middle" font-size="8" class="muted">753.5</text> |
| 132 | + <rect x="244.4" y="218.4" width="56.8" height="67.6" class="bar-3"><title>yamerl: 676.1 (decode)</title></rect> |
| 133 | + <text x="272.8" y="215.4" text-anchor="middle" font-size="8" class="muted">676.1</text> |
| 136 134 | <text x="272.8" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 272.8,296.0)">yamerl</text> |
| 137 135 | <text x="335.6" y="282.0" text-anchor="middle" font-size="8" class="faint">N/A</text> |
| 138 136 | <text x="335.6" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 335.6,296.0)">ymlr</text> |
| @@ -140,70 +138,72 @@ | |
| 140 138 | <text x="570.0" y="204.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">YAML encode — 0.1K</text> |
| 141 139 | <line x1="430.0" y1="286.0" x2="750.0" y2="286.0" class="grid" stroke-width="1"/> |
| 142 140 | <text x="424.0" y="289.0" text-anchor="end" font-size="9" class="muted">0</text> |
| 143 | - <line x1="430.0" y1="259.3" x2="750.0" y2="259.3" class="grid" stroke-width="1"/> |
| 144 | - <text x="424.0" y="262.3" text-anchor="end" font-size="9" class="muted">5</text> |
| 145 | - <line x1="430.0" y1="232.7" x2="750.0" y2="232.7" class="grid" stroke-width="1"/> |
| 146 | - <text x="424.0" y="235.7" text-anchor="end" font-size="9" class="muted">10</text> |
| 141 | + <line x1="430.0" y1="266.0" x2="750.0" y2="266.0" class="grid" stroke-width="1"/> |
| 142 | + <text x="424.0" y="269.0" text-anchor="end" font-size="9" class="muted">2</text> |
| 143 | + <line x1="430.0" y1="246.0" x2="750.0" y2="246.0" class="grid" stroke-width="1"/> |
| 144 | + <text x="424.0" y="249.0" text-anchor="end" font-size="9" class="muted">4</text> |
| 145 | + <line x1="430.0" y1="226.0" x2="750.0" y2="226.0" class="grid" stroke-width="1"/> |
| 146 | + <text x="424.0" y="229.0" text-anchor="end" font-size="9" class="muted">6</text> |
| 147 147 | <line x1="430.0" y1="206.0" x2="750.0" y2="206.0" class="grid" stroke-width="1"/> |
| 148 | - <text x="424.0" y="209.0" text-anchor="end" font-size="9" class="muted">15</text> |
| 149 | - <rect x="436.0" y="280.1" width="56.8" height="5.9" class="bar-glazer"><title>glazer: 1.1 (encode)</title></rect> |
| 150 | - <text x="464.4" y="277.1" text-anchor="middle" font-size="8" class="muted">1.1</text> |
| 148 | + <text x="424.0" y="209.0" text-anchor="end" font-size="9" class="muted">8</text> |
| 149 | + <rect x="436.0" y="264.0" width="56.8" height="22.0" class="bar-glazer"><title>glazer: 2.2 (encode)</title></rect> |
| 150 | + <text x="464.4" y="261.0" text-anchor="middle" font-size="8" class="muted">2.2</text> |
| 151 151 | <text x="464.4" y="296.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 464.4,296.0)">glazer</text> |
| 152 152 | <text x="527.2" y="282.0" text-anchor="middle" font-size="8" class="faint">N/A</text> |
| 153 153 | <text x="527.2" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 527.2,296.0)">yaml_rustler</text> |
| 154 | - <rect x="561.6" y="241.7" width="56.8" height="44.3" class="bar-2"><title>fast_yaml: 8.3 (encode)</title></rect> |
| 155 | - <text x="590.0" y="238.7" text-anchor="middle" font-size="8" class="muted">8.3</text> |
| 154 | + <rect x="561.6" y="210.0" width="56.8" height="76.0" class="bar-2"><title>fast_yaml: 7.6 (encode)</title></rect> |
| 155 | + <text x="590.0" y="207.0" text-anchor="middle" font-size="8" class="muted">7.6</text> |
| 156 156 | <text x="590.0" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 590.0,296.0)">fast_yaml</text> |
| 157 157 | <text x="652.8" y="282.0" text-anchor="middle" font-size="8" class="faint">N/A</text> |
| 158 158 | <text x="652.8" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 652.8,296.0)">yamerl</text> |
| 159 | - <rect x="687.2" y="207.1" width="56.8" height="78.9" class="bar-4"><title>ymlr: 14.8 (encode)</title></rect> |
| 160 | - <text x="715.6" y="204.1" text-anchor="middle" font-size="8" class="muted">14.8</text> |
| 159 | + <rect x="687.2" y="227.0" width="56.8" height="59.0" class="bar-4"><title>ymlr: 5.9 (encode)</title></rect> |
| 160 | + <text x="715.6" y="224.0" text-anchor="middle" font-size="8" class="muted">5.9</text> |
| 161 161 | <text x="715.6" y="296.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 715.6,296.0)">ymlr</text> |
| 162 162 | <line x1="430.0" y1="286.0" x2="750.0" y2="286.0" class="axis" stroke-width="1"/> |
| 163 163 | <text x="190.0" y="342.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">CSV decode — 1.3K</text> |
| 164 164 | <line x1="50.0" y1="424.0" x2="370.0" y2="424.0" class="grid" stroke-width="1"/> |
| 165 165 | <text x="44.0" y="427.0" text-anchor="end" font-size="9" class="muted">0</text> |
| 166 166 | <line x1="50.0" y1="404.0" x2="370.0" y2="404.0" class="grid" stroke-width="1"/> |
| 167 | - <text x="44.0" y="407.0" text-anchor="end" font-size="9" class="muted">100</text> |
| 167 | + <text x="44.0" y="407.0" text-anchor="end" font-size="9" class="muted">200</text> |
| 168 168 | <line x1="50.0" y1="384.0" x2="370.0" y2="384.0" class="grid" stroke-width="1"/> |
| 169 | - <text x="44.0" y="387.0" text-anchor="end" font-size="9" class="muted">200</text> |
| 169 | + <text x="44.0" y="387.0" text-anchor="end" font-size="9" class="muted">400</text> |
| 170 170 | <line x1="50.0" y1="364.0" x2="370.0" y2="364.0" class="grid" stroke-width="1"/> |
| 171 | - <text x="44.0" y="367.0" text-anchor="end" font-size="9" class="muted">300</text> |
| 171 | + <text x="44.0" y="367.0" text-anchor="end" font-size="9" class="muted">600</text> |
| 172 172 | <line x1="50.0" y1="344.0" x2="370.0" y2="344.0" class="grid" stroke-width="1"/> |
| 173 | - <text x="44.0" y="347.0" text-anchor="end" font-size="9" class="muted">400</text> |
| 174 | - <rect x="56.0" y="420.6" width="72.5" height="3.4" class="bar-glazer"><title>glazer: 17.2 (decode)</title></rect> |
| 175 | - <text x="92.2" y="417.6" text-anchor="middle" font-size="8" class="muted">17.2</text> |
| 173 | + <text x="44.0" y="347.0" text-anchor="end" font-size="9" class="muted">800</text> |
| 174 | + <rect x="56.0" y="422.9" width="72.5" height="1.1" class="bar-glazer"><title>glazer: 10.7 (decode)</title></rect> |
| 175 | + <text x="92.2" y="419.9" text-anchor="middle" font-size="8" class="muted">10.7</text> |
| 176 176 | <text x="92.2" y="434.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 92.2,434.0)">glazer</text> |
| 177 | - <rect x="134.5" y="414.9" width="72.5" height="9.1" class="bar-1"><title>nimble_csv: 45.7 (decode)</title></rect> |
| 178 | - <text x="170.8" y="411.9" text-anchor="middle" font-size="8" class="muted">45.7</text> |
| 177 | + <rect x="134.5" y="419.5" width="72.5" height="4.5" class="bar-1"><title>nimble_csv: 44.8 (decode)</title></rect> |
| 178 | + <text x="170.8" y="416.5" text-anchor="middle" font-size="8" class="muted">44.8</text> |
| 179 179 | <text x="170.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 170.8,434.0)">nimble_csv</text> |
| 180 | - <rect x="213.0" y="406.0" width="72.5" height="18.0" class="bar-2"><title>csv: 89.8 (decode)</title></rect> |
| 181 | - <text x="249.2" y="403.0" text-anchor="middle" font-size="8" class="muted">89.8</text> |
| 180 | + <rect x="213.0" y="414.1" width="72.5" height="9.9" class="bar-2"><title>csv: 99.3 (decode)</title></rect> |
| 181 | + <text x="249.2" y="411.1" text-anchor="middle" font-size="8" class="muted">99.3</text> |
| 182 182 | <text x="249.2" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 249.2,434.0)">csv</text> |
| 183 | - <rect x="291.5" y="347.5" width="72.5" height="76.5" class="bar-3"><title>erl_csv: 382.3 (decode)</title></rect> |
| 184 | - <text x="327.8" y="344.5" text-anchor="middle" font-size="8" class="muted">382.3</text> |
| 183 | + <rect x="291.5" y="353.4" width="72.5" height="70.6" class="bar-3"><title>erl_csv: 705.5 (decode)</title></rect> |
| 184 | + <text x="327.8" y="350.4" text-anchor="middle" font-size="8" class="muted">705.5</text> |
| 185 185 | <text x="327.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 327.8,434.0)">erl_csv</text> |
| 186 186 | <line x1="50.0" y1="424.0" x2="370.0" y2="424.0" class="axis" stroke-width="1"/> |
| 187 187 | <text x="570.0" y="342.0" text-anchor="middle" font-size="13" font-weight="bold" class="fg">CSV encode — 1.3K</text> |
| 188 188 | <line x1="430.0" y1="424.0" x2="750.0" y2="424.0" class="grid" stroke-width="1"/> |
| 189 189 | <text x="424.0" y="427.0" text-anchor="end" font-size="9" class="muted">0</text> |
| 190 190 | <line x1="430.0" y1="397.3" x2="750.0" y2="397.3" class="grid" stroke-width="1"/> |
| 191 | - <text x="424.0" y="400.3" text-anchor="end" font-size="9" class="muted">100</text> |
| 191 | + <text x="424.0" y="400.3" text-anchor="end" font-size="9" class="muted">200</text> |
| 192 192 | <line x1="430.0" y1="370.7" x2="750.0" y2="370.7" class="grid" stroke-width="1"/> |
| 193 | - <text x="424.0" y="373.7" text-anchor="end" font-size="9" class="muted">200</text> |
| 193 | + <text x="424.0" y="373.7" text-anchor="end" font-size="9" class="muted">400</text> |
| 194 194 | <line x1="430.0" y1="344.0" x2="750.0" y2="344.0" class="grid" stroke-width="1"/> |
| 195 | - <text x="424.0" y="347.0" text-anchor="end" font-size="9" class="muted">300</text> |
| 196 | - <rect x="436.0" y="422.1" width="72.5" height="1.9" class="bar-glazer"><title>glazer: 7.3 (encode)</title></rect> |
| 197 | - <text x="472.2" y="419.1" text-anchor="middle" font-size="8" class="muted">7.3</text> |
| 195 | + <text x="424.0" y="347.0" text-anchor="end" font-size="9" class="muted">600</text> |
| 196 | + <rect x="436.0" y="423.6" width="72.5" height="0.4" class="bar-glazer"><title>glazer: 3.3 (encode)</title></rect> |
| 197 | + <text x="472.2" y="420.6" text-anchor="middle" font-size="8" class="muted">3.3</text> |
| 198 198 | <text x="472.2" y="434.0" text-anchor="end" font-size="9" class="fg" font-weight="bold" transform="rotate(-35 472.2,434.0)">glazer</text> |
| 199 | - <rect x="514.5" y="415.7" width="72.5" height="8.3" class="bar-1"><title>nimble_csv: 31.3 (encode)</title></rect> |
| 200 | - <text x="550.8" y="412.7" text-anchor="middle" font-size="8" class="muted">31.3</text> |
| 199 | + <rect x="514.5" y="418.8" width="72.5" height="5.2" class="bar-1"><title>nimble_csv: 38.8 (encode)</title></rect> |
| 200 | + <text x="550.8" y="415.8" text-anchor="middle" font-size="8" class="muted">38.8</text> |
| 201 201 | <text x="550.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 550.8,434.0)">nimble_csv</text> |
| 202 | - <rect x="593.0" y="375.5" width="72.5" height="48.5" class="bar-2"><title>csv: 182 (encode)</title></rect> |
| 203 | - <text x="629.2" y="372.5" text-anchor="middle" font-size="8" class="muted">182</text> |
| 202 | + <rect x="593.0" y="389.7" width="72.5" height="34.3" class="bar-2"><title>csv: 257.3 (encode)</title></rect> |
| 203 | + <text x="629.2" y="386.7" text-anchor="middle" font-size="8" class="muted">257.3</text> |
| 204 204 | <text x="629.2" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 629.2,434.0)">csv</text> |
| 205 | - <rect x="671.5" y="348.0" width="72.5" height="76.0" class="bar-3"><title>erl_csv: 285.1 (encode)</title></rect> |
| 206 | - <text x="707.8" y="345.0" text-anchor="middle" font-size="8" class="muted">285.1</text> |
| 205 | + <rect x="671.5" y="367.0" width="72.5" height="57.0" class="bar-3"><title>erl_csv: 427.4 (encode)</title></rect> |
| 206 | + <text x="707.8" y="364.0" text-anchor="middle" font-size="8" class="muted">427.4</text> |
| 207 207 | <text x="707.8" y="434.0" text-anchor="end" font-size="9" class="fg" transform="rotate(-35 707.8,434.0)">erl_csv</text> |
| 208 208 | <line x1="430.0" y1="424.0" x2="750.0" y2="424.0" class="axis" stroke-width="1"/> |
| 209 209 | </svg> |
| \ No newline at end of file |
Loading more files…