Skip to content

Commit 3cd98df

Browse files
authored
This adds new tests regarding ordering. (simdjson#1233)
* This adds new tests regarding ordering. * Updating the documentation with more examples. * Adding compilation tests. * Pruning code for exceptions. * Guarding exceptionless.
1 parent 001be23 commit 3cd98df

File tree

2 files changed

+112
-3
lines changed

2 files changed

+112
-3
lines changed

doc/ondemand.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ in production systems:
466466
if it was `nullptr` but did not care what the actual value was--it will iterate. The destructor automates
467467
the iteration.
468468

469-
### Applicability and Limitations of the On Demand Approach
469+
### Limitations of the On Demand Approach
470470

471471
We expect that the On Demand approach has many of the performance benefits of the schema-based approach, while providing a flexibility that is similar to that of the DOM-based approach. However, there are some limitations.
472472

@@ -480,12 +480,23 @@ Cons of the On Demand approach:
480480

481481
There are currently additional technical limitations which we expect to resolve in future releases of the simdjson library:
482482

483-
* We intend to help users who wish to use the On Demand API but require support for order-insensitive semantics, but in our current implementation support for out-of-order keys (if needed) must be provided by the programmer.
484483
* The simdjson library offers runtime dispatching which allows you to compile one binary and have it run at full speed on different processors, taking advantage of the specific features of the processor. The On Demand API does not have runtime dispatch support at this time. To benefit from the On Demand API, you must compile your code for a specific processor. E.g., if your processor supports AVX2 instructions, you should compile your binary executable with AVX2 instruction support (by using your compiler's commands). If you are sufficiently technically proficient, you can implement runtime dispatching within your application, by compiling your On Demand code for different processors.
485484
* There is an initial phase which scans the entire document quickly, irrespective of the size of the document. We plan to break this phase into distinct steps for large files in a future release as we have done with other components of our API (e.g., `parse_many`).
486485
* The On Demand API does not support JSON Pointer. This capability is currently limited to our core API.
486+
* We intend to help users who wish to use the On Demand API but require support for order-insensitive semantics, but in our current implementation support for out-of-order keys (if needed) must be provided by the programmer. Currently, one might proceed in the following manner as a fallback measure if keys can appear in any order:
487+
```C++
488+
for (ondemand::object my_object : doc["mykey"]) {
489+
for (auto field : my_object) {
490+
if (field.key() == "key_value1") { process1(field.value()); }
491+
else if (field.key() == "key_value2") { process2(field.value()); }
492+
else if (field.key() == "key_value3") { process3(field.value()); }
493+
}
494+
}
495+
```
496+
497+
### Applicability of the On Demand Approach
487498
488-
Hence, at this time we recommend the On Demand API in the following cases:
499+
At this time we recommend the On Demand API in the following cases:
489500
490501
1. The 64-bit hardware (CPU) used to run the software is known at compile time. If you need runtime dispatching because you cannot be certain of the hardware used to run your software, you will be better served with the core simdjson API. (This only applies to x64 (AMD/Intel). On 64-bit ARM hardware, runtime dispatching is unnecessary.)
491502
2. The used parts of JSON files do not need to be validated and the layout of the nodes is in a known order. If you are receiving JSON from other systems, you might be better served with core simdjson API as it fully validates the JSON inputs and allows you to navigate through the document at will.

tests/ondemand/ondemand_basictests.cpp

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,28 @@
2121
using namespace simdjson;
2222
using namespace simdjson::builtin;
2323

24+
#if SIMDJSON_EXCEPTIONS
25+
26+
// bogus functions for compilation tests
27+
void process1(int ) {}
28+
void process2(int ) {}
29+
void process3(int ) {}
30+
31+
// Do not run this, it is only meant to compile
32+
void compilation_test_1() {
33+
const padded_string bogus = ""_padded;
34+
ondemand::parser parser;
35+
auto doc = parser.iterate(bogus);
36+
for (ondemand::object my_object : doc["mykey"]) {
37+
for (auto field : my_object) {
38+
if (field.key() == "key_value1") { process1(field.value()); }
39+
else if (field.key() == "key_value2") { process2(field.value()); }
40+
else if (field.key() == "key_value3") { process3(field.value()); }
41+
}
42+
}
43+
}
44+
#endif
45+
2446
#define ONDEMAND_SUBTEST(NAME, JSON, TEST) \
2547
{ \
2648
std::cout << "- Subtest " << (NAME) << " - JSON: " << (JSON) << " ..." << std::endl; \
@@ -637,6 +659,81 @@ namespace dom_api_tests {
637659
}
638660
}
639661

662+
663+
namespace ordering_tests {
664+
using namespace std;
665+
using namespace simdjson;
666+
using namespace simdjson::dom;
667+
#if SIMDJSON_EXCEPTIONS
668+
669+
auto json = "{\"coordinates\":[{\"x\":1.1,\"y\":2.2,\"z\":3.3}]}"_padded;
670+
671+
bool in_order() {
672+
TEST_START();
673+
ondemand::parser parser{};
674+
auto doc = parser.iterate(json);
675+
double x{0};
676+
double y{0};
677+
double z{0};
678+
for (ondemand::object point_object : doc["coordinates"]) {
679+
x += double(point_object["x"]);
680+
y += double(point_object["y"]);
681+
z += double(point_object["z"]);
682+
}
683+
return (x == 1.1) && (y == 2.2) && (z == 3.3);
684+
}
685+
686+
bool out_of_order() {
687+
TEST_START();
688+
ondemand::parser parser{};
689+
auto doc = parser.iterate(json);
690+
double x{0};
691+
double y{0};
692+
double z{0};
693+
for (ondemand::object point_object : doc["coordinates"]) {
694+
z += double(point_object["z"]);
695+
try {
696+
x += double(point_object["x"]);
697+
return false;
698+
} catch(simdjson_error&) {}
699+
try {
700+
y += double(point_object["y"]);
701+
return false;
702+
} catch(simdjson_error&) {}
703+
}
704+
return (x == 0) && (y == 0) && (z == 3.3);
705+
}
706+
707+
bool robust_order() {
708+
TEST_START();
709+
ondemand::parser parser{};
710+
auto doc = parser.iterate(json);
711+
double x{0};
712+
double y{0};
713+
double z{0};
714+
for (ondemand::object point_object : doc["coordinates"]) {
715+
for (auto field : point_object) {
716+
if (field.key() == "z") { z += double(field.value()); }
717+
else if (field.key() == "x") { x += double(field.value()); }
718+
else if (field.key() == "y") { y += double(field.value()); }
719+
}
720+
}
721+
return (x == 1.1) && (y == 2.2) && (z == 3.3);
722+
}
723+
#endif
724+
725+
bool run() {
726+
return
727+
#if SIMDJSON_EXCEPTIONS
728+
in_order() &&
729+
out_of_order() &&
730+
robust_order() &&
731+
#endif
732+
true;
733+
}
734+
735+
}
736+
640737
namespace twitter_tests {
641738
using namespace std;
642739
using namespace simdjson;
@@ -1251,6 +1348,7 @@ int main(int argc, char *argv[]) {
12511348
// twitter_tests::run() &&
12521349
// number_tests::run() &&
12531350
error_tests::run() &&
1351+
ordering_tests::run() &&
12541352
true
12551353
) {
12561354
std::cout << "Basic tests are ok." << std::endl;

0 commit comments

Comments
 (0)