docs: add three figures to the 3.13.0 post
- short strings: two overlapping 16-byte loads and stores - eight digits at a time: the three multiplications, lane by lane - validate on the 19 held-out files, per file, Mac and x86-64 The prose the figures replace is trimmed. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
6 files changed
+3606
-12
No files matched your search
@@ -391,10 +391,14 @@ vst1q_u8(d + n - 16, b); // the two stores overlap too, with the same bytes
|
||||
|
||||
<p class="nj-code-caption" markdown>Writing a string of 16 to 32 bytes with two overlapping loads and stores (NEON).</p>
|
||||
|
||||
Both loads lie inside the string, together they cover all of it, and all tests happen before the first store. Shorter
|
||||
strings use the same trick with two overlapping 8-, 4- or 2-byte loads, so no `memcpy` with a length known only at run
|
||||
time is left. On `twitter.json`,
|
||||
this cut the instructions of `dump()` by 21 %.
|
||||
<div class="nj-fig-wrap" markdown>
|
||||
--8<-- "images/perf_blog_overlap.svg"
|
||||
</div>
|
||||
|
||||
<p class="nj-caption" markdown>The code above on `profile_link_color`, a key of `twitter.json`.</p>
|
||||
|
||||
Shorter strings use the same trick with two overlapping 8-, 4- or 2-byte loads, so no `memcpy` with a length known
|
||||
only at run time is left. On `twitter.json`, this cut the instructions of `dump()` by 21 %.
|
||||
|
||||
### Escapes from a table
|
||||
|
||||
@@ -476,11 +480,14 @@ std::uint32_t parse_eight_digits(std::uint64_t v) noexcept
|
||||
|
||||
<p class="nj-code-caption" markdown>fast_float's conversion of eight ASCII digits to their value, with three multiplications.</p>
|
||||
|
||||
The mask turns the characters into digit values. Multiplying by `10·2⁸ + 1` adds ten times each byte to the byte
|
||||
above it, so after the shift every second byte holds a two-digit number: `"12345678"` becomes 12, 34, 56 and 78. The
|
||||
second step does the same with pairs of bytes and a factor of 100 (1234 and 5678), the third with 32-bit halves and
|
||||
10,000. Whether all eight bytes are digits is one more expression: a digit is 0x30 to 0x39, so its high nibble must be
|
||||
3, and adding 6 must keep it 3. Integers of up to 18 digits and floats of up to 19 then need no overflow check at all.
|
||||
<div class="nj-fig-wrap" markdown>
|
||||
--8<-- "images/perf_blog_digits.svg"
|
||||
</div>
|
||||
|
||||
<p class="nj-caption" markdown>`parse_eight_digits()` on `"12345678"`: multiplying by `10·2⁸ + 1` adds ten times each byte to the byte above it, and the shift and the next mask keep every second lane.</p>
|
||||
|
||||
Whether all eight bytes are digits is one more expression: a digit is 0x30 to 0x39, so its high nibble must be 3, and
|
||||
adding 6 must keep it 3. Integers of up to 18 digits and floats of up to 19 then need no overflow check at all.
|
||||
|
||||
### Clinger's fast path
|
||||
|
||||
@@ -1290,9 +1297,17 @@ The four files are the ones 3.13.0 was tuned on, so we also ran *validate*, *sum
|
||||
other files of simdjson's [`jsonexamples`](https://github.com/simdjson/simdjson-data/tree/master/jsonexamples). By
|
||||
geometric mean, `json_document` stays the fastest in *validate*, *minify* and *write* on every compiler, and in *sum*
|
||||
with Clang and on the Mac; with GCC, simdjson sums in 0.83 to 0.85 of its time. File by file, it is less
|
||||
clear-cut: on x86-64, `json_document` validates only 4 to 8 of the 19 files fastest (13 on the Mac). simdjson wins 5
|
||||
to 8 of the others, and Boost.JSON, without number conversion, validates the number-heavy `mesh.pretty`, `numbers`
|
||||
and `marine_ik` up to 1.5 times as fast. We know two causes, but so far each fix slowed down other files.
|
||||
clear-cut:
|
||||
|
||||
<div class="nj-fig-wrap" markdown>
|
||||
--8<-- "images/perf_blog_heldout.svg"
|
||||
</div>
|
||||
|
||||
<p class="nj-caption" markdown>*validate* on the 19 files: `json_document`'s fastest fully validating way against the fastest library's, per file; 1.0× means it is the fastest. Less is better. The right column names the fastest library on x86-64 (GCC 16.2).</p>
|
||||
|
||||
On x86-64, `json_document` validates only 4 to 8 of the 19 files fastest, against 13 on the Mac. Boost.JSON, without
|
||||
number conversion, validates the number-heavy `mesh.pretty`, `numbers` and `marine_ik` up to 1.5 times as fast. We
|
||||
know two causes, but so far each fix slowed down other files.
|
||||
|
||||
Every *validate* way also ran the 318 files of [JSONTestSuite](https://github.com/nst/JSONTestSuite). The fully
|
||||
validating ways pass, with a few exceptions listed in [Appendix E](#e-comparison-with-other-libraries), one of them
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<svg class="nj-fig nj-charts nj-charts--swar" viewBox="0 0 600 430" role="img" aria-labelledby="nj-blog-digits nj-blog-digits-d" xmlns="http://www.w3.org/2000/svg">
|
||||
<title id="nj-blog-digits">Converting eight A​SCII digits to their value with three multiplications</title>
|
||||
<desc id="nj-blog-digits-d">The text 12345678 as one word. Masking gives the digit values 1 to 8, one per byte. Multiplying by 10 times 2 to the 8 plus 1 and shifting gives 12, 34, 56 and 78 in 16-bit lanes; multiplying by 100 times 2 to the 16 plus 1 gives 1234 and 5678 in 32-bit lanes; multiplying by 10000 times 2 to the 32 plus 1 gives 12345678.</desc>
|
||||
<text class="fg-h" x="40" y="20">eight A​SCII digits in one 64-bit word (byte 0 is the lowest)</text>
|
||||
<rect class="fg-cell" x="40" y="30" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="69" y="53" text-anchor="middle">1</text>
|
||||
<text class="nj-charts-tick" x="69" y="80">0x31</text>
|
||||
<rect class="fg-cell" x="104" y="30" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="133" y="53" text-anchor="middle">2</text>
|
||||
<text class="nj-charts-tick" x="133" y="80">0x32</text>
|
||||
<rect class="fg-cell" x="168" y="30" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="197" y="53" text-anchor="middle">3</text>
|
||||
<text class="nj-charts-tick" x="197" y="80">0x33</text>
|
||||
<rect class="fg-cell" x="232" y="30" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="261" y="53" text-anchor="middle">4</text>
|
||||
<text class="nj-charts-tick" x="261" y="80">0x34</text>
|
||||
<rect class="fg-cell" x="296" y="30" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="325" y="53" text-anchor="middle">5</text>
|
||||
<text class="nj-charts-tick" x="325" y="80">0x35</text>
|
||||
<rect class="fg-cell" x="360" y="30" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="389" y="53" text-anchor="middle">6</text>
|
||||
<text class="nj-charts-tick" x="389" y="80">0x36</text>
|
||||
<rect class="fg-cell" x="424" y="30" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="453" y="53" text-anchor="middle">7</text>
|
||||
<text class="nj-charts-tick" x="453" y="80">0x37</text>
|
||||
<rect class="fg-cell" x="488" y="30" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="517" y="53" text-anchor="middle">8</text>
|
||||
<text class="nj-charts-tick" x="517" y="80">0x38</text>
|
||||
<text class="fg-h" x="40" y="112">& 0x0F0F0F0F0F0F0F0F: one digit value per byte</text>
|
||||
<rect class="fg-cell" x="40" y="122" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="69" y="145" text-anchor="middle">1</text>
|
||||
<rect class="fg-cell" x="104" y="122" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="133" y="145" text-anchor="middle">2</text>
|
||||
<rect class="fg-cell" x="168" y="122" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="197" y="145" text-anchor="middle">3</text>
|
||||
<rect class="fg-cell" x="232" y="122" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="261" y="145" text-anchor="middle">4</text>
|
||||
<rect class="fg-cell" x="296" y="122" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="325" y="145" text-anchor="middle">5</text>
|
||||
<rect class="fg-cell" x="360" y="122" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="389" y="145" text-anchor="middle">6</text>
|
||||
<rect class="fg-cell" x="424" y="122" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="453" y="145" text-anchor="middle">7</text>
|
||||
<rect class="fg-cell" x="488" y="122" width="58" height="34" rx="4"/>
|
||||
<text class="fg-code" x="517" y="145" text-anchor="middle">8</text>
|
||||
<text class="fg-h" x="40" y="186">× (10 · 2⁸ + 1) >> 8, every second byte kept: two digits per 16 bits</text>
|
||||
<rect class="fg-cell" x="40" y="196" width="122" height="34" rx="4"/>
|
||||
<text class="fg-code" x="101" y="219" text-anchor="middle">12</text>
|
||||
<rect class="fg-cell" x="168" y="196" width="122" height="34" rx="4"/>
|
||||
<text class="fg-code" x="229" y="219" text-anchor="middle">34</text>
|
||||
<rect class="fg-cell" x="296" y="196" width="122" height="34" rx="4"/>
|
||||
<text class="fg-code" x="357" y="219" text-anchor="middle">56</text>
|
||||
<rect class="fg-cell" x="424" y="196" width="122" height="34" rx="4"/>
|
||||
<text class="fg-code" x="485" y="219" text-anchor="middle">78</text>
|
||||
<text class="fg-h" x="40" y="260">× (100 · 2¹⁶ + 1) >> 16, every second lane kept: four digits per 32 bits</text>
|
||||
<rect class="fg-cell" x="40" y="270" width="250" height="34" rx="4"/>
|
||||
<text class="fg-code" x="165" y="293" text-anchor="middle">1234</text>
|
||||
<rect class="fg-cell" x="296" y="270" width="250" height="34" rx="4"/>
|
||||
<text class="fg-code" x="421" y="293" text-anchor="middle">5678</text>
|
||||
<text class="fg-h" x="40" y="334">× (10000 · 2³² + 1) >> 32: the value</text>
|
||||
<rect class="fg-cell" x="40" y="344" width="506" height="34" rx="4"/>
|
||||
<rect class="nj-charts-c1" fill-opacity=".25" x="40" y="344" width="506" height="34" rx="4"/>
|
||||
<text class="fg-code" x="293" y="367" text-anchor="middle">12345678</text>
|
||||
<text class="fg-note fg-note--l" x="40" y="400">Each step combines neighboring lanes, in all lanes of the word at once:</text>
|
||||
<text class="fg-note fg-note--l" x="40" y="418">three multiplications instead of eight, and no branch.</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.0 KiB |
@@ -0,0 +1,98 @@
|
||||
<svg class="nj-fig nj-charts nj-charts--blog" viewBox="0 0 620 482" role="img" aria-labelledby="nj-blog-heldout nj-blog-heldout-d" xmlns="http://www.w3.org/2000/svg">
|
||||
<title id="nj-blog-heldout">Validating 19 files 3.13.0 was not tuned on: json_document's time relative to the fastest library per file</title>
|
||||
<desc id="nj-blog-heldout-d">Dot plot per file, less is better; 1.0 means json_document is the fastest fully validating library. github_events: Mac 1.00, x86-64 1.00 (nlohmann/json json_document); mesh: Mac 1.00, x86-64 1.00 (nlohmann/json json_document); semanticscholar-corpus: Mac 1.00, x86-64 1.00 (nlohmann/json json_document); twitter_api_compact_response: Mac 1.00, x86-64 1.00 (nlohmann/json json_document); twitter_api_response: Mac 1.00, x86-64 1.00 (nlohmann/json json_document); update-center: Mac 1.00, x86-64 1.00 (nlohmann/json json_document); apache_builds: Mac 1.15, x86-64 1.00 (nlohmann/json json_document); twitter_timeline: Mac 1.04, x86-64 1.02 (yyjson); twitterescaped: Mac 1.10, x86-64 1.08 (simdjson); gsoc-2018: Mac 1.00, x86-64 1.10 (Boost.J​SON); google_maps_api_compact_response: Mac 1.03, x86-64 1.12 (yyjson); tree-pretty: Mac 1.01, x86-64 1.14 (simdjson); repeat: Mac 1.00, x86-64 1.14 (simdjson); random: Mac 1.00, x86-64 1.17 (simdjson); instruments: Mac 1.00, x86-64 1.18 (simdjson); google_maps_api_response: Mac 1.01, x86-64 1.19 (simdjson); marine_ik: Mac 1.00, x86-64 1.23 (Boost.J​SON); numbers: Mac 1.00, x86-64 1.32 (Boost.J​SON); mesh.pretty: Mac 1.00, x86-64 1.49 (Boost.J​SON).</desc>
|
||||
<line class="nj-charts-grid" x1="262" y1="50" x2="262" y2="438"/>
|
||||
<text class="nj-charts-tick" x="262" y="454">1.0×</text>
|
||||
<line class="nj-charts-grid" x1="302.727" y1="50" x2="302.727" y2="438"/>
|
||||
<text class="nj-charts-tick" x="302.727" y="454">1.1×</text>
|
||||
<line class="nj-charts-grid" x1="343.455" y1="50" x2="343.455" y2="438"/>
|
||||
<text class="nj-charts-tick" x="343.455" y="454">1.2×</text>
|
||||
<line class="nj-charts-grid" x1="384.182" y1="50" x2="384.182" y2="438"/>
|
||||
<text class="nj-charts-tick" x="384.182" y="454">1.3×</text>
|
||||
<line class="nj-charts-grid" x1="424.909" y1="50" x2="424.909" y2="438"/>
|
||||
<text class="nj-charts-tick" x="424.909" y="454">1.4×</text>
|
||||
<line class="nj-charts-grid" x1="465.636" y1="50" x2="465.636" y2="438"/>
|
||||
<text class="nj-charts-tick" x="465.636" y="454">1.5×</text>
|
||||
<text class="nj-charts-tick" x="374" y="472">json_document’s time / the fastest library’s, less is better</text>
|
||||
<circle class="nj-charts-json-dot" cx="13" cy="14" r="5"/><text class="nj-charts-leg" x="23" y="18.5">Apple M1 Max</text>
|
||||
<circle class="nj-charts-ojson-dot" cx="134.2" cy="14" r="5"/><text class="nj-charts-leg" x="144.2" y="18.5">x86-64, G​CC 16.2</text>
|
||||
<text class="nj-charts-tick nj-charts-tick--l" x="500" y="48">fastest on x86-64</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="68" text-anchor="end">github_events</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="60.5" r="4.5"><title>github_events, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="262.0" cy="67.5" r="4.5"><title>github_events, x86-64, G​CC 16.2: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l" x="500" y="68">json_document</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="88" text-anchor="end">mesh</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="80.5" r="4.5"><title>mesh, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="262.0" cy="87.5" r="4.5"><title>mesh, x86-64, G​CC 16.2: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l" x="500" y="88">json_document</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="108" text-anchor="end">semanticscholar-corpus</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="100.5" r="4.5"><title>semanticscholar-corpus, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="262.0" cy="107.5" r="4.5"><title>semanticscholar-corpus, x86-64, G​CC 16.2: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l" x="500" y="108">json_document</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="128" text-anchor="end">twitter_api_compact_response</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="120.5" r="4.5"><title>twitter_api_compact_response, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="262.0" cy="127.5" r="4.5"><title>twitter_api_compact_response, x86-64, G​CC 16.2: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l" x="500" y="128">json_document</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="148" text-anchor="end">twitter_api_response</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="140.5" r="4.5"><title>twitter_api_response, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="262.0" cy="147.5" r="4.5"><title>twitter_api_response, x86-64, G​CC 16.2: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l" x="500" y="148">json_document</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="168" text-anchor="end">update-center</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="160.5" r="4.5"><title>update-center, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="262.0" cy="167.5" r="4.5"><title>update-center, x86-64, G​CC 16.2: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l" x="500" y="168">json_document</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="188" text-anchor="end">apache_builds</text>
|
||||
<circle class="nj-charts-json-dot" cx="323.8" cy="180.5" r="4.5"><title>apache_builds, Apple M1 Max: 1.15× the time of simdjson</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="262.0" cy="187.5" r="4.5"><title>apache_builds, x86-64, G​CC 16.2: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l" x="500" y="188">json_document</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="208" text-anchor="end">twitter_timeline</text>
|
||||
<circle class="nj-charts-json-dot" cx="277.6" cy="200.5" r="4.5"><title>twitter_timeline, Apple M1 Max: 1.04× the time of yyjson</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="270.8" cy="207.5" r="4.5"><title>twitter_timeline, x86-64, G​CC 16.2: 1.02× the time of yyjson</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="208">yyjson</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="228" text-anchor="end">twitterescaped</text>
|
||||
<circle class="nj-charts-json-dot" cx="303.1" cy="220.5" r="4.5"><title>twitterescaped, Apple M1 Max: 1.10× the time of yyjson</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="293.5" cy="227.5" r="4.5"><title>twitterescaped, x86-64, G​CC 16.2: 1.08× the time of simdjson</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="228">simdjson</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="248" text-anchor="end">gsoc-2018</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="240.5" r="4.5"><title>gsoc-2018, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="303.9" cy="247.5" r="4.5"><title>gsoc-2018, x86-64, G​CC 16.2: 1.10× the time of Boost.J​SON</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="248">Boost.J​SON</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="268" text-anchor="end">google_maps_api_compact_response</text>
|
||||
<circle class="nj-charts-json-dot" cx="274.9" cy="260.5" r="4.5"><title>google_maps_api_compact_response, Apple M1 Max: 1.03× the time of yyjson</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="310.6" cy="267.5" r="4.5"><title>google_maps_api_compact_response, x86-64, G​CC 16.2: 1.12× the time of yyjson</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="268">yyjson</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="288" text-anchor="end">tree-pretty</text>
|
||||
<circle class="nj-charts-json-dot" cx="265.6" cy="280.5" r="4.5"><title>tree-pretty, Apple M1 Max: 1.01× the time of simdjson</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="317.7" cy="287.5" r="4.5"><title>tree-pretty, x86-64, G​CC 16.2: 1.14× the time of simdjson</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="288">simdjson</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="308" text-anchor="end">repeat</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="300.5" r="4.5"><title>repeat, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="319.3" cy="307.5" r="4.5"><title>repeat, x86-64, G​CC 16.2: 1.14× the time of simdjson</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="308">simdjson</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="328" text-anchor="end">random</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="320.5" r="4.5"><title>random, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="333.3" cy="327.5" r="4.5"><title>random, x86-64, G​CC 16.2: 1.17× the time of simdjson</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="328">simdjson</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="348" text-anchor="end">instruments</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="340.5" r="4.5"><title>instruments, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="334.2" cy="347.5" r="4.5"><title>instruments, x86-64, G​CC 16.2: 1.18× the time of simdjson</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="348">simdjson</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="368" text-anchor="end">google_maps_api_response</text>
|
||||
<circle class="nj-charts-json-dot" cx="266.3" cy="360.5" r="4.5"><title>google_maps_api_response, Apple M1 Max: 1.01× the time of simdjson</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="341.1" cy="367.5" r="4.5"><title>google_maps_api_response, x86-64, G​CC 16.2: 1.19× the time of simdjson</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="368">simdjson</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="388" text-anchor="end">marine_ik</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="380.5" r="4.5"><title>marine_ik, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="356.9" cy="387.5" r="4.5"><title>marine_ik, x86-64, G​CC 16.2: 1.23× the time of Boost.J​SON</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="388">Boost.J​SON</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="408" text-anchor="end">numbers</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="400.5" r="4.5"><title>numbers, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="393.4" cy="407.5" r="4.5"><title>numbers, x86-64, G​CC 16.2: 1.32× the time of Boost.J​SON</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="408">Boost.J​SON</text>
|
||||
<text class="nj-charts-rowlabel nj-charts-code" x="252" y="428" text-anchor="end">mesh.pretty</text>
|
||||
<circle class="nj-charts-json-dot" cx="262.0" cy="420.5" r="4.5"><title>mesh.pretty, Apple M1 Max: 1.00× the time of the fastest (it is the fastest)</title></circle>
|
||||
<circle class="nj-charts-ojson-dot" cx="461.4" cy="427.5" r="4.5"><title>mesh.pretty, x86-64, G​CC 16.2: 1.49× the time of Boost.J​SON</title></circle>
|
||||
<text class="nj-charts-tick nj-charts-tick--l nj-charts-best" x="500" y="428">Boost.J​SON</text>
|
||||
<line class="nj-charts-ref" x1="262" y1="50" x2="262" y2="438"/>
|
||||
<text class="nj-charts-tick" x="262" y="44">fastest</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,72 @@
|
||||
<svg class="nj-fig nj-charts nj-charts--swar" viewBox="0 0 640 294" role="img" aria-labelledby="nj-blog-overlap nj-blog-overlap-d" xmlns="http://www.w3.org/2000/svg">
|
||||
<title id="nj-blog-overlap">Writing an 18-byte string with two overlapping 16-byte loads and stores</title>
|
||||
<desc id="nj-blog-overlap-d">The 18 bytes of profile_link_color. Load a covers bytes 0 to 15, load b covers bytes 2 to 17, so bytes 2 to 15 are in both. Neither contains a byte that needs escaping, so a is stored at the destination and b 2 bytes later; the second store writes bytes 2 to 15 again with the same values. This works for any length from 16 to 32 bytes without a loop.</desc>
|
||||
<text class="fg-h" x="40" y="20">a string of n = 18 bytes: too long for one 16-byte vector, too short for a loop</text>
|
||||
<rect class="fg-cell" x="40" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="53.5" y="58" text-anchor="middle">p</text>
|
||||
<rect class="fg-cell" x="71" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="84.5" y="58" text-anchor="middle">r</text>
|
||||
<rect class="fg-cell" x="102" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="102" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="115.5" y="58" text-anchor="middle">o</text>
|
||||
<rect class="fg-cell" x="133" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="133" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="146.5" y="58" text-anchor="middle">f</text>
|
||||
<rect class="fg-cell" x="164" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="164" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="177.5" y="58" text-anchor="middle">i</text>
|
||||
<rect class="fg-cell" x="195" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="195" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="208.5" y="58" text-anchor="middle">l</text>
|
||||
<rect class="fg-cell" x="226" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="226" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="239.5" y="58" text-anchor="middle">e</text>
|
||||
<rect class="fg-cell" x="257" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="257" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="270.5" y="58" text-anchor="middle">_</text>
|
||||
<rect class="fg-cell" x="288" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="288" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="301.5" y="58" text-anchor="middle">l</text>
|
||||
<rect class="fg-cell" x="319" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="319" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="332.5" y="58" text-anchor="middle">i</text>
|
||||
<rect class="fg-cell" x="350" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="350" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="363.5" y="58" text-anchor="middle">n</text>
|
||||
<rect class="fg-cell" x="381" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="381" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="394.5" y="58" text-anchor="middle">k</text>
|
||||
<rect class="fg-cell" x="412" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="412" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="425.5" y="58" text-anchor="middle">_</text>
|
||||
<rect class="fg-cell" x="443" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="443" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="456.5" y="58" text-anchor="middle">c</text>
|
||||
<rect class="fg-cell" x="474" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="474" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="487.5" y="58" text-anchor="middle">o</text>
|
||||
<rect class="fg-cell" x="505" y="34" width="27" height="36" rx="4"/>
|
||||
<rect class="nj-charts-c3" fill-opacity=".3" x="505" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="518.5" y="58" text-anchor="middle">l</text>
|
||||
<rect class="fg-cell" x="536" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="549.5" y="58" text-anchor="middle">o</text>
|
||||
<rect class="fg-cell" x="567" y="34" width="27" height="36" rx="4"/>
|
||||
<text class="fg-code" x="580.5" y="58" text-anchor="middle">r</text>
|
||||
<text class="nj-charts-tick" x="53.5" y="86">0</text>
|
||||
<text class="nj-charts-tick" x="115.5" y="86">2</text>
|
||||
<text class="nj-charts-tick" x="518.5" y="86">15</text>
|
||||
<text class="nj-charts-tick" x="580.5" y="86">17</text>
|
||||
<rect class="nj-charts-c1" fill-opacity=".22" x="40" y="100" width="492" height="22" rx="4"/>
|
||||
<rect class="nj-charts-c1" x="40" y="100" width="4" height="22" rx="2"/>
|
||||
<rect class="nj-charts-c1" x="528" y="100" width="4" height="22" rx="2"/>
|
||||
<text class="fg-code" x="286" y="116" text-anchor="middle" style="font-size:14px">a = load 16 bytes at p</text>
|
||||
<rect class="nj-charts-c2" fill-opacity=".22" x="102" y="130" width="492" height="22" rx="4"/>
|
||||
<rect class="nj-charts-c2" x="102" y="130" width="4" height="22" rx="2"/>
|
||||
<rect class="nj-charts-c2" x="590" y="130" width="4" height="22" rx="2"/>
|
||||
<text class="fg-code" x="348" y="146" text-anchor="middle" style="font-size:14px">b = load 16 bytes at p + n − 16</text>
|
||||
<text class="fg-note fg-note--l" x="40" y="182">Both loads lie inside the string, and together they cover all of it; bytes 2 to 15 are in both.</text>
|
||||
<text class="fg-note fg-note--l" x="40" y="204">Test a and b for a quote, a backslash, a control character or 0x7F: none, so write</text>
|
||||
<text class="fg-code" x="40" y="234">store a at d, store b at d + n − 16</text>
|
||||
<text class="fg-note fg-note--l" x="40" y="262">The second store writes bytes 2 to 15 again, with the same values. For any n from 16 to 32:</text>
|
||||
<text class="fg-note fg-note--l" x="40" y="280">two loads, one test, two stores, no loop and no branch on the length.</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.0 KiB |
Reference in new issue
Block a user