@@ -21,6 +21,9 @@ CppCon 2025
2121
2222---
2323
24+ ![ bg right 95%] ( images/alice.png )
25+
26+
2427# JSON
2528
2629* Portable, simple
@@ -33,16 +36,6 @@ CppCon 2025
3336 * arrays (list)
3437
3538
36- ---
37-
38- ``` json
39- {
40- "username" : " Alice" ,
41- "level" : 42 ,
42- "health" : 99.5 ,
43- "inventory" : [" sword" , " shield" , " potion" ]
44- }
45- ```
4639
4740---
4841
@@ -60,8 +53,15 @@ Parsed 0.63 GB in 6.961 seconds (90.72 MB/s)
6053
6154---
6255
56+ <style scoped >
57+ img [alt ~= " center" ] {
58+ display : block ;
59+ margin : 0 auto ;
60+ }
61+ </style >
62+
63+ ![ w:700 center] ( images/gwen.jpeg )
6364
64- <img src =" images/gwen.jpeg " width =" 55% " />
6565
6666Source: Gwen (Chen) Shapira
6767
@@ -78,7 +78,7 @@ Source: Gwen (Chen) Shapira
7878* simdjson was the first library to break the gigabyte per second barrier
7979 * Parsing Gigabytes of JSON per Second, VLDB Journal 28 (6), 2019
8080 * On-Demand JSON: A Better Way to Parse Documents? SPE 54 (6), 2024
81- * JSON for Modern C++ (nlohmann/json) can be $100 \times$ slower!
81+ * JSON for Modern C++ (nlohmann/json) can be $10 \times$ slower!
8282
8383<img src =" images/simdjson.png " width =" 10% " />
8484
@@ -96,12 +96,23 @@ Source: Gwen (Chen) Shapira
9696
9797# Not All Processors are Equal
9898
99+ <style >
100+ .center-table {
101+ display : flex ;
102+ justify-content : center ;
103+ }
104+ </style >
105+
106+ <div class =" center-table " >
107+
99108| processor | year | arithmetic logic units | SIMD units |
100109| -----------------| ---------| ---------------------------| ----------------|
101110| Apple M* | 2019 | 6+ | $4 \times 128$ |
102111| Intel Lion Cove | 2024 | 6 | $4 \times 256$ |
103112| AMD Zen 5 | 2024 | 6 | $4 \times 512$ |
104113
114+ </div >
115+
105116---
106117
107118![ bg right] ( images/avx.jpeg )
@@ -123,15 +134,15 @@ Source: Gwen (Chen) Shapira
123134
124135
125136* First scan identifies the structural characters, start of all strings at about 10 GB/s using SIMD instructions.
126- * Validates Unicode (UTF-8) at 30 GB/s.
137+ * Validates Unicode at 30 GB/s.
127138* Rest of parsing relies on the generated index.
128139* Allows fast skipping. (Only parse what we need)
129140* Can minify JSON at 10 to 20 GB/s
130141
131142---
132143
133144
134- <img src =" images/simdjson_benchmark.png " width =" 80 %" />
145+ <img src =" images/simdjson_benchmark.png " width =" 85 %" />
135146
136147https://openbenchmarking.org/test/pts/simdjson
137148
@@ -140,7 +151,7 @@ https://openbenchmarking.org/test/pts/simdjson
140151
141152# Usage
142153
143- You are probably using simdjson:
154+ ** You are probably using simdjson:**
144155
145156- Node.js, Electron,...
146157- ClickHouse
@@ -277,7 +288,10 @@ section {
277288# C#
278289
279290```C#
291+
280292string jsonString = JsonSerializer.Serialize(player, options);
293+
294+
281295Player deserializedPlayer = JsonSerializer.Deserialize<Player>(jsonInput, options);
282296```
283297
@@ -507,6 +521,20 @@ void serialize(string_builder& b, const std::set<T>& v) { /* ... */ }
507521
508522Concepts let us say: **"If it walks like a duck and quacks like a duck..."**
509523
524+ ```cpp
525+ template <typename T>
526+ concept container_but_not_string =
527+ requires(T a) {
528+ { a.size() } -> std::convertible_to<std::size_t>;
529+ {
530+ a[std::declval<std::size_t>()]
531+ }; // check if elements are accessible for the subscript operator
532+ };
533+ ```
534+
535+ ---
536+
537+
510538``` cpp
511539template <typename T>
512540concept container_but_not_string =
@@ -522,19 +550,50 @@ concept container_but_not_string =
522550---
523551
524552```cpp
525- template <typename T>
526- requires (has_size_and_subscript<T >) // "If it has .size() and operator[ ] "
527- void serialize(string_builder& b, const T& container) {
528- b.append('[ ');
529- for (size_t i = 0; i < container.size(); ++i) {
530- serialize(b, container[ i] );
531- }
532- b.append('] ');
553+ template <class T>
554+ requires(container_but_not_string<T>)
555+ constexpr void atom(string_builder &b, const T &t) {
556+ if (t.size() == 0) {
557+ b.append_raw("[]");
558+ return;
559+ }
560+ b.append('[');
561+ atom(b, t[0]);
562+ for (size_t i = 1; i < t.size(); ++i) {
563+ b.append(',');
564+ atom(b, t[i]);
565+ }
566+ b.append(']');
533567}
534568```
535569
536570✅ Works with ` vector ` , ` array ` , ` deque ` , custom containers...
537571
572+
573+ ---
574+
575+ ``` cpp
576+ template <typename T>
577+ concept appendable_containers =
578+ (details::supports_emplace_back<T> || details::supports_emplace<T> ||
579+ details::supports_push_back<T> || details::supports_push<T> ||
580+ details::supports_add<T> || details::supports_append<T> ||
581+ details::supports_insert<T>);
582+ ```
583+
584+ ---
585+
586+ ``` cpp
587+ template <appendable_containers T, typename ... Args>
588+ constexpr decltype (auto) emplace_one(T &vec, Args &&...args) {
589+ if constexpr (details::supports_emplace_back<T >) {
590+ return vec.emplace_back(std::forward<Args >(args)...);
591+ } else if constexpr (details::supports_emplace<T >) {
592+ return vec.emplace(std::forward<Args >(args)...);
593+ } else if // ...
594+ }
595+ ```
596+
538597---
539598
540599# Concepts + Reflection = Automatic Support
@@ -566,8 +625,9 @@ The magic:
566625
567626<img src =" images/perf_with_simdjson.png " width =" 80% " />
568627
569- ** 3.4 GB/s ** - 14x faster than nlohmann, 2.5x faster than Serde!
628+ ---
570629
630+ ** 3.4 GB/s** - 14x faster than nlohmann, 2.5x faster than Serde!
571631
572632---
573633
0 commit comments