Compare commits

...

141 Commits

Author SHA1 Message Date
Daniel Lemire 241ce7304c New version. 2022-07-19 16:47:06 -04:00
Daniel Lemire 5dbe96da96 We change slightly on development checks are enabled. (#1869)
* We change slightly on development checks are enabled.

* Removing garbagy code.
2022-07-19 16:40:02 -04:00
Daniel Lemire 40b397a3d4 Fixing issue 1870 (#1871) 2022-07-19 15:17:12 -04:00
strager 5510089d45 Improve build times for debug builds (#1859)
* Rename simdjson_really_inline -> simdjson_inline

I want to change the simdjson_really_inline macro to sometimes not force
inlining. After that upcoming change, the name simdjson_really_inline
will no longer makes sense.

Rename simdjson_really_inline to simdjson_inline. This patch should not
change semantics; simdjson_inline still forces inlining as before.

Some functions still need to be really inlined for ABI reasons.
(GCC's -Wpsabi complains otherwise.) Leave those functions marked as
simdjson_really_inline.

* Improve build times for debug builds

simdjson_inline is used for most simdjson functions. It forces inlining.
In unoptimized/debug builds, this can lead to a lot of machine code
being generated (especially with Address Sanitizer), causing slow
compilation.

Change simdjson_inline to force inlining only for optimized builds.

Sometimes, the programmer might want a slightly-optimized build and want
fast compilation (e.g. GCC's -Og mode). Allow simdjson users to define
the simdjson_inline macro themselves (e.g. on the command line:
-Dsimdjson_inline=inline) in cases where the default behavior is
undesired.

This patch reduced build times by over 75% for ondemand_object_tests.cpp
with GCC 9.4.0 and CMAKE_BUILD_TYPE=Debug on my AMD 5950X:

Before: 6.885 6.683 6.971 6.957 6.949 seconds (5 samples)
After:  1.492 1.551 1.494 1.490 1.531 seconds (5 samples)
2022-07-19 15:14:33 -04:00
Daniel Lemire 62a57907a7 Adding DOM benchmark to msgpack (#1866)
* We need simdjson dom for the json2msgpack benchmark

* Minor tweaking.
2022-07-14 13:47:10 -04:00
Daniel Lemire becbe99e81 Update README.md 2022-07-14 09:45:04 -04:00
Daniel Lemire bd3d67e889 Documenting a specific use case where you need a value if and only if it is another key is not present (#1865)
* Documenting a specific use case.

* Adding more comments and documentation.
2022-07-09 10:54:28 -04:00
Dirk Stolle a89d57d0d4 update dependency nlohmann/json for benchmarks to current version 3.10.5 (#1862) 2022-07-08 12:32:05 -04:00
Dirk Stolle e04d400c64 update jsoncpp to version 1.9.5 (#1863) 2022-07-08 12:31:43 -04:00
Daniel Lemire 1075e8609c Updating single header, prior to release. 2022-07-04 21:55:09 -04:00
Daniel Lemire 3fde8a4eac New release candidate (#1856)
* Patch for possible AVX-512 overflow.

* Updating the test for new padding.

* Preparing new version.

* replace binary integer literals with hex literals for C++11 compatibility (#1855)

Binary integer literals are a C++14 feature, so those are not supported
in C++11 and should be replaced by hexadecimal literals instead.

Fixes #1854.

Co-authored-by: Dirk Stolle <striezel-dev@web.de>
2022-07-04 21:54:19 -04:00
Daniel Lemire 62bdb9a2f7 [noci] update users 2022-07-02 21:44:48 -04:00
Daniel Lemire 2fbacb0058 New version 2022-06-30 11:49:26 -04:00
Daniel Lemire 509066f06a adding msgpack benchmarks (#1853) 2022-06-30 10:29:50 -04:00
Daniel Lemire 070f0b26a3 Removing dead code. (#1852) 2022-06-25 00:11:31 -04:00
Daniel Lemire 1a195623a5 Improve string performance in ondemand by making the string processing runtime dispatched. (#1849)
* This should improve string performance in ondemand by making the string processing runtime dispatched.
2022-06-24 09:57:16 -04:00
Dirk Stolle 5f7a56e7f1 add SIMDJSON_IMPLEMENTATION_ICELAKE to implementation-selection.md (#1848) 2022-06-22 13:09:19 -04:00
Daniel Lemire 5e60f0482d Update implementation-selection.md 2022-06-21 21:29:12 -04:00
Daniel Lemire e6c90b8efb Preparing release. 2022-06-15 15:23:03 -04:00
Daniel Lemire 7c450fbb70 Adding clang 13 tests. (#1844) 2022-06-15 15:21:33 -04:00
Daniel Lemire 4e1e002cb0 This verifies and fixes issue 1834. (#1843) 2022-06-15 13:42:04 -04:00
Benson Muite de196dd7a3 [skip ci] Grammar and typo fixes (#1842) 2022-06-14 16:16:39 -04:00
Daniel Lemire 08cb8dd81c Simpler counters. (#1841) 2022-06-07 15:19:51 -04:00
Dirk Stolle 57d54792ba update actions/cache + actions/checkout in GitHub Actions to v3 (#1839) 2022-06-06 08:51:50 -04:00
Dirk Stolle 79879802f9 run tests with GCC 8, too (#1837) 2022-06-03 20:52:07 -04:00
Daniel Lemire fbe955e9a4 gcc12 without warnings. (#1836) 2022-06-02 22:53:39 -04:00
Daniel Lemire a49ac04046 Version 2.0.3 2022-06-02 13:57:46 -04:00
Daniel Lemire 49c7654a70 We will be enabling AVX-512 under Visual Studio 2019 by default. (#1833) 2022-06-02 13:56:20 -04:00
Daniel Lemire 3e777c1759 This is a release candidate for issue 1831. (#1832)
Patch for GCC 8.
2022-06-02 09:19:30 -04:00
Daniel Lemire a410c723c8 Patch release. 2022-05-26 16:25:57 -04:00
Daniel Lemire f91a1ae07e Let us time minify and make sure AVX-512 is used by default. (#1830)
* Let us time minify
* Making AVX-512 available by default.
* Silencing some maybe-uninitialized warning under GCC (warning appears in the standard library).
* Making the Python amalgamation script a bit more Windows friendly.
* We do not try to silence -Wmaybe-uninitialized under clang.
2022-05-26 16:15:49 -04:00
Daniel Lemire c3954b1fb8 Update README.md 2022-05-25 17:25:01 -04:00
Daniel Lemire ce74ece545 Preparing release. 2022-05-25 11:43:06 -04:00
Daniel Lemire dd4dce848e Update CONTRIBUTORS 2022-05-25 11:24:40 -04:00
Daniel Lemire e8f370b085 Basic AVX-512 implementation (icelake or better) (#1813)
* Add cascadelake implementation, which use AVX512 Intrinsics to optimize performance(#1811)

Co-authored-by: mellonyou <fangzheng.zhang@intel.com>
Co-authored-by: wanweiqiangintel <weiqiang.wan@intel.com>
2022-05-25 11:14:02 -04:00
Daniel Lemire 645033a8c8 This runs the streaming amazon benchmarks in two modes: threaded and (#1828)
unthreaded. In the large case, we find that the threaded scenario with
ondemand has a 40% speed benefit over the unthreaded scenario.
2022-05-24 17:06:54 -04:00
Daniel Lemire 3b5ceeb80d Making the python script more robust. (#1827) 2022-05-20 13:32:15 -04:00
Dirk Stolle 82433a67f9 fix a few typos (#1829) 2022-05-20 13:31:30 -04:00
Daniel Lemire 8c1bfe782b Adds 'current_depth()'. (#1824) 2022-05-17 18:06:42 -04:00
Daniel Lemire 730939f01c Better documentation regarding the direct get_number_type() method. (#1821) 2022-05-13 15:31:09 -04:00
Daniel Lemire b169dc2ea7 Fixing get_number_type() (#1819) 2022-05-12 12:15:38 -04:00
Andrea Pappacoda 1aa1d537fe docs(basics): ondemand::element -> ::document (#1810)
simdjson::ondemand::element doesn't exist
2022-05-05 14:55:22 -04:00
Richard Ebeling c122462278 [skip ci] Fix accidental pastes in doc/basics.md (#1809)
Co-authored-by: Richard Ebeling <He3lixxx@users.noreply.github.com>
2022-05-02 08:13:55 -04:00
Daniel Lemire b6b338bea9 This simplifies the build somewhat by always including developer-options.cmake (#1806) 2022-04-27 12:51:04 -04:00
Dirk Stolle f72636b5b0 fix a typo in documentation (#1807) 2022-04-26 18:01:12 -04:00
Daniel Lemire f6a2bac11b what happens if we remove this check for CI? (#1804) 2022-04-23 14:09:22 -04:00
Daniel Lemire e4ddc5446b Fixing typo. 2022-04-10 08:16:46 -04:00
PavelP e0e0aa9e7b Update simdjson.h to include simdjson_version.h (#1794)
After this change amalgamated simdjson.h has version info at the beginning of the file.
2022-03-19 08:00:24 -04:00
Daniel Lemire 9f0a2e0e86 Update to vs17 (required) (#1795)
* Update to vs17 (required)

* Moving to windows-latest.

* Dropping old vs
2022-03-19 08:00:06 -04:00
Andrei Gritsiuk 203c03e90b resolves #1784 - GCC 11.1.0 and CLang 12.0.0 complain on 'and' operator in padded_string-inl.h (#1785)
Co-authored-by: Andrei <C:\Users\Andrei\AppData\Roaming\The Bat!>
2022-01-31 11:38:54 -05:00
Ivan Volnov 6698eb96b9 Fix C++20 build warnings (#1782) (#1787)
* Fix C++20 build warnings (#1782)

* Build fix for ppc64 (#1782)
2022-01-20 14:16:27 -05:00
pkubaj 30f7de387c Fix build on FreeBSD/powerpc64* (#1786)
FreeBSD uses sys/endian.h and bswap64().
2022-01-18 11:21:47 -05:00
Piotr Doan e0788507fe Missing value::get() template specialization for number (#1779) 2022-01-11 12:07:20 -05:00
Daniel Lemire e4740c87fb Update README.md 2022-01-11 12:05:16 -05:00
Daniel Lemire 5beef701e7 Update CONTRIBUTORS 2022-01-03 15:55:47 -05:00
Daniel Lemire c6f9c93c33 Use static variables to enforce initialization order. (#1773) (#1777)
Fixes https://github.com/simdjson/simdjson/issues/1771

Co-authored-by: Hao Chen <chenhao.yalier@gmail.com>
2022-01-03 15:54:57 -05:00
Daniel Lemire 3a93e45dd1 Removing scoop support. 2021-12-30 12:10:11 -05:00
Daniel Lemire 6db8ceb46c Verify and fix 1768. (#1769)
* Verify and fix 1768.

* Breaking down the namespaces for C++11 compilers.
2021-12-21 15:12:38 -05:00
Daniel Lemire 23651f0d41 Updating a macro. 2021-12-21 09:54:02 -05:00
N. Kolotov 7e1893db42 Added SIMDJSON_ prefix to STRINGIFY and to NO_SANITIZE_UNDEFINED macros. (#1766) 2021-12-21 09:53:06 -05:00
Daniel Lemire b4b1927b0f Making the documentation more explicit. (#1765) 2021-12-21 09:51:20 -05:00
Daniel Lemire e275589832 Update implementation-selection.md 2021-12-07 13:15:05 -05:00
epoll-reactor 69ee84973a Fix some typos in source files. (#1761)
Co-authored-by: epoll-reactor <>
2021-12-06 16:56:15 -05:00
epoll-reactor 76bed68ec3 Fix broken link in basics documentation. (#1760) 2021-12-04 12:21:08 -05:00
epoll-reactor 003d970cd2 Fix -Wredundant-decls warning in json_type.h. (#1759)
Co-authored-by: threadpoolexecutor <davidkor77@gmail.com>
2021-12-02 13:49:48 -05:00
DavidKorczynski 4aaf3f030c Add CIFuzz integration (#1757)
Signed-off-by: David Korczynski <david@adalogics.com>
2021-11-30 10:14:26 -05:00
Daniel Lemire 2763f7e719 Fixing issue 1755 (#1756) 2021-11-24 09:28:28 -05:00
strager 39035c39be Fix typos in comments (#1754) 2021-11-19 09:44:10 -05:00
strager ac179ff40f Fix broken links in documentation (#1753) 2021-11-12 08:47:22 -05:00
Tyler Kennedy b41bece32c Fix a couple of broken links in the basics.md TOC (#1752) 2021-11-07 19:58:32 -05:00
Daniel Lemire 9cb0c5f92d Patching. (#1750) 2021-11-05 19:46:57 -04:00
Daniel Lemire 1dec7b04fe Remark. 2021-11-05 13:32:45 -04:00
strager c6eb6f98b8 Fix typos in documentation (#1747)
The variable is called LOG_ENABLED, not ENABLE_LOGGING. Fix the
documentation in json_iterator.h.
2021-11-03 10:13:13 -04:00
Daniel Lemire 1b01969bda Adding tests for issue 1745. (#1746)
* Adding tests for issue 1745.

* Tweaking the documentation so that it is clearer.
2021-11-03 10:12:18 -04:00
Daniel Lemire 17f3148ac7 Version 1.0.2. 2021-10-27 19:29:42 -04:00
Daniel Lemire 35b4a48e99 Fixing issue 1742 (#1743)
* Fix for issue 1742.

* Some additional tests.
2021-10-27 19:25:23 -04:00
mir4cle c0d18452fc Add an option to get current location from value (#1738)
Co-authored-by: Igor Logvanev <igor.logvanev@aimtech.team>
2021-10-24 16:55:49 -04:00
Daniel Lemire e5c9a310cf Preparing release 1.0.1. 2021-10-20 12:18:04 -04:00
Daniel Lemire 6d308a08c5 Fixing issue 1736 (#1737)
* Fixing issue 1736

* Updating google benchmark.

* Minor trimming.

* Using the variable (to silence a warning).

* Adding assignment operator.
2021-10-20 12:15:35 -04:00
Daniel Lemire 9e477ddb00 Let us try to improve the documentation so that it is clearer. (#1733)
* Let us try to improve the documentation so that it is clearer.

* Minor tweaks.
2021-10-19 13:09:41 -04:00
Daniel Lemire b7c4d1eeef Adding test for issue 1729. (#1730)
* Adding test for issue 1729.

* Adding comment.

* Trying to move to 11.7.

* Tweaking.

* More tweaking.

* Adding additional test.

* Missing "<<".

* Minor update.

* Removing legacy systems.
2021-10-13 09:30:37 -04:00
Daniel Lemire 4a2f10ebcf Let us trim out these legacy systems from CI. 2021-10-12 18:24:03 -04:00
Daniel Lemire 41cb909604 Minor change to handle paranoid compilers. (#1732) 2021-10-12 17:23:45 -04:00
Daniel Lemire 91908ade4d Additional documentation following issue 1723 (#1724)
* Some extra documentation regarding issue 1723.

* Adding comments.

* Minor fix.

* [no ci] more documentation
2021-10-09 11:41:20 -04:00
Daniel Lemire 9a32c48098 Cleaning up the single-header demo. (#1731)
* Cleaning up the single-header demo.

* Updating xcode
2021-10-09 11:34:21 -04:00
Daniel Lemire d996ffc494 Minor typo. (#1721)
* Minor typo.

* Minor fixes.

* Patching...
2021-09-25 11:34:44 -04:00
Daniel Lemire d56fdc3d04 [no ci] deleting an irrelevant comment. 2021-09-22 18:06:59 -04:00
Daniel Lemire 1dce4fed6e [no ci] moving documentation bit to the right location. (#1719) 2021-09-20 09:33:21 -04:00
Daniel Lemire cae5e5342f Additional ndjson tests. (#1717)
* Additional ndjson tests.

* Switching the data source.

* Fixing.
2021-09-18 16:29:10 -04:00
Madhur Chauhan 4e609aa955 fix redundant ; in document-inl.h (#1715) 2021-09-17 14:02:03 -04:00
Paul Dreik d28e5534d9 ignore unused variable (#1714) 2021-09-12 17:37:58 -04:00
Daniel Lemire 3bd8b0b575 Refreshing the single-header files. 2021-09-07 14:36:17 -04:00
Daniel Lemire af4ff7cc33 Adding fast "get_number_type()" function, bypassing "get_number()" (#1713)
* Adding fast "get_number_type" function, bypassing "get_number"

* Minor tweak.

* Adding missing get_number_type().
2021-09-07 14:34:40 -04:00
Nicolas Boyer c9179ad81d Add count_fields method for objects (#1712)
* Implement count_elements for object

* Add count_elements() for simdjson_result

* Add count_elements for documents(arrays,objects).

* Add tests for objects.

* Add tests for documents array. Typos.

* Renaming to count_fields() for objects.

* Update doc.

* Apply patch
2021-09-02 16:18:48 -04:00
Daniel Lemire d6b5124c88 Pushing the release 1.0.0 candidate. (#1709) 2021-09-01 15:25:45 -04:00
Dougall Johnson 64b62fd3b3 simd8x64::compress optimisation for Apple M1 (#1708)
* Optimized the arm64 implementation of simd8x64::compress

This is ~35% faster on the fast_minify benchmarks on Apple M1

* Return byte-count from simd8x64::compress

This avoids a redundant popcount on ARM, for ~3% faster minify
on Apple M1
2021-09-01 15:25:11 -04:00
Daniel Lemire cebe3fb299 Tweaking current_location(). (#1707)
* Tweaking current_location().

* Well.
2021-08-28 20:19:30 -04:00
Nicolas Boyer ed7343f7f2 Provide current location in JSON input (#1695)
* Setup.

* Add current_location().

* Make return simdjson_result and fix cast issues.

* Whitespace.

* Add broken JSON tests. Add null parser check.

* Remove unused variables.

* Alive fix.

* Fix merge issues.

* Simplification for out of bounds.

* More tests.

* Move pointer back for unrecoverable errors.

* Add new error OUT_OF_BOUNDS

* Remove unnecessary include and fix OUT_OF_BOUNDS.

* Add more tests. Fix unrecoverable errors.

* Fix tests.

* Modify one test.

* Update doc.

* Typos.

* Add read_me tests.

* Update doc.

* Add current_location for simdjson_result and document_reference

* Typos.

Co-authored-by: Daniel Lemire <lemire@gmail.com>
2021-08-27 13:41:59 -04:00
Daniel Lemire 35158257c6 Implementing get_number for the document instances. (#1706) 2021-08-27 10:26:01 -04:00
Daniel Lemire b935ce2e06 Allowing casts instead of get_double, get_uint64 and get_int64 (#1705) 2021-08-27 10:25:17 -04:00
Daniel Lemire 4afe7565b4 ondemand dynamically-typed numbers (#1704)
* Building up a number type.

* Implemented is_integer and is_negative.

* Implemented get_number in value_iterator.

* Final prototype.

* [no ci] typo
2021-08-26 12:16:44 -04:00
Daniel Lemire 6bed34ad61 This exposes 'reset' for object and array instances. (#1696)
* This exposes 'rewind' for object and array instances.

* Putting really_inline back to count_elements()

* Update array.h

* Adding empty array rewind.

* Adds "is_empty" method to arrays.

* More fragmentation.

* Tweaking implementation.

* Fixing issue with get_value() on document instances.

* Changing the name of the new rewind functions to reset.
2021-08-21 10:23:59 -04:00
Daniel Lemire 0ad52a7e22 Renaming scalar to is_scalar. (#1698) 2021-08-21 10:23:22 -04:00
Daniel Lemire aa52cf6868 Alive fix. (#1700) 2021-08-21 10:22:59 -04:00
Daniel Lemire cd11838e5f Update parse_many.md 2021-08-20 14:52:43 -04:00
Daniel Lemire c31157bafe Update iterate_many.md 2021-08-20 14:15:38 -04:00
Daniel Lemire 419b7b2ce8 Update parse_many.md 2021-08-20 14:09:54 -04:00
Daniel Lemire ca3f3cc49d Update iterate_many.md 2021-08-20 14:09:30 -04:00
Paul Dreik d3f0e2afb3 [no ci] remove references to bintray (#1702)
* download fuzz corpus from www.pauldreik.se

* remove reference to bintray
2021-08-19 08:39:07 -04:00
Daniel Lemire eac3832ec0 [no ci] removing space 2021-08-17 08:35:21 -04:00
Daniel Lemire db19c7675f [no ci] tweaking documentation 2021-08-15 10:32:11 -04:00
strager d036fdf919 Reduce #include bloat (<iostream>) (#1697)
Including <iostream> has two problems:

* Compile times are worse because of over-inclusion
* Binary sizes are worse when statically linking libstdc++ because
  iostreams cannot be dead-code-stripped

simdjson only needs std::ostream. Include the header declaring only what
we need (<ostream>), omitting stuff we don't need (std::cout and its
initialization, for example).

This commit should not change behavior, but it might break users who
assume that including <simdjson/simdjson.h> will make std::cout
available (such as many of simdjson's own files).
2021-08-13 11:24:36 -04:00
Daniel Lemire fc0934755a [no ci] Adding new "include <iostream>" lines in the documentation following the recent removal of iostream from our headers. 2021-08-13 11:23:16 -04:00
Daniel Lemire de4deb8c4e Makes it possible to cast a document to a value. (#1690)
* Makes it possible to cast a document to a value.
2021-08-11 20:02:30 -04:00
Daniel Lemire ba46616cbc Small test for document_reference usage. (#1694) 2021-08-10 21:08:59 -04:00
Daniel Lemire a552638373 removing trailing spaces 2021-08-10 15:12:05 -04:00
Daniel Lemire e30123d58f [no ci] 2021-08-10 15:02:51 -04:00
Daniel Lemire b7dee3e9c8 [no ci] remark 2021-08-09 13:04:20 -04:00
Daniel Lemire 717d0c24a6 [no ci] tuning documentation 2021-08-09 12:09:40 -04:00
Daniel Lemire 40813752f4 This will update the amalgamate_demo.cpp file to use On Demand. (#1689)
* This will update the amalgamate_demo.cpp file to use On Demand.

* Making the demo exceptionless.
2021-08-07 12:43:40 -04:00
Daniel Lemire 19902abaf8 Guarding first/second access. (#1688)
* Guarding first/second access.

* Correcting our own usage.

* Adding more documentation.
2021-08-06 20:25:05 -04:00
Daniel Lemire 06643fc9f5 Additional tests and document tuning (#1684)
* Additional example.

* Adds more tests.

* Actually using the variable.
2021-08-02 16:35:02 -04:00
Daniel Lemire 0fa68d8930 Fixing noexcept on operator << with simdjson_result. (#1678)
* Additional tests.

* Finishing touch.

* Extending to IO.
2021-07-31 17:54:27 -04:00
Daniel Lemire cc98358453 Adding error handing examples to the documentation (#1679)
* Adding error handing examples.

* Guarding the exception-throwing test.
2021-07-31 14:31:48 -04:00
Dirk Stolle 5f0b35b2c5 update string_view lite to version 1.6.0 (#1677)
This is the header as seen in the current master branch,
commit d27d7b5081406a35b41cb16b321be8833b4cd811, on
<https://github.com/martinmoene/string-view-lite>.
2021-07-31 11:19:51 -04:00
Daniel Lemire bd0f5e9322 [no ci] details 2021-07-30 18:20:37 -04:00
Daniel Lemire cb0e4b23c7 [no ci] clearing headings 2021-07-30 18:12:06 -04:00
Daniel Lemire d83e69d977 Fix an issue with truncated-byte function. (#1674) 2021-07-30 13:12:42 -04:00
Daniel Lemire f657516a7e Pruning some white spaces. 2021-07-27 13:16:18 -04:00
Daniel Lemire 8d29c5f931 [no ci] README update 2021-07-27 11:10:56 -04:00
Daniel Lemire eeac91579c [no ci] additional examples 2021-07-27 11:08:24 -04:00
Daniel Lemire e5a4b8b81b [no ci] minor indentation issue 2021-07-27 11:05:15 -04:00
Daniel Lemire 7b8f775893 Update basics.md 2021-07-27 11:04:01 -04:00
Daniel Lemire c6ef2105ab Minor tweak. 2021-07-27 10:56:05 -04:00
Daniel Lemire e681234e45 [no ci] update to power usage section 2021-07-27 10:30:19 -04:00
Daniel Lemire eb93b98d6a verify and fix issue 1668 (#1673)
* Adding test.

* Verifies and fix issue 1668. This commit updates the previous behavior of the
On Demand stream support by return a value type (document_reference) instead
of a reference to a document. This allows us to bridge with the usually simdjson
error system, with its simdjson_result types.

* Minor reformat.

* Adds a test with initial tests passing.

* Adding an example.
2021-07-27 08:51:07 -04:00
Nicolas Boyer 7d887fdc1e Parse numbers inside strings (#1667)
* Update basic.md to document JSON pointer for On Demand.

* Add automatic rewind for at_pointer

* Remove DOM examples in basics.md and update documentation reflecting addition of at_pointer automatic rewinding.

* Review

* Add test

* Naive implementation for doubles in string.

* Add double from string in atom doc.

* Simplification (removed all *_from_string())

* Add int and uint parsing in string.

* Make duplicates instead.

* Make tests exceptionless.

* Add missing declarations.

* Add more tests (errors, JSON pointer).

* Add crypto json tests.

* Update doc.

* Update doc after review.

Co-authored-by: Daniel Lemire <lemire@gmail.com>
2021-07-27 08:50:44 -04:00
Daniel Lemire 9d405a5df4 [skip ci] made requirements more precise 2021-07-26 08:47:21 -04:00
Daniel Lemire 18c003e8bf Adding CI for old LLVM in GitHub Actions (#1672)
* Adding CI for old LLVM

* Simplifying.
2021-07-26 08:37:29 -04:00
Daniel Lemire ec4316aa84 Adding macos testing. (#1670) 2021-07-25 12:25:31 -04:00
Daniel Lemire b79261eebc This cleans a bit the current code, especially with respect to EOF guards. (#1669)
* Upgrading the GitHub Actions.

* Upgrading appveyor

* Upgrading circle ci.

* Cleaning.
2021-07-25 10:36:22 -04:00
289 changed files with 28589 additions and 9453 deletions
+5 -5
View File
@@ -15,22 +15,22 @@ environment:
- job_name: VS2019 - job_name: VS2019
CMAKE_ARGS: -A %Platform% CMAKE_ARGS: -A %Platform%
- job_name: VS2019ARM - job_name: VS2019ARM
CMAKE_ARGS: -A ARM64 -DCMAKE_CROSSCOMPILING=1 -D SIMDJSON_GOOGLE_BENCHMARKS=OFF # Does Google Benchmark builds under VS ARM? CMAKE_ARGS: -A ARM64 -DSIMDJSON_DEVELOPER_MODE=ON -DCMAKE_CROSSCOMPILING=1 -D SIMDJSON_GOOGLE_BENCHMARKS=OFF # Does Google Benchmark builds under VS ARM?
- job_name: VS2017 (Static, No Threads) - job_name: VS2017 (Static, No Threads)
image: Visual Studio 2017 image: Visual Studio 2017
CMAKE_ARGS: -A %Platform% -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_ENABLE_THREADS=OFF CMAKE_ARGS: -A %Platform% -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_ENABLE_THREADS=OFF
CTEST_ARGS: -LE explicitonly CTEST_ARGS: -LE explicitonly
- job_name: VS2019 (Win32) - job_name: VS2019 (Win32)
platform: Win32 platform: Win32
CMAKE_ARGS: -A %Platform% -DBUILD_SHARED_LIBS=ON -DSIMDJSON_ENABLE_THREADS=ON # This should be the default. Testing anyway. CMAKE_ARGS: -A %Platform% -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=ON -DSIMDJSON_ENABLE_THREADS=ON # This should be the default. Testing anyway.
CTEST_ARGS: -LE explicitonly CTEST_ARGS: -LE explicitonly
- job_name: VS2019 (Win32, No Exceptions) - job_name: VS2019 (Win32, No Exceptions)
platform: Win32 platform: Win32
CMAKE_ARGS: -A %Platform% -DBUILD_SHARED_LIBS=ON -DSIMDJSON_ENABLE_THREADS=ON -DSIMDJSON_EXCEPTIONS=OFF CMAKE_ARGS: -A %Platform% -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=ON -DSIMDJSON_ENABLE_THREADS=ON -DSIMDJSON_EXCEPTIONS=OFF
CTEST_ARGS: -LE explicitonly CTEST_ARGS: -LE explicitonly
- job_name: VS2015 - job_name: VS2015
image: Visual Studio 2015 image: Visual Studio 2015
CMAKE_ARGS: -A %Platform% -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_ENABLE_THREADS=OFF CMAKE_ARGS: -A %Platform% -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_ENABLE_THREADS=OFF
CTEST_ARGS: -LE explicitonly CTEST_ARGS: -LE explicitonly
build_script: build_script:
+10 -18
View File
@@ -1,7 +1,7 @@
version: 2.1 version: 2.1
# We constantly run out of memory so please do not use parallelism (-j, -j4). # We constantly run out of memory so please do not use parallelism (-j, -j4).
# Reusable image / compiler definitions # Reusable image / compiler definitions
executors: executors:
@@ -48,7 +48,7 @@ executors:
CXX: clang++-9 CXX: clang++-9
CC: clang-9 CC: clang-9
CMAKE_BUILD_FLAGS: CMAKE_BUILD_FLAGS:
CTEST_FLAGS: --output-on-failure CTEST_FLAGS: --output-on-failure
clang6: clang6:
docker: docker:
@@ -88,13 +88,13 @@ commands:
steps: steps:
- cmake_prep - cmake_prep
- dependency_restore - dependency_restore
- run: cmake $CMAKE_FLAGS -DCMAKE_INSTALL_PREFIX:PATH=destination -B build . - run: cmake -DSIMDJSON_DEVELOPER_MODE=ON $CMAKE_FLAGS -DCMAKE_INSTALL_PREFIX:PATH=destination -B build .
- dependency_cache # dependencies are produced in the configure step - dependency_cache # dependencies are produced in the configure step
cmake_build: cmake_build:
steps: steps:
- cmake_build_cache - cmake_build_cache
- run: cmake --build build - run: cmake --build build
cmake_test: cmake_test:
steps: steps:
@@ -130,7 +130,7 @@ commands:
- cmake_build_cache - cmake_build_cache
- run: | - run: |
cmake -DSIMDJSON_ENABLE_DOM_CHECKPERF=ON --build build --target checkperf && cmake -DSIMDJSON_ENABLE_DOM_CHECKPERF=ON --build build --target checkperf &&
cd build && cd build &&
ctest --output-on-failure -R checkperf ctest --output-on-failure -R checkperf
# we not only want cmake to build and run tests, but we want also a successful installation from which we can build, link and run programs # we not only want cmake to build and run tests, but we want also a successful installation from which we can build, link and run programs
@@ -191,12 +191,12 @@ jobs:
sanitize-gcc10: sanitize-gcc10:
description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build
executor: gcc10 executor: gcc10
environment: { CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly } environment: { CMAKE_FLAGS: -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
steps: [ cmake_test ] steps: [ cmake_test ]
sanitize-clang10: sanitize-clang10:
description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build
executor: clang10 executor: clang10
environment: { CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly } environment: { CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_NO_FORCE_INLINING=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
steps: [ cmake_test ] steps: [ cmake_test ]
threadsanitize-gcc10: threadsanitize-gcc10:
description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build
@@ -206,15 +206,7 @@ jobs:
threadsanitize-clang10: threadsanitize-clang10:
description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build
executor: clang10 executor: clang10
environment: { CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE_THREADS=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly } environment: { CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_NO_FORCE_INLINING=ON -DSIMDJSON_SANITIZE_THREADS=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
steps: [ cmake_test ]
nocheckeof-clang10:
description: Validate that when __SIMDJSON_CHECK_EOF=0, everything still succeeds
environment:
CXXFLAGS: -D__SIMDJSON_CHECK_EOF=0
CMAKE_BUILD_FLAGS: --target ondemand_tests
CTEST_FLAGS: --output-on-failure -R ondemand_
executor: clang10
steps: [ cmake_test ] steps: [ cmake_test ]
# dynamic # dynamic
dynamic-gcc10: dynamic-gcc10:
@@ -270,12 +262,12 @@ jobs:
sanitize-haswell-gcc10: sanitize-haswell-gcc10:
description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build description: Build and run tests on GCC 10 and AVX 2 with a cmake sanitize build
executor: gcc10 executor: gcc10
environment: { CXXFLAGS: -march=haswell, CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly } environment: { CXXFLAGS: -march=haswell, CMAKE_FLAGS: -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
steps: [ cmake_test ] steps: [ cmake_test ]
sanitize-haswell-clang10: sanitize-haswell-clang10:
description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build description: Build and run tests on clang 10 and AVX 2 with a cmake sanitize build
executor: clang10 executor: clang10
environment: { CXXFLAGS: -march=haswell, CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly } environment: { CXXFLAGS: -march=haswell, CMAKE_FLAGS: -DBUILD_SHARED_LIBS=ON -DSIMDJSON_NO_FORCE_INLINING=ON -DSIMDJSON_SANITIZE=ON, CTEST_FLAGS: --output-on-failure -LE explicitonly }
steps: [ cmake_test ] steps: [ cmake_test ]
workflows: workflows:
+8 -46
View File
@@ -1,46 +1,4 @@
kind: pipeline kind: pipeline
name: i386-gcc # we do not support 32-bit systems, but we run tests
platform: { os: linux, arch: amd64 }
steps:
- name: Build and Test
image: i386/ubuntu
environment:
CC: gcc
CXX: g++
BUILD_FLAGS: -- -j
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
commands:
- scripts/addcmakeppa.sh "$(env -i sh -c '. /etc/os-release; echo $VERSION_CODENAME')"
- apt-get install -y g++ cmake gcc git
- mkdir build
- cd build
- cmake $CMAKE_FLAGS ..
- cmake --build . $BUILD_FLAGS
- ctest $CTEST_FLAGS
---
kind: pipeline
name: i386-clang # we do not support 32-bit systems, but we run tests
platform: { os: linux, arch: amd64 }
steps:
- name: Build and Test
image: i386/ubuntu
environment:
CC: clang-6.0
CXX: clang++-6.0
BUILD_FLAGS: -- -j
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
commands:
- scripts/addcmakeppa.sh "$(env -i sh -c '. /etc/os-release; echo $VERSION_CODENAME')"
- apt-get install -y clang++-6.0 cmake git
- mkdir build
- cd build
- cmake $CMAKE_FLAGS ..
- cmake --build . $BUILD_FLAGS
- ctest $CTEST_FLAGS
---
kind: pipeline
name: gcc9 name: gcc9
platform: { os: linux, arch: amd64 } platform: { os: linux, arch: amd64 }
steps: steps:
@@ -50,7 +8,7 @@ steps:
CC: gcc CC: gcc
CXX: g++ CXX: g++
BUILD_FLAGS: -- -j BUILD_FLAGS: -- -j
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=icelake;haswell;westmere;fallback
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
commands: commands:
- echo "deb http://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list - echo "deb http://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list
@@ -61,6 +19,7 @@ steps:
- cmake $CMAKE_FLAGS .. - cmake $CMAKE_FLAGS ..
- cmake --build . $BUILD_FLAGS - cmake --build . $BUILD_FLAGS
- ctest $CTEST_FLAGS -L acceptance -LE per_implementation - ctest $CTEST_FLAGS -L acceptance -LE per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=icelake ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=haswell ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=westmere ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=fallback ctest $CTEST_FLAGS -L per_implementation
@@ -77,7 +36,7 @@ steps:
CC: clang-6.0 CC: clang-6.0
CXX: clang++-6.0 CXX: clang++-6.0
BUILD_FLAGS: -- -j BUILD_FLAGS: -- -j
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=icelake;haswell;westmere;fallback
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
commands: commands:
- mkdir build - mkdir build
@@ -85,6 +44,7 @@ steps:
- cmake $CMAKE_FLAGS .. - cmake $CMAKE_FLAGS ..
- cmake --build . $BUILD_FLAGS - cmake --build . $BUILD_FLAGS
- ctest $CTEST_FLAGS -L acceptance -LE per_implementation - ctest $CTEST_FLAGS -L acceptance -LE per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=icelake ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=haswell ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=westmere ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=fallback ctest $CTEST_FLAGS -L per_implementation
@@ -142,7 +102,7 @@ steps:
CC: gcc CC: gcc
CXX: g++ CXX: g++
BUILD_FLAGS: -- -j BUILD_FLAGS: -- -j
CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback CMAKE_FLAGS: -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_IMPLEMENTATION=icelake;haswell;westmere;fallback
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
commands: commands:
- echo "deb http://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list - echo "deb http://deb.debian.org/debian buster-backports main" >> /etc/apt/sources.list
@@ -153,6 +113,7 @@ steps:
- cmake $CMAKE_FLAGS .. - cmake $CMAKE_FLAGS ..
- cmake --build . $BUILD_FLAGS - cmake --build . $BUILD_FLAGS
- ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L acceptance -LE per_implementation - ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L acceptance -LE per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=icelake ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=haswell ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=westmere ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=fallback ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
@@ -168,7 +129,7 @@ steps:
environment: environment:
CC: clang-9 CC: clang-9
CXX: clang++-9 CXX: clang++-9
CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_IMPLEMENTATION=haswell;westmere;fallback CMAKE_FLAGS: -DSIMDJSON_SANITIZE=ON -DSIMDJSON_IMPLEMENTATION=icelake;haswell;westmere;fallback
BUILD_FLAGS: -- -j BUILD_FLAGS: -- -j
CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly CTEST_FLAGS: -j4 --output-on-failure -LE explicitonly
commands: commands:
@@ -177,6 +138,7 @@ steps:
- cmake $CMAKE_FLAGS .. - cmake $CMAKE_FLAGS ..
- cmake --build . $BUILD_FLAGS - cmake --build . $BUILD_FLAGS
- ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L acceptance -LE per_implementation - ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L acceptance -LE per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=icelake ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=haswell ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=haswell ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=westmere ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=westmere ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
- SIMDJSON_FORCE_IMPLEMENTATION=fallback ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation - SIMDJSON_FORCE_IMPLEMENTATION=fallback ASAN_OPTIONS="detect_leaks=0" ctest $CTEST_FLAGS -L per_implementation
+3 -9
View File
@@ -1,12 +1,6 @@
name: Alpine Linux name: Alpine Linux
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
ubuntu-build: ubuntu-build:
@@ -15,8 +9,8 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
+24
View File
@@ -0,0 +1,24 @@
name: CIFuzz
on: [pull_request]
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'simdjson'
dry-run: false
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'simdjson'
fuzz-seconds: 600
dry-run: false
- name: Upload Crash
uses: actions/upload-artifact@v1
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts
@@ -1,15 +1,12 @@
name: Detect trailing whitespace name: Detect trailing whitespace
on: on: [push, pull_request]
pull_request:
branches:
- master
jobs: jobs:
whitespace: whitespace:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Remove whitespace and check the diff - name: Remove whitespace and check the diff
run: | run: |
set -eu set -eu
+3 -3
View File
@@ -37,14 +37,14 @@ jobs:
chmod +x llvm.sh chmod +x llvm.sh
sudo ./llvm.sh $CLANGVERSION sudo ./llvm.sh $CLANGVERSION
- uses: actions/checkout@v1 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- uses: actions/cache@v2 - uses: actions/cache@v3
id: cache-corpus id: cache-corpus
with: with:
path: out/ path: out/
+34
View File
@@ -0,0 +1,34 @@
name: Macos (Xcode 11)
on: [push, pull_request]
jobs:
macos-build:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Use cmake
run: |
xcversion select 11.7
mkdir builddebug &&
cd builddebug &&
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly &&
cd .. &&
mkdir build &&
cd build &&
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly &&
cmake --install . &&
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
cd ../tests/installation_tests/find &&
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
+33
View File
@@ -0,0 +1,33 @@
name: Macos
on: [push, pull_request]
jobs:
macos-build:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Use cmake
run: |
mkdir builddebug &&
cd builddebug &&
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly &&
cd .. &&
mkdir build &&
cd build &&
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly &&
cmake --install . &&
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
cd ../tests/installation_tests/find &&
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
-68
View File
@@ -1,68 +0,0 @@
name: MinGW32-CI
on:
push:
branches:
- master
pull_request:
branches:
- master
# Important: scoop will either install 32-bit GCC or 64-bit GCC, not both.
# It is important to build static libraries because cmake is not smart enough under Windows/mingw to take care of the path. So
# with a dynamic library, you could get failures due to the fact that the EXE can't find its DLL.
jobs:
ci:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
name: windows-gcc
runs-on: windows-2016
env:
CMAKE_GENERATOR: Ninja # This is critical, try ' cmake -GNinja-DBUILD_SHARED_LIBS=OFF .. ' if using the command line
CC: gcc
CXX: g++
steps: # To reproduce what is below, start a powershell with administrative rights, using scoop *is* a good idea
- uses: actions/checkout@v2
- uses: actions/cache@v2 # we cache the scoop setup with 32-bit GCC
id: cache
with:
path: |
C:\ProgramData\scoop
key: scoop32 # static key: should be good forever
- uses: actions/cache@v2
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Setup Windows # This should almost never run if the cache works.
if: steps.cache.outputs.cache-hit != 'true'
shell: powershell
run: |
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
scoop install sudo --global
sudo scoop install git --global
sudo scoop install ninja --global
sudo scoop install cmake --global
sudo scoop install gcc --arch 32bit --global
$env:path
Write-Host 'Everything has been installed, you are good!'
- name: Build and Test 32-bit x86
shell: powershell
run: |
$ENV:PATH="C:\ProgramData\scoop\shims;C:\ProgramData\scoop\apps\gcc\current\bin;C:\ProgramData\scoop\apps\ninja\current;$ENV:PATH"
g++ --version
cmake --version
ninja --version
git --version
mkdir build32
cd build32
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_ENABLE_THREADS=OFF ..
cmake --build . --target acceptance_tests --verbose
ctest -L acceptance --output-on-failure
-74
View File
@@ -1,74 +0,0 @@
name: MinGW64-CI
on:
push:
branches:
- master
pull_request:
branches:
- master
# Important: scoop will either install 32-bit GCC or 64-bit GCC, not both.
# It is important to build static libraries because cmake is not smart enough under Windows/mingw to take care of the path. So
# with a dynamic library, you could get failures due to the fact that the EXE can't find its DLL.
jobs:
ci:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
name: windows-gcc
runs-on: windows-2016
env:
CMAKE_GENERATOR: Ninja # This is critical, try ' cmake -GNinja-DBUILD_SHARED_LIBS=OFF .. ' if using the command line
CC: gcc
CXX: g++
steps: # To reproduce what is below, start a powershell with administrative rights, using scoop *is* a good idea
- uses: actions/checkout@v2
- uses: actions/cache@v2 # we cache the scoop setup with 64-bit GCC
id: cache
with:
path: |
C:\ProgramData\scoop
key: scoop64 # static key: should be good forever
- uses: actions/cache@v2
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Setup Windows # This should almost never run if the cache works.
if: steps.cache.outputs.cache-hit != 'true'
shell: powershell
run: |
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
scoop install sudo --global
sudo scoop install git --global
sudo scoop install ninja --global
sudo scoop install cmake --global
sudo scoop install gcc --arch 64bit --global
$env:path
Write-Host 'Everything has been installed, you are good!'
- name: Build and Test 64-bit x64
shell: powershell
run: |
$ENV:PATH="C:\ProgramData\scoop\shims;C:\ProgramData\scoop\apps\gcc\current\bin;C:\ProgramData\scoop\apps\ninja\current;$ENV:PATH"
g++ --version
cmake --version
ninja --version
git --version
mkdir build64
cd build64
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_ENABLE_THREADS=OFF ..
cmake --build . --target acceptance_tests --verbose
ctest -L acceptance --output-on-failure
cd ..
mkdir build64debug
cd build64debug
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_ENABLE_THREADS=OFF ..
cmake --build . --target acceptance_tests --verbose
ctest -L acceptance --output-on-failure
+5 -16
View File
@@ -1,12 +1,7 @@
name: MSYS2-CLANG-CI name: MSYS2-CLANG-CI
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
windows-mingw: windows-mingw:
@@ -22,21 +17,15 @@ jobs:
- msystem: "MINGW64" - msystem: "MINGW64"
install: mingw-w64-x86_64-libxml2 mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-clang install: mingw-w64-x86_64-libxml2 mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-clang
type: Release type: Release
- msystem: "MINGW32"
install: mingw-w64-i686-libxml2 mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-clang
type: Release
- msystem: "MINGW64" - msystem: "MINGW64"
install: mingw-w64-x86_64-libxml2 mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-clang install: mingw-w64-x86_64-libxml2 mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-clang
type: Debug type: Debug
- msystem: "MINGW32"
install: mingw-w64-i686-libxml2 mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-clang
type: Debug
env: env:
CMAKE_GENERATOR: Ninja CMAKE_GENERATOR: Ninja
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
@@ -49,6 +38,6 @@ jobs:
run: | run: |
mkdir build mkdir build
cd build cd build
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_DO_NOT_USE_THREADS_NO_MATTER_WHAT=ON .. cmake -DSIMDJSON_DEVELOPER_MODE=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_DO_NOT_USE_THREADS_NO_MATTER_WHAT=ON ..
cmake --build . --verbose cmake --build . --verbose
ctest -j4 --output-on-failure -LE explicitonly ctest -j4 --output-on-failure -LE explicitonly
+3 -15
View File
@@ -1,12 +1,6 @@
name: MSYS2-CI name: MSYS2-CI
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
windows-mingw: windows-mingw:
@@ -25,21 +19,15 @@ jobs:
- msystem: "MINGW64" - msystem: "MINGW64"
install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc
type: Release type: Release
- msystem: "MINGW32"
install: mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-gcc
type: Release
- msystem: "MINGW64" - msystem: "MINGW64"
install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc install: mingw-w64-x86_64-cmake mingw-w64-x86_64-ninja mingw-w64-x86_64-gcc
type: Debug type: Debug
- msystem: "MINGW32"
install: mingw-w64-i686-cmake mingw-w64-i686-ninja mingw-w64-i686-gcc
type: Debug
env: env:
CMAKE_GENERATOR: Ninja CMAKE_GENERATOR: Ninja
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
+2 -2
View File
@@ -15,8 +15,8 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-18.04 runs-on: ubuntu-18.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
+31
View File
@@ -0,0 +1,31 @@
name: Ubuntu 18.04 CI (LLVM 7)
on: [push, pull_request]
jobs:
ubuntu-build:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-18.04
env:
CC: clang-7
CXX: clang++-7
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: install clang 7
run: |
sudo apt update
sudo apt install clang-7
- name: Use cmake
run: |
mkdir build &&
cd build &&
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly
+4 -9
View File
@@ -1,12 +1,7 @@
name: Ubuntu 18.04 CI (GCC 7) with Thread Sanitizer name: Ubuntu 18.04 CI (GCC 7) with Thread Sanitizer
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
ubuntu-build: ubuntu-build:
@@ -15,8 +10,8 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-18.04 runs-on: ubuntu-18.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
+3 -9
View File
@@ -1,12 +1,6 @@
name: Ubuntu 18.04 CI (GCC 7) name: Ubuntu 18.04 CI (GCC 7)
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
ubuntu-build: ubuntu-build:
@@ -15,8 +9,8 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-18.04 runs-on: ubuntu-18.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
+2 -2
View File
@@ -15,8 +15,8 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
+38
View File
@@ -0,0 +1,38 @@
name: Ubuntu 20.04 CI (GCC 8)
on: [push, pull_request]
jobs:
ubuntu-build:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04
env:
CXX: g++-8
CC: gcc-8
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Install GCC 8
run: sudo apt-get install -y g++-8
- name: Use cmake
run: |
mkdir builddebug &&
cd builddebug &&
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly &&
cd .. &&
mkdir build &&
cd build &&
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly &&
cmake --install . &&
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
cd ../tests/installation_tests/find &&
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
+3 -9
View File
@@ -1,12 +1,6 @@
name: Ubuntu 20.04 CI (GCC 9) without exceptions name: Ubuntu 20.04 CI (GCC 9) without exceptions
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
ubuntu-build: ubuntu-build:
@@ -15,8 +9,8 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
+4 -10
View File
@@ -1,12 +1,6 @@
name: Ubuntu 20.04 CI (GCC 9) without threads name: Ubuntu 20.04 CI (GCC 9) Without Threads
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
ubuntu-build: ubuntu-build:
@@ -15,8 +9,8 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
+23
View File
@@ -0,0 +1,23 @@
name: Ubuntu 20.04 CI (GCC 9) With Memory Sanitizer
on: [push, pull_request]
jobs:
ubuntu-build:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Use cmake
run: |
mkdir builddebug &&
cd builddebug &&
cmake -DSIMDJSON_SANITIZE=ON -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly
+3 -9
View File
@@ -1,12 +1,6 @@
name: Ubuntu 20.04 CI (GCC 9) with Thread Sanitizer name: Ubuntu 20.04 CI (GCC 9) with Thread Sanitizer
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
ubuntu-build: ubuntu-build:
@@ -15,8 +9,8 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
+3 -9
View File
@@ -1,12 +1,6 @@
name: Ubuntu 20.04 CI (GCC 9) name: Ubuntu 20.04 CI (GCC 9)
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
ubuntu-build: ubuntu-build:
@@ -15,8 +9,8 @@ jobs:
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
+25
View File
@@ -0,0 +1,25 @@
name: Ubuntu 22.04 CI (CLANG 13)
on: [push, pull_request]
jobs:
ubuntu-build:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Install clang++-13
run: sudo apt-get install -y clang++-13
- name: Use cmake
run: |
mkdir build &&
cd build &&
CXX=clang++-13 cmake -DSIMDJSON_DEVELOPER_MODE=ON .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly
+25
View File
@@ -0,0 +1,25 @@
name: Ubuntu 22.04 CI (GCC 12)
on: [push, pull_request]
jobs:
ubuntu-build:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Install gcc12
run: sudo apt-get install -y g++-12
- name: Use cmake
run: |
mkdir build &&
cd build &&
CXX=g++-12 cmake -DSIMDJSON_DEVELOPER_MODE=ON .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly
+33
View File
@@ -0,0 +1,33 @@
name: Ubuntu 22.04 CI (GCC 11)
on: [push, pull_request]
jobs:
ubuntu-build:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Use cmake
run: |
mkdir builddebug &&
cd builddebug &&
cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly &&
cd .. &&
mkdir build &&
cd build &&
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
cmake --build . &&
ctest -j --output-on-failure -LE explicitonly &&
cmake --install . &&
echo -e '#include <simdjson.h>\nint main(int argc,char**argv) {simdjson::dom::parser parser;simdjson::dom::element tweets = parser.load(argv[1]); }' > tmp.cpp && c++ -Idestination/include -Ldestination/lib -std=c++17 -Wl,-rpath,destination/lib -o linkandrun tmp.cpp -lsimdjson && ./linkandrun jsonexamples/twitter.json &&
cd ../tests/installation_tests/find &&
mkdir build && cd build && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../build/destination .. && cmake --build .
-37
View File
@@ -1,37 +0,0 @@
name: VS16-CLANG-CI
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
ci:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
name: windows-vs16
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: 'Run CMake with VS16 Clang'
uses: lukka/run-cmake@v3
with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
buildDirectory: "${{ github.workspace }}/../../_temp/windows"
cmakeBuildType: Release
buildWithCMake: true
cmakeAppendedArgs: -T ClangCL -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF
buildWithCMakeArgs: --config Release
- name: 'Run CTest'
run: ctest -C Release -LE explicitonly --output-on-failure
working-directory: "${{ github.workspace }}/../../_temp/windows"
-51
View File
@@ -1,51 +0,0 @@
name: VS16-Ninja-CI
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
ci:
if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]')
name: windows-vs16
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: 'Run CMake with VS16'
uses: lukka/run-cmake@v2
with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
buildDirectory: "${{ github.workspace }}/../../_temp/windows"
cmakeBuildType: Release
buildWithCMake: true
cmakeAppendedArgs: -G Ninja -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF
buildWithCMakeArgs: --config Release
- name: 'Run CTest'
run: ctest -C Release -LE explicitonly --output-on-failure
working-directory: "${{ github.workspace }}/../../_temp/windows"
- name: 'Install with CMake'
uses: lukka/run-cmake@v3
with:
cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
buildWithCMakeArgs: '--target install'
- name: 'Test Installation with CMake'
uses: lukka/run-cmake@v3
with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
cmakeListsTxtPath: '${{ github.workspace }}/tests/installation_tests/find/CMakeLists.txt'
cmakeBuildType: Release
buildWithCMake: true
buildDirectory: '${{ github.workspace }}/tests/installation_tests/find/buildDirectory'
cmakeAppendedArgs: -G Ninja
buildWithCMakeArgs: '--config Release --verbose'
@@ -1,10 +1,10 @@
name: VS16-ARM-CI name: VS17-ARM-CI
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
ci: ci:
name: windows-vs16 name: windows-vs17
runs-on: windows-latest runs-on: windows-latest
strategy: strategy:
fail-fast: false fail-fast: false
@@ -14,7 +14,7 @@ jobs:
- {arch: ARM64} - {arch: ARM64}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Use cmake - name: Use cmake
run: | run: |
cmake -A ${{ matrix.arch }} -DCMAKE_CROSSCOMPILING=1 -DSIMDJSON_DEVELOPER_MODE=ON -D SIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_EXCEPTIONS=OFF -B build && cmake -A ${{ matrix.arch }} -DCMAKE_CROSSCOMPILING=1 -DSIMDJSON_DEVELOPER_MODE=ON -D SIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_EXCEPTIONS=OFF -B build &&
@@ -1,34 +1,28 @@
name: VS16-CI name: VS17-CI
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
ci: ci:
if: >- if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') && ! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
name: windows-vs16 name: windows-vs17
runs-on: windows-latest runs-on: windows-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- {gen: Visual Studio 16 2019, arch: Win32, static: ON} - {gen: Visual Studio 17 2022, arch: Win32, shared: ON}
- {gen: Visual Studio 16 2019, arch: Win32, static: OFF} - {gen: Visual Studio 17 2022, arch: Win32, shared: OFF}
- {gen: Visual Studio 16 2019, arch: x64, static: ON} - {gen: Visual Studio 17 2022, arch: x64, shared: ON}
- {gen: Visual Studio 16 2019, arch: x64, static: OFF} - {gen: Visual Studio 17 2022, arch: x64, shared: OFF}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Configure - name: Configure
run: | run: |
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_BUILD_STATIC=${{matrix.static}} -B build cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DBUILD_SHARED_LIBS=${{matrix.shared}} -B build
- name: Build Debug - name: Build Debug
run: cmake --build build --config Debug --verbose run: cmake --build build --config Debug --verbose
- name: Build Release - name: Build Release
@@ -1,34 +1,25 @@
name: VS15-CI name: VS17-CLANG-CI
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
ci: ci:
if: >- if: >-
! contains(toJSON(github.event.commits.*.message), '[skip ci]') && ! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
! contains(toJSON(github.event.commits.*.message), '[skip github]') ! contains(toJSON(github.event.commits.*.message), '[skip github]')
name: windows-vs15 name: windows-vs17
runs-on: windows-2016 runs-on: windows-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- {gen: Visual Studio 15 2017, arch: Win32, static: ON} - {gen: Visual Studio 17 2022, arch: x64}
- {gen: Visual Studio 15 2017, arch: Win32, static: OFF}
- {gen: Visual Studio 15 2017, arch: x64, static: ON}
- {gen: Visual Studio 15 2017, arch: x64, static: OFF}
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Configure - name: Configure
run: | run: |
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_COMPETITION=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_BUILD_STATIC=${{matrix.static}} -B build cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -T ClangCL -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build
- name: Build Debug - name: Build Debug
run: cmake --build build --config Debug --verbose run: cmake --build build --config Debug --verbose
- name: Build Release - name: Build Release
@@ -1,24 +1,18 @@
name: VS16-NoExcept-CI name: VS17-NoExcept-CI
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
ci: ci:
name: windows-vs16 name: windows-vs17
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: actions/cache@v2 - uses: actions/cache@v3
with: with:
path: dependencies/.cache path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }} key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: 'Run CMake with VS16' - name: 'Run CMake with VS17'
uses: lukka/run-cmake@v3 uses: lukka/run-cmake@v3
with: with:
cmakeListsOrSettingsJson: CMakeListsTxtAdvanced cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
+13 -2
View File
@@ -17,7 +17,6 @@
"__errc": "cpp", "__errc": "cpp",
"__functional_base": "cpp", "__functional_base": "cpp",
"__hash_table": "cpp", "__hash_table": "cpp",
"__locale": "cpp",
"__mutex_base": "cpp", "__mutex_base": "cpp",
"__node_handle": "cpp", "__node_handle": "cpp",
"__nullptr": "cpp", "__nullptr": "cpp",
@@ -85,6 +84,18 @@
"utility": "cpp", "utility": "cpp",
"valarray": "cpp", "valarray": "cpp",
"vector": "cpp", "vector": "cpp",
"*.ipp": "cpp" "*.ipp": "cpp",
"__functional_base_03": "cpp",
"filesystem": "cpp",
"*.inc": "cpp",
"compare": "cpp",
"concepts": "cpp",
"variant": "cpp",
"__bits": "cpp",
"csignal": "cpp",
"future": "cpp",
"queue": "cpp",
"shared_mutex": "cpp",
"ranges": "cpp"
} }
} }
+5 -13
View File
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
project( project(
simdjson simdjson
# The version number is modified by tools/release.py # The version number is modified by tools/release.py
VERSION 0.9.1 VERSION 2.2.1
DESCRIPTION "Parsing gigabytes of JSON per second" DESCRIPTION "Parsing gigabytes of JSON per second"
HOMEPAGE_URL "https://simdjson.org/" HOMEPAGE_URL "https://simdjson.org/"
LANGUAGES CXX C LANGUAGES CXX C
@@ -20,8 +20,8 @@ string(
# ---- Options, variables ---- # ---- Options, variables ----
# These version numbers are modified by tools/release.py # These version numbers are modified by tools/release.py
set(SIMDJSON_LIB_VERSION "8.0.0" CACHE STRING "simdjson library version") set(SIMDJSON_LIB_VERSION "13.0.0" CACHE STRING "simdjson library version")
set(SIMDJSON_LIB_SOVERSION "8" CACHE STRING "simdjson library soversion") set(SIMDJSON_LIB_SOVERSION "13" CACHE STRING "simdjson library soversion")
option(SIMDJSON_ENABLE_THREADS "Link with thread support" ON) option(SIMDJSON_ENABLE_THREADS "Link with thread support" ON)
@@ -49,19 +49,10 @@ endif()
if(is_top_project) if(is_top_project)
option(SIMDJSON_DEVELOPER_MODE "Enable targets for developing simdjson" OFF) option(SIMDJSON_DEVELOPER_MODE "Enable targets for developing simdjson" OFF)
option(BUILD_SHARED_LIBS "Build simdjson as a shared library" OFF) option(BUILD_SHARED_LIBS "Build simdjson as a shared library" OFF)
if("$ENV{CI}")
set(SIMDJSON_DEVELOPER_MODE ON CACHE INTERNAL "")
endif()
endif() endif()
include(cmake/handle-deprecations.cmake) include(cmake/handle-deprecations.cmake)
include(cmake/developer-options.cmake)
if(SIMDJSON_DEVELOPER_MODE)
include(cmake/developer-options.cmake)
else()
message(STATUS "Building only the library. Advanced users may want to turn SIMDJSON_DEVELOPER_MODE to ON, e.g., via -D SIMDJSON_DEVELOPER_MODE=ON.")
endif()
# ---- simdjson library ---- # ---- simdjson library ----
@@ -180,6 +171,7 @@ endif()
# ---- Developer mode extras ---- # ---- Developer mode extras ----
if(NOT SIMDJSON_DEVELOPER_MODE) if(NOT SIMDJSON_DEVELOPER_MODE)
message(STATUS "Building only the library. Advanced users may want to turn SIMDJSON_DEVELOPER_MODE to ON, e.g., via -D SIMDJSON_DEVELOPER_MODE=ON.")
return() return()
elseif(NOT is_top_project) elseif(NOT is_top_project)
message(AUTHOR_WARNING "Developer mode is intended for developers of simdjson") message(AUTHOR_WARNING "Developer mode is intended for developers of simdjson")
+4 -4
View File
@@ -62,13 +62,13 @@ Pull Requests
Pull requests are always invited. However, we ask that you follow these guidelines: Pull requests are always invited. However, we ask that you follow these guidelines:
- It is wiser to discuss your ideas first as part of an issue before you start coding. If you omit this step and code first, be prepare to have your code receive scrutiny and be dropped. - It is wise to discuss your ideas first as part of an issue before you start coding. If you omit this step and code first, be prepared to have your code receive scrutiny and be dropped.
- Users should provide a rationale for their changes. Does it improve performance? Does it add a feature? Does it improve maintainability? Does fix a bug? This must be explicitly stated as part of the pull request. Do not propose changes based on taste or intuition. We do not delegate programming to tools: that some tool suggested a code change is not reason enough to change the code. - Users should provide a rationale for their changes. Does it improve performance? Does it add a feature? Does it improve maintainability? Does it fix a bug? This must be explicitly stated as part of the pull request. Do not propose changes based on taste or intuition. We do not delegate programming to tools: that some tool suggested a code change is not reason enough to change the code.
1. When your code improves performance, please document the gains with a benchmark using hard numbers. 1. When your code improves performance, please document the gains with a benchmark using hard numbers.
2. If your code fixes a bug, please be either fix a failing test, or propose a new test. 2. If your code fixes a bug, please either fix a failing test, or propose a new test.
3. Other types of changes must be clearly motivated. We openly discourage changes with no identifiable benefits. 3. Other types of changes must be clearly motivated. We openly discourage changes with no identifiable benefits.
- Changes should be focused and minimal. You should change as few lines of code as possible. Please do not reformat or touch files needlessly. - Changes should be focused and minimal. You should change as few lines of code as possible. Please do not reformat or touch files needlessly.
- New features must be accompanied of new tests, in general. - New features must be accompanied by new tests, in general.
- Your code should pass our continuous-integration tests. It is your responsibility to ensure that your proposal pass the tests. We do not merge pull requests that would break our build. - Your code should pass our continuous-integration tests. It is your responsibility to ensure that your proposal pass the tests. We do not merge pull requests that would break our build.
- An exception to this would be changes to non-code files, such as documentation and assets, or trivial changes to code, such as comments, where it is encouraged to explicitly ask for skipping a CI run using the `[skip ci]` prefix in your Pull Request title **and** in the first line of the most recent commit in a push. Example for such a commit: `[skip ci] Fixed typo in power_of_ten's docs` - An exception to this would be changes to non-code files, such as documentation and assets, or trivial changes to code, such as comments, where it is encouraged to explicitly ask for skipping a CI run using the `[skip ci]` prefix in your Pull Request title **and** in the first line of the most recent commit in a push. Example for such a commit: `[skip ci] Fixed typo in power_of_ten's docs`
This benefits the project in such a way that the CI pipeline is not burdened by running jobs on changes that don't change any behavior in the code, which reduces wait times for other Pull Requests that do change behavior and require testing. This benefits the project in such a way that the CI pipeline is not burdened by running jobs on changes that don't change any behavior in the code, which reduces wait times for other Pull Requests that do change behavior and require testing.
+5 -1
View File
@@ -37,5 +37,9 @@ Furkan Taşkale
Brendan Knapp Brendan Knapp
Danila Kutenin Danila Kutenin
Pavel Pavlov Pavel Pavlov
# if you have contributed to the project and your name does not Hao Chen
Nicolas Boyer
Kim Walisch and Jatin Bhateja (AVX-512 bitset decoder)
Fangzheng Zhang and Weiqiang Wan (AVX-512 kernel)
# if you have contributed to the project and your name does not
# appear in this list, please let us know! # appear in this list, please let us know!
+1 -1
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = "0.9.1" PROJECT_NUMBER = "2.2.1"
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a
+10 -6
View File
@@ -3,7 +3,7 @@
[![Ubuntu 20.04 CI](https://github.com/simdjson/simdjson/workflows/Ubuntu%2020.04%20CI%20(GCC%209)/badge.svg)](https://simdjson.org/plots.html) [![Ubuntu 20.04 CI](https://github.com/simdjson/simdjson/workflows/Ubuntu%2020.04%20CI%20(GCC%209)/badge.svg)](https://simdjson.org/plots.html)
![VS16-CI](https://github.com/simdjson/simdjson/workflows/VS16-CI/badge.svg) ![VS16-CI](https://github.com/simdjson/simdjson/workflows/VS16-CI/badge.svg)
![MinGW64-CI](https://github.com/simdjson/simdjson/workflows/MinGW64-CI/badge.svg) ![MinGW64-CI](https://github.com/simdjson/simdjson/workflows/MinGW64-CI/badge.svg)
[![][license img]][license] [![Doxygen Documentation](https://img.shields.io/badge/docs-doxygen-green.svg)](https://simdjson.org/api/0.9.0/index.html) [![][license img]][license] [![Doxygen Documentation](https://img.shields.io/badge/docs-doxygen-green.svg)](https://simdjson.org/api/2.0.0/index.html)
simdjson : Parsing gigabytes of JSON per second simdjson : Parsing gigabytes of JSON per second
=============================================== ===============================================
@@ -53,6 +53,7 @@ The simdjson library is easily consumable with a single .h and .cpp file.
2. Create `quickstart.cpp`: 2. Create `quickstart.cpp`:
```c++ ```c++
#include <iostream>
#include "simdjson.h" #include "simdjson.h"
using namespace simdjson; using namespace simdjson;
int main(void) { int main(void) {
@@ -78,7 +79,7 @@ Usage documentation is available:
* [Performance](doc/performance.md) shows some more advanced scenarios and how to tune for them. * [Performance](doc/performance.md) shows some more advanced scenarios and how to tune for them.
* [Implementation Selection](doc/implementation-selection.md) describes runtime CPU detection and * [Implementation Selection](doc/implementation-selection.md) describes runtime CPU detection and
how you can work with it. how you can work with it.
* [API](https://simdjson.org/api/0.9.0/annotated.html) contains the automatically generated API documentation. * [API](https://simdjson.org/api/1.0.0/annotated.html) contains the automatically generated API documentation.
Performance results Performance results
------------------- -------------------
@@ -110,10 +111,12 @@ For NDJSON files, we can exceed 3 GB/s with [our multithreaded parsing function
Real-world usage Real-world usage
---------------- ----------------
- [Microsoft FishStore](https://github.com/microsoft/FishStore) - [ClickHouse](https://github.com/ClickHouse/ClickHouse)
- [Yandex ClickHouse](https://github.com/yandex/ClickHouse)
- [Clang Build Analyzer](https://github.com/aras-p/ClangBuildAnalyzer) - [Clang Build Analyzer](https://github.com/aras-p/ClangBuildAnalyzer)
- [Shopify HeapProfiler](https://github.com/Shopify/heap-profiler) - [Shopify HeapProfiler](https://github.com/Shopify/heap-profiler)
- [StarRocks](https://github.com/StarRocks/starrocks)
- [Microsoft FishStore](https://github.com/microsoft/FishStore)
If you are planning to use simdjson in a product, please work from one of our releases. If you are planning to use simdjson in a product, please work from one of our releases.
@@ -137,7 +140,8 @@ We distinguish between "bindings" (which just wrap the C++ code) and a port to a
- [rcppsimdjson](https://github.com/eddelbuettel/rcppsimdjson): R bindings. - [rcppsimdjson](https://github.com/eddelbuettel/rcppsimdjson): R bindings.
- [simdjson_erlang](https://github.com/ChomperT/simdjson_erlang): erlang bindings. - [simdjson_erlang](https://github.com/ChomperT/simdjson_erlang): erlang bindings.
- [lua-simdjson](https://github.com/FourierTransformer/lua-simdjson): lua bindings. - [lua-simdjson](https://github.com/FourierTransformer/lua-simdjson): lua bindings.
- [hermes-json](https://hackage.haskell.org/package/hermes-json): haskell bindings.
- [simdjzon](https://github.com/travisstaloch/simdjzon): zig port.
About simdjson About simdjson
-------------- --------------
@@ -158,7 +162,7 @@ We also have an informal [blog post providing some background and context](https
For the video inclined, <br /> For the video inclined, <br />
[![simdjson at QCon San Francisco 2019](http://img.youtube.com/vi/wlvKAT7SZIQ/0.jpg)](http://www.youtube.com/watch?v=wlvKAT7SZIQ)<br /> [![simdjson at QCon San Francisco 2019](http://img.youtube.com/vi/wlvKAT7SZIQ/0.jpg)](http://www.youtube.com/watch?v=wlvKAT7SZIQ)<br />
(it was the best voted talk, we're kinda proud of it). (It was the best voted talk, we're kinda proud of it.)
Funding Funding
------- -------
@@ -4,18 +4,22 @@
#include <map> #include <map>
#include <string> #include <string>
namespace amazon_cellphones { namespace amazon_cellphones {
const bool UNTHREADED = false;
const bool THREADED = true;
using namespace json_benchmark; using namespace json_benchmark;
struct brand { struct brand {
double cumulative_rating; double cumulative_rating;
uint64_t reviews_count; uint64_t reviews_count;
simdjson_really_inline bool operator==(const brand &other) const { simdjson_inline bool operator==(const brand &other) const {
return cumulative_rating == other.cumulative_rating && return cumulative_rating == other.cumulative_rating &&
reviews_count == other.reviews_count; reviews_count == other.reviews_count;
} }
simdjson_really_inline bool operator!=(const brand &other) const { return !(*this == other); } simdjson_inline bool operator!=(const brand &other) const { return !(*this == other); }
}; };
simdjson_unused static std::ostream &operator<<(std::ostream &o, const brand &b) { simdjson_unused static std::ostream &operator<<(std::ostream &o, const brand &b) {
@@ -59,10 +63,11 @@ struct runner : public file_runner<I> {
} }
}; };
template<bool threaded>
struct simdjson_dom; struct simdjson_dom;
template<typename I> simdjson_really_inline static void amazon_cellphones(benchmark::State &state) { template<typename I> simdjson_inline static void amazon_cellphones(benchmark::State &state) {
run_json_benchmark<runner<I>, runner<simdjson_dom>>(state); run_json_benchmark<runner<I>, runner<simdjson_dom<UNTHREADED>>>(state);
} }
} // namespace amazon_cellphones } // namespace amazon_cellphones
+8 -1
View File
@@ -8,12 +8,16 @@ namespace amazon_cellphones {
using namespace simdjson; using namespace simdjson;
template<bool threaded>
struct simdjson_dom { struct simdjson_dom {
using StringType = std::string; using StringType = std::string;
dom::parser parser{}; dom::parser parser{};
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) { bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
#ifdef SIMDJSON_THREADS_ENABLED
parser.threaded = threaded;
#endif
auto stream = parser.parse_many(json); auto stream = parser.parse_many(json);
auto i = stream.begin(); auto i = stream.begin();
++i; // Skip first line ++i; // Skip first line
@@ -37,7 +41,10 @@ struct simdjson_dom {
}; };
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_dom)->UseManualTime(); BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_dom<UNTHREADED>)->UseManualTime();
#ifdef SIMDJSON_THREADS_ENABLED
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_dom<THREADED>)->UseManualTime();
#endif
} // namespace amazon_cellphones } // namespace amazon_cellphones
@@ -8,17 +8,21 @@ namespace amazon_cellphones {
using namespace simdjson; using namespace simdjson;
template<bool threaded>
struct simdjson_ondemand { struct simdjson_ondemand {
using StringType = std::string; using StringType = std::string;
ondemand::parser parser{}; ondemand::parser parser{};
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) { bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
#ifdef SIMDJSON_THREADS_ENABLED
parser.threaded = threaded;
#endif
ondemand::document_stream stream = parser.iterate_many(json); ondemand::document_stream stream = parser.iterate_many(json);
ondemand::document_stream::iterator i = stream.begin(); ondemand::document_stream::iterator i = stream.begin();
++i; // Skip first line ++i; // Skip first line
for (;i != stream.end(); ++i) { for (;i != stream.end(); ++i) {
auto & doc = *i; auto doc = *i;
size_t index{0}; size_t index{0};
StringType copy; StringType copy;
double rating; double rating;
@@ -58,7 +62,10 @@ struct simdjson_ondemand {
}; };
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_ondemand)->UseManualTime(); BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_ondemand<UNTHREADED>)->UseManualTime();
#ifdef SIMDJSON_THREADS_ENABLED
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_ondemand<THREADED>)->UseManualTime();
#endif
} // namespace amazon_cellphones } // namespace amazon_cellphones
+1
View File
@@ -1,4 +1,5 @@
#include <benchmark/benchmark.h> #include <benchmark/benchmark.h>
#include <iostream>
#include "simdjson.h" #include "simdjson.h"
#include <sstream> #include <sstream>
+6
View File
@@ -25,6 +25,12 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
#include <benchmark/benchmark.h> #include <benchmark/benchmark.h>
SIMDJSON_POP_DISABLE_WARNINGS SIMDJSON_POP_DISABLE_WARNINGS
#include "json2msgpack/simdjson_dom.h"
#include "json2msgpack/simdjson_ondemand.h"
#include "json2msgpack/rapidjson.h"
#include "json2msgpack/yyjson.h"
#include "json2msgpack/sajson.h"
#include "json2msgpack/nlohmann_json.h"
#include "amazon_cellphones/simdjson_dom.h" #include "amazon_cellphones/simdjson_dom.h"
#include "amazon_cellphones/simdjson_ondemand.h" #include "amazon_cellphones/simdjson_ondemand.h"
+1
View File
@@ -1,4 +1,5 @@
#include <benchmark/benchmark.h> #include <benchmark/benchmark.h>
#include <iostream>
#include "simdjson.h" #include "simdjson.h"
using namespace simdjson; using namespace simdjson;
using namespace benchmark; using namespace benchmark;
+42 -6
View File
@@ -97,9 +97,9 @@ struct option_struct {
verbose = true; verbose = true;
break; break;
case 'a': { case 'a': {
auto impl = simdjson::available_implementations[optarg]; auto impl = simdjson::get_available_implementations()[optarg];
if(impl && impl->supported_by_runtime_system()) { if(impl && impl->supported_by_runtime_system()) {
simdjson::active_implementation = impl; simdjson::get_active_implementation() = impl;
} else { } else {
std::cerr << "implementation " << optarg << " not found or not supported " << std::endl; std::cerr << "implementation " << optarg << " not found or not supported " << std::endl;
} }
@@ -164,7 +164,7 @@ struct feature_benchmarker {
} }
simdjson_really_inline void run_iterations(size_t iterations, bool stage1_only=false) { simdjson_inline void run_iterations(size_t iterations, bool stage1_only=false) {
struct7.run_iterations(iterations, stage1_only); struct7.run_iterations(iterations, stage1_only);
struct7_miss.run_iterations(iterations, stage1_only); struct7_miss.run_iterations(iterations, stage1_only);
struct7_full.run_iterations(iterations, stage1_only); struct7_full.run_iterations(iterations, stage1_only);
@@ -204,10 +204,13 @@ struct feature_benchmarker {
} }
// Rate of 1-7-structural misses per 8-structural flip // Rate of 1-7-structural misses per 8-structural flip
double struct1_7_miss_rate(BenchmarkStage stage) const { double struct1_7_miss_rate(BenchmarkStage stage) const {
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
return 1;
#else
if (!has_events()) { return 1; } if (!has_events()) { return 1; }
return struct7_miss[stage].best.branch_misses() - struct7[stage].best.branch_misses() / double(struct7_miss.stats->blocks_with_1_structural_flipped); return struct7_miss[stage].best.branch_misses() - struct7[stage].best.branch_misses() / double(struct7_miss.stats->blocks_with_1_structural_flipped);
#endif
} }
// Extra cost of an 8-15 structural block over a 1-7 structural block // Extra cost of an 8-15 structural block over a 1-7 structural block
double struct8_15_cost(BenchmarkStage stage) const { double struct8_15_cost(BenchmarkStage stage) const {
return cost_per_block(stage, struct15, struct15.stats->blocks_with_8_structurals, struct7); return cost_per_block(stage, struct15, struct15.stats->blocks_with_8_structurals, struct7);
@@ -218,8 +221,12 @@ struct feature_benchmarker {
} }
// Rate of 8-15-structural misses per 8-structural flip // Rate of 8-15-structural misses per 8-structural flip
double struct8_15_miss_rate(BenchmarkStage stage) const { double struct8_15_miss_rate(BenchmarkStage stage) const {
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
return 1;
#else
if (!has_events()) { return 1; } if (!has_events()) { return 1; }
return double(struct15_miss[stage].best.branch_misses() - struct15[stage].best.branch_misses()) / double(struct15_miss.stats->blocks_with_8_structurals_flipped); return double(struct15_miss[stage].best.branch_misses() - struct15[stage].best.branch_misses()) / double(struct15_miss.stats->blocks_with_8_structurals_flipped);
#endif
} }
// Extra cost of a 16+-structural block over an 8-15 structural block (actual varies based on # of structurals!) // Extra cost of a 16+-structural block over an 8-15 structural block (actual varies based on # of structurals!)
@@ -232,10 +239,15 @@ struct feature_benchmarker {
} }
// Rate of 16-structural misses per 16-structural flip // Rate of 16-structural misses per 16-structural flip
double struct16_miss_rate(BenchmarkStage stage) const { double struct16_miss_rate(BenchmarkStage stage) const {
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
return 1;
#else
if (!has_events()) { return 1; } if (!has_events()) { return 1; }
return double(struct23_miss[stage].best.branch_misses() - struct23[stage].best.branch_misses()) / double(struct23_miss.stats->blocks_with_16_structurals_flipped); return double(struct23_miss[stage].best.branch_misses() - struct23[stage].best.branch_misses()) / double(struct23_miss.stats->blocks_with_16_structurals_flipped);
#endif
} }
// Extra cost of having UTF-8 in a block // Extra cost of having UTF-8 in a block
double utf8_cost(BenchmarkStage stage) const { double utf8_cost(BenchmarkStage stage) const {
return cost_per_block(stage, utf8, utf8.stats->blocks_with_utf8, struct7_full); return cost_per_block(stage, utf8, utf8.stats->blocks_with_utf8, struct7_full);
@@ -246,10 +258,13 @@ struct feature_benchmarker {
} }
// Rate of UTF-8 misses per UTF-8 flip // Rate of UTF-8 misses per UTF-8 flip
double utf8_miss_rate(BenchmarkStage stage) const { double utf8_miss_rate(BenchmarkStage stage) const {
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
return 1;
#else
if (!has_events()) { return 1; } if (!has_events()) { return 1; }
return double(utf8_miss[stage].best.branch_misses() - utf8[stage].best.branch_misses()) / double(utf8_miss.stats->blocks_with_utf8_flipped); return double(utf8_miss[stage].best.branch_misses() - utf8[stage].best.branch_misses()) / double(utf8_miss.stats->blocks_with_utf8_flipped);
#endif
} }
// Extra cost of having escapes in a block // Extra cost of having escapes in a block
double escape_cost(BenchmarkStage stage) const { double escape_cost(BenchmarkStage stage) const {
return cost_per_block(stage, escape, escape.stats->blocks_with_escapes, struct7_full); return cost_per_block(stage, escape, escape.stats->blocks_with_escapes, struct7_full);
@@ -260,10 +275,15 @@ struct feature_benchmarker {
} }
// Rate of escape misses per escape flip // Rate of escape misses per escape flip
double escape_miss_rate(BenchmarkStage stage) const { double escape_miss_rate(BenchmarkStage stage) const {
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
return 1;
#else
if (!has_events()) { return 1; } if (!has_events()) { return 1; }
return double(escape_miss[stage].best.branch_misses() - escape[stage].best.branch_misses()) / double(escape_miss.stats->blocks_with_escapes_flipped); return double(escape_miss[stage].best.branch_misses() - escape[stage].best.branch_misses()) / double(escape_miss.stats->blocks_with_escapes_flipped);
#endif
} }
double calc_expected_feature_cost(BenchmarkStage stage, const benchmarker& file) const { double calc_expected_feature_cost(BenchmarkStage stage, const benchmarker& file) const {
// Expected base ns/block (empty) // Expected base ns/block (empty)
json_stats& stats = *file.stats; json_stats& stats = *file.stats;
@@ -300,7 +320,6 @@ struct feature_benchmarker {
double calc_expected(BenchmarkStage stage, const benchmarker& file) const { double calc_expected(BenchmarkStage stage, const benchmarker& file) const {
return calc_expected_feature_cost(stage, file) + calc_expected_miss_cost(stage, file); return calc_expected_feature_cost(stage, file) + calc_expected_miss_cost(stage, file);
} }
void print(const option_struct& options) const { void print(const option_struct& options) const {
printf("\n"); printf("\n");
printf("Features in ns/block (64 bytes):\n"); printf("Features in ns/block (64 bytes):\n");
@@ -359,6 +378,22 @@ struct feature_benchmarker {
} }
}; };
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
void print_file_effectiveness(BenchmarkStage stage, const char* filename, const benchmarker& results, const feature_benchmarker& features) {
double actual = results[stage].best.elapsed_ns() / double(results.stats->blocks);
double calc = features.calc_expected(stage, results);
double calc_misses = features.calc_expected_misses(stage, results);
double calc_miss_cost = features.calc_expected_miss_cost(stage, results);
printf(" | %-8s ", benchmark_stage_name(stage));
printf("| %-15s ", filename);
printf("| %8.3g ", features.calc_expected_feature_cost(stage, results));
printf("| %8.3g ", calc_miss_cost);
printf("| %8.3g ", calc);
printf("| %8.3g ", actual);
printf("| %+8.3g ", actual - calc);
printf("| %13llu ", (long long unsigned)(calc_misses));
}
#else
void print_file_effectiveness(BenchmarkStage stage, const char* filename, const benchmarker& results, const feature_benchmarker& features) { void print_file_effectiveness(BenchmarkStage stage, const char* filename, const benchmarker& results, const feature_benchmarker& features) {
double actual = results[stage].best.elapsed_ns() / double(results.stats->blocks); double actual = results[stage].best.elapsed_ns() / double(results.stats->blocks);
double calc = features.calc_expected(stage, results); double calc = features.calc_expected(stage, results);
@@ -382,6 +417,7 @@ void print_file_effectiveness(BenchmarkStage stage, const char* filename, const
} }
printf("|\n"); printf("|\n");
} }
#endif
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// Read options // Read options
+5 -4
View File
@@ -2,7 +2,7 @@
#define __BENCHMARKER_H #define __BENCHMARKER_H
#include "event_counter.h" #include "event_counter.h"
#include "simdjson.h" // For SIMDJSON_DISABLE_DEPRECATED_WARNINGS #include "simdjson.h"
#include <cassert> #include <cassert>
#include <cctype> #include <cctype>
@@ -308,7 +308,7 @@ struct benchmarker {
return all_stages_without_allocation.iterations; return all_stages_without_allocation.iterations;
} }
simdjson_really_inline void run_iteration(bool stage1_only, bool hotbuffers=false) { simdjson_inline void run_iteration(bool stage1_only, bool hotbuffers=false) {
// Allocate dom::parser // Allocate dom::parser
collector.start(); collector.start();
dom::parser parser; dom::parser parser;
@@ -384,7 +384,7 @@ struct benchmarker {
loop << all_loop_count; loop << all_loop_count;
} }
simdjson_really_inline void run_iterations(size_t iterations, bool stage1_only, bool hotbuffers=false) { simdjson_inline void run_iterations(size_t iterations, bool stage1_only, bool hotbuffers=false) {
for (size_t i = 0; i<iterations; i++) { for (size_t i = 0; i<iterations; i++) {
run_iteration(stage1_only, hotbuffers); run_iteration(stage1_only, hotbuffers);
} }
@@ -423,7 +423,7 @@ struct benchmarker {
stage.instructions() / static_cast<double>(stats->structurals), stage.instructions() / static_cast<double>(stats->structurals),
stage.instructions() / static_cast<double>(stage.cycles()) stage.instructions() / static_cast<double>(stage.cycles())
); );
#if !SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
// NOTE: removed cycles/miss because it is a somewhat misleading stat // NOTE: removed cycles/miss because it is a somewhat misleading stat
printf("%s%-13s: %7.0f branch misses (%6.2f%%) - %.0f cache misses (%6.2f%%) - %.2f cache references\n", printf("%s%-13s: %7.0f branch misses (%6.2f%%) - %.0f cache misses (%6.2f%%) - %.2f cache references\n",
prefix, prefix,
@@ -434,6 +434,7 @@ struct benchmarker {
percent(stage.cache_misses(), all_stages_without_allocation.cache_misses()), percent(stage.cache_misses(), all_stages_without_allocation.cache_misses()),
stage.cache_references() stage.cache_references()
); );
#endif
} }
} }
@@ -46,7 +46,7 @@ struct runner : public file_runner<I> {
struct simdjson_dom; struct simdjson_dom;
template<typename I> simdjson_really_inline static void distinct_user_id(benchmark::State &state) { template<typename I> simdjson_inline static void distinct_user_id(benchmark::State &state) {
run_json_benchmark<runner<I>, runner<simdjson_dom>>(state); run_json_benchmark<runner<I>, runner<simdjson_dom>>(state);
} }
+1 -1
View File
@@ -48,7 +48,7 @@ BENCHMARK_TEMPLATE(distinct_user_id, rapidjson)->UseManualTime();
struct rapidjson_insitu : rapidjson_base { struct rapidjson_insitu : rapidjson_base {
bool run(simdjson::padded_string &json, std::vector<uint64_t> &result) { bool run(simdjson::padded_string &json, std::vector<uint64_t> &result) {
return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag>(json.data()), result); return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag|kParseInsituFlag>(json.data()), result);
} }
}; };
BENCHMARK_TEMPLATE(distinct_user_id, rapidjson_insitu)->UseManualTime(); BENCHMARK_TEMPLATE(distinct_user_id, rapidjson_insitu)->UseManualTime();
+4 -2
View File
@@ -9,12 +9,14 @@ namespace distinct_user_id {
struct sajson { struct sajson {
size_t ast_buffer_size{0}; size_t ast_buffer_size{0};
size_t *ast_buffer{nullptr}; size_t *ast_buffer{nullptr};
simdjson_really_inline std::string_view get_string_view(const ::sajson::value &obj, std::string_view key) { ~sajson() { free(ast_buffer); }
simdjson_inline std::string_view get_string_view(const ::sajson::value &obj, std::string_view key) {
auto val = obj.get_value_of_key({key.data(), key.length()}); auto val = obj.get_value_of_key({key.data(), key.length()});
if (val.get_type() != ::sajson::TYPE_STRING) { throw "field is not a string"; } if (val.get_type() != ::sajson::TYPE_STRING) { throw "field is not a string"; }
return { val.as_cstring(), val.get_string_length() }; return { val.as_cstring(), val.get_string_length() };
} }
simdjson_really_inline uint64_t get_str_uint64(const ::sajson::value &obj, std::string_view key) { simdjson_inline uint64_t get_str_uint64(const ::sajson::value &obj, std::string_view key) {
// Since sajson only supports 53-bit numbers, and IDs in twitter.json can be > 53 bits, we read the corresponding id_str and parse that. // Since sajson only supports 53-bit numbers, and IDs in twitter.json can be > 53 bits, we read the corresponding id_str and parse that.
auto val = obj.get_value_of_key({key.data(), key.length()}); auto val = obj.get_value_of_key({key.data(), key.length()});
if (val.get_type() != ::sajson::TYPE_STRING) { throw "field not a string"; } if (val.get_type() != ::sajson::TYPE_STRING) { throw "field not a string"; }
+5 -5
View File
@@ -66,7 +66,7 @@ void print_usage(ostream& out) {
out << "-H - Make the buffers hot (reduce page allocation and related OS tasks during parsing) [default]" << endl; out << "-H - Make the buffers hot (reduce page allocation and related OS tasks during parsing) [default]" << endl;
out << "-a IMPL - Use the given parser implementation. By default, detects the most advanced" << endl; out << "-a IMPL - Use the given parser implementation. By default, detects the most advanced" << endl;
out << " implementation supported on the host machine." << endl; out << " implementation supported on the host machine." << endl;
for (auto impl : simdjson::available_implementations) { for (auto impl : simdjson::get_available_implementations()) {
if(impl->supported_by_runtime_system()) { if(impl->supported_by_runtime_system()) {
out << "-a " << std::left << std::setw(9) << impl->name() << " - Use the " << impl->description() << " parser implementation." << endl; out << "-a " << std::left << std::setw(9) << impl->name() << " - Use the " << impl->description() << " parser implementation." << endl;
} }
@@ -116,10 +116,10 @@ struct option_struct {
verbose = true; verbose = true;
break; break;
case 'a': { case 'a': {
const implementation *impl = simdjson::available_implementations[optarg]; const implementation *impl = simdjson::get_available_implementations()[optarg];
if ((!impl) || (!impl->supported_by_runtime_system())) { if ((!impl) || (!impl->supported_by_runtime_system())) {
std::string exit_message = string("Unsupported option value -a ") + optarg + ": expected -a with one of "; std::string exit_message = string("Unsupported option value -a ") + optarg + ": expected -a with one of ";
for (auto imple : simdjson::available_implementations) { for (auto imple : simdjson::get_available_implementations()) {
if(imple->supported_by_runtime_system()) { if(imple->supported_by_runtime_system()) {
exit_message += imple->name(); exit_message += imple->name();
exit_message += " "; exit_message += " ";
@@ -127,7 +127,7 @@ struct option_struct {
} }
exit_usage(exit_message); exit_usage(exit_message);
} }
simdjson::active_implementation = impl; simdjson::get_active_implementation() = impl;
break; break;
} }
case 'C': case 'C':
@@ -175,7 +175,7 @@ int main(int argc, char *argv[]) {
option_struct options(argc, argv); option_struct options(argc, argv);
if (options.verbose) { if (options.verbose) {
verbose_stream = &cout; verbose_stream = &cout;
verbose() << "Implementation: " << simdjson::active_implementation->name() << endl; verbose() << "Implementation: " << simdjson::get_active_implementation()->name() << endl;
} }
// Start collecting events. We put this early so if it prints an error message, it's the // Start collecting events. We put this early so if it prints an error message, it's the
+3 -3
View File
@@ -41,7 +41,7 @@ using stat_t = struct stat_s;
simdjson_really_inline void simdjson_process_atom(stat_t &s, simdjson_inline void simdjson_process_atom(stat_t &s,
simdjson::dom::element element) { simdjson::dom::element element) {
if (element.is<int64_t>()) { if (element.is<int64_t>()) {
s.integer_count++; s.integer_count++;
@@ -50,9 +50,9 @@ simdjson_really_inline void simdjson_process_atom(stat_t &s,
} else if(element.is<double>()) { } else if(element.is<double>()) {
s.float_count++; s.float_count++;
} else if (element.is<bool>()) { } else if (element.is<bool>()) {
simdjson::error_code err;
bool v; bool v;
err = element.get(v); simdjson::error_code error;
if ((error = element.get(v))) { std::cerr << error << std::endl; abort(); }
if (v) { if (v) {
s.true_count++; s.true_count++;
} else { } else {
+27 -4
View File
@@ -1,6 +1,15 @@
#ifndef __EVENT_COUNTER_H #ifndef __EVENT_COUNTER_H
#define __EVENT_COUNTER_H #define __EVENT_COUNTER_H
#ifndef SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
#ifdef __aarch64__
// on ARM, we use just cycles and instructions
#define SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS 1
#else
// elsewhere, we try to use four counters.
#define SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS 0
#endif
#endif
#include <cassert> #include <cassert>
#include <cctype> #include <cctype>
#ifndef _MSC_VER #ifndef _MSC_VER
@@ -46,6 +55,12 @@ struct event_count {
event_count(const event_count& other): elapsed(other.elapsed), event_counts(other.event_counts) { } event_count(const event_count& other): elapsed(other.elapsed), event_counts(other.event_counts) { }
// The types of counters (so we can read the getter more easily) // The types of counters (so we can read the getter more easily)
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
enum event_counter_types {
CPU_CYCLES,
INSTRUCTIONS
};
#else
enum event_counter_types { enum event_counter_types {
CPU_CYCLES, CPU_CYCLES,
INSTRUCTIONS, INSTRUCTIONS,
@@ -53,15 +68,16 @@ struct event_count {
CACHE_REFERENCES, CACHE_REFERENCES,
CACHE_MISSES CACHE_MISSES
}; };
#endif
double elapsed_sec() const { return duration<double>(elapsed).count(); } double elapsed_sec() const { return duration<double>(elapsed).count(); }
double elapsed_ns() const { return duration<double, std::nano>(elapsed).count(); } double elapsed_ns() const { return duration<double, std::nano>(elapsed).count(); }
double cycles() const { return static_cast<double>(event_counts[CPU_CYCLES]); } double cycles() const { return static_cast<double>(event_counts[CPU_CYCLES]); }
double instructions() const { return static_cast<double>(event_counts[INSTRUCTIONS]); } double instructions() const { return static_cast<double>(event_counts[INSTRUCTIONS]); }
#if !SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
double branch_misses() const { return static_cast<double>(event_counts[BRANCH_MISSES]); } double branch_misses() const { return static_cast<double>(event_counts[BRANCH_MISSES]); }
double cache_references() const { return static_cast<double>(event_counts[CACHE_REFERENCES]); } double cache_references() const { return static_cast<double>(event_counts[CACHE_REFERENCES]); }
double cache_misses() const { return static_cast<double>(event_counts[CACHE_MISSES]); } double cache_misses() const { return static_cast<double>(event_counts[CACHE_MISSES]); }
#endif
event_count& operator=(const event_count& other) { event_count& operator=(const event_count& other) {
this->elapsed = other.elapsed; this->elapsed = other.elapsed;
this->event_counts = other.event_counts; this->event_counts = other.event_counts;
@@ -105,9 +121,11 @@ struct event_aggregate {
double elapsed_ns() const { return total.elapsed_ns() / iterations; } double elapsed_ns() const { return total.elapsed_ns() / iterations; }
double cycles() const { return total.cycles() / iterations; } double cycles() const { return total.cycles() / iterations; }
double instructions() const { return total.instructions() / iterations; } double instructions() const { return total.instructions() / iterations; }
#if !SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
double branch_misses() const { return total.branch_misses() / iterations; } double branch_misses() const { return total.branch_misses() / iterations; }
double cache_references() const { return total.cache_references() / iterations; } double cache_references() const { return total.cache_references() / iterations; }
double cache_misses() const { return total.cache_misses() / iterations; } double cache_misses() const { return total.cache_misses() / iterations; }
#endif
}; };
struct event_collector { struct event_collector {
@@ -117,11 +135,16 @@ struct event_collector {
#if defined(__linux__) #if defined(__linux__)
LinuxEvents<PERF_TYPE_HARDWARE> linux_events; LinuxEvents<PERF_TYPE_HARDWARE> linux_events;
event_collector(bool quiet = false) : linux_events(vector<int>{ event_collector(bool quiet = false) : linux_events(vector<int>{
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
PERF_COUNT_HW_CPU_CYCLES,
PERF_COUNT_HW_INSTRUCTIONS,
#else
PERF_COUNT_HW_CPU_CYCLES, PERF_COUNT_HW_CPU_CYCLES,
PERF_COUNT_HW_INSTRUCTIONS, PERF_COUNT_HW_INSTRUCTIONS,
PERF_COUNT_HW_BRANCH_MISSES, PERF_COUNT_HW_BRANCH_MISSES,
PERF_COUNT_HW_CACHE_REFERENCES, PERF_COUNT_HW_CACHE_REFERENCES,
PERF_COUNT_HW_CACHE_MISSES PERF_COUNT_HW_CACHE_MISSES
#endif
}, quiet) {} }, quiet) {}
bool has_events() { bool has_events() {
return linux_events.is_working(); return linux_events.is_working();
@@ -133,13 +156,13 @@ struct event_collector {
} }
#endif #endif
simdjson_really_inline void start() { simdjson_inline void start() {
#if defined(__linux) #if defined(__linux)
linux_events.start(); linux_events.start();
#endif #endif
start_clock = steady_clock::now(); start_clock = steady_clock::now();
} }
simdjson_really_inline event_count& end() { simdjson_inline event_count& end() {
time_point<steady_clock> end_clock = steady_clock::now(); time_point<steady_clock> end_clock = steady_clock::now();
#if defined(__linux) #if defined(__linux)
linux_events.end(count.event_counts); linux_events.end(count.event_counts);
+1 -1
View File
@@ -33,7 +33,7 @@ struct runner : public file_runner<I> {
struct simdjson_dom; struct simdjson_dom;
template<typename I> simdjson_really_inline static void find_tweet(benchmark::State &state) { template<typename I> simdjson_inline static void find_tweet(benchmark::State &state) {
run_json_benchmark<runner<I>, runner<simdjson_dom>>(state); run_json_benchmark<runner<I>, runner<simdjson_dom>>(state);
} }
+1 -1
View File
@@ -42,7 +42,7 @@ BENCHMARK_TEMPLATE(find_tweet, rapidjson)->UseManualTime();
struct rapidjson_insitu : rapidjson_base { struct rapidjson_insitu : rapidjson_base {
bool run(simdjson::padded_string &json, uint64_t find_id, std::string_view &result) { bool run(simdjson::padded_string &json, uint64_t find_id, std::string_view &result) {
return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag>(json.data()), find_id, result); return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag|kParseInsituFlag>(json.data()), find_id, result);
} }
}; };
BENCHMARK_TEMPLATE(find_tweet, rapidjson_insitu)->UseManualTime(); BENCHMARK_TEMPLATE(find_tweet, rapidjson_insitu)->UseManualTime();
+4 -2
View File
@@ -11,12 +11,14 @@ struct sajson {
size_t ast_buffer_size{0}; size_t ast_buffer_size{0};
size_t *ast_buffer{nullptr}; size_t *ast_buffer{nullptr};
simdjson_really_inline std::string_view get_string_view(const ::sajson::value &obj, std::string_view key) { ~sajson() { free(ast_buffer); }
simdjson_inline std::string_view get_string_view(const ::sajson::value &obj, std::string_view key) {
auto val = obj.get_value_of_key({key.data(), key.length()}); auto val = obj.get_value_of_key({key.data(), key.length()});
if (val.get_type() != ::sajson::TYPE_STRING) { throw "field is not a string"; } if (val.get_type() != ::sajson::TYPE_STRING) { throw "field is not a string"; }
return { val.as_cstring(), val.get_string_length() }; return { val.as_cstring(), val.get_string_length() };
} }
simdjson_really_inline uint64_t get_str_uint64(const ::sajson::value &obj, std::string_view key) { simdjson_inline uint64_t get_str_uint64(const ::sajson::value &obj, std::string_view key) {
// Since sajson only supports 53-bit numbers, and IDs in twitter.json can be > 53 bits, we read the corresponding id_str and parse that. // Since sajson only supports 53-bit numbers, and IDs in twitter.json can be > 53 bits, we read the corresponding id_str and parse that.
auto val = obj.get_value_of_key({key.data(), key.length()}); auto val = obj.get_value_of_key({key.data(), key.length()});
if (val.get_type() != ::sajson::TYPE_STRING) { throw "field not a string"; } if (val.get_type() != ::sajson::TYPE_STRING) { throw "field not a string"; }
+48
View File
@@ -0,0 +1,48 @@
#pragma once
#include "json_benchmark/file_runner.h"
namespace json2msgpack {
using namespace json_benchmark;
template <typename I> struct runner : public file_runner<I> {
std::string_view result;
std::unique_ptr<char[]> buffer;
bool setup(benchmark::State &state) {
bool isok = this->load_json(state, TWITTER_JSON);
if (isok) {
// Let us allocate a sizeable buffer.
buffer = std::unique_ptr<char[]>(new char[this->json.size() * 4 + 1024]);
}
return isok;
}
bool before_run(benchmark::State &state) {
if (!file_runner<I>::before_run(state)) {
return false;
}
// Clear the buffer.
::memset(buffer.get(), 0, this->json.size() * 4 + 1024);
return true;
}
bool run(benchmark::State &) {
return this->implementation.run(this->json, buffer.get(), result);
}
template <typename R>
bool diff(benchmark::State &state, runner<R> &reference) {
return diff_results(state, result.size(), reference.result.size(), diff_flags::NONE);
}
};
struct simdjson_ondemand;
template <typename I>
simdjson_inline static void json2msgpack(benchmark::State &state) {
run_json_benchmark<runner<I>, runner<simdjson_ondemand>>(state);
}
} // namespace json2msgpack
+117
View File
@@ -0,0 +1,117 @@
#pragma once
#ifdef SIMDJSON_COMPETITION_NLOHMANN_JSON
#include "json2msgpack.h"
namespace json2msgpack {
using namespace nlohmann;
struct nlohmann_json2msgpack {
inline std::string_view to_msgpack(const simdjson::padded_string &json,
uint8_t *buf);
private:
inline void write_double(const double d) noexcept;
inline void write_byte(const uint8_t b) noexcept;
inline void write_uint32(const uint32_t w) noexcept;
inline void write_string(const std::string& str);
inline void recursive_processor(basic_json<> element);
uint8_t *buff{};
};
std::string_view nlohmann_json2msgpack::to_msgpack(const simdjson::padded_string &json,
uint8_t *buf) {
buff = buf;
auto val = nlohmann::json::parse(json.data(), json.data() + json.size());
recursive_processor(val);
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
}
void nlohmann_json2msgpack::write_double(const double d) noexcept {
*buff++ = 0xcb;
::memcpy(buff, &d, sizeof(d));
buff += sizeof(d);
}
void nlohmann_json2msgpack::write_byte(const uint8_t b) noexcept {
*buff = b;
buff++;
}
void nlohmann_json2msgpack::write_uint32(const uint32_t w) noexcept {
::memcpy(buff, &w, sizeof(w));
buff += sizeof(w);
}
void nlohmann_json2msgpack::write_string(const std::string & str) {
write_byte(0xdb);
write_uint32(uint32_t(str.size()));
::memcpy(buff, str.data(), str.size());
buff += str.size();
}
void nlohmann_json2msgpack::recursive_processor(json element) {
switch (element.type()) {
case nlohmann::detail::value_t::array: {
uint32_t counter = 0;
write_byte(0xdd);
std::vector<json> array = element.get<std::vector<json>>();
write_uint32(uint32_t(array.size()));
for (auto child : array) {
recursive_processor(child);
}
} break;
case nlohmann::detail::value_t::object: {
write_byte(0xdf);
std::map<std::string,json> object = element.get<std::map<std::string,json>>();
write_uint32(uint32_t(object.size()));
for (auto field : object) {
write_string(field.first);
recursive_processor(field.second);
}
} break;
case nlohmann::detail::value_t::number_integer:
case nlohmann::detail::value_t::number_unsigned:
case nlohmann::detail::value_t::number_float:
write_double(double(element));
break;
case nlohmann::detail::value_t::string:
write_string(std::string(element));
break;
case nlohmann::detail::value_t::boolean:
write_byte(0xc2 + bool(element));
break;
case nlohmann::detail::value_t::null:
write_byte(0xc0);
break;
case nlohmann::detail::value_t::discarded:
case nlohmann::detail::value_t::binary:
default:
printf("unexpected\n");
break;
}
}
struct nlohmann_json {
using StringType = std::string_view;
nlohmann_json2msgpack parser{};
bool run(simdjson::padded_string &json, char *buffer,
std::string_view &result) {
result = parser.to_msgpack(json, reinterpret_cast<uint8_t *>(buffer));
return true;
}
};
BENCHMARK_TEMPLATE(json2msgpack, nlohmann_json)->UseManualTime();
} // namespace json2msgpack
#endif // SIMDJSON_COMPETITION_NLOHMANN_JSON
+140
View File
@@ -0,0 +1,140 @@
#pragma once
#ifdef SIMDJSON_COMPETITION_RAPIDJSON
#include "json2msgpack.h"
namespace json2msgpack {
using namespace rapidjson;
template <int parseflag>
struct rapidjson2msgpack {
inline std::string_view to_msgpack(char *json, uint8_t *buf);
private:
inline void write_double(const double d) noexcept;
inline void write_byte(const uint8_t b) noexcept;
inline void write_uint32(const uint32_t w) noexcept;
inline void write_uint32_at(const uint32_t w, uint8_t *p) noexcept;
void write_string(const char * s, size_t length) noexcept;
inline void recursive_processor(Value &v);
uint8_t *buff{};
};
template <int parseflag>
std::string_view rapidjson2msgpack<parseflag>::to_msgpack(char *json, uint8_t *buf) {
buff = buf;
Document doc{};
if(parseflag & kParseInsituFlag) {
doc.ParseInsitu<parseflag>(json);
} else {
doc.Parse<parseflag>(json);
}
recursive_processor(doc);
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
}
template <int parseflag>
void rapidjson2msgpack<parseflag>::write_double(const double d) noexcept {
*buff++ = 0xcb;
::memcpy(buff, &d, sizeof(d));
buff += sizeof(d);
}
template <int parseflag>
void rapidjson2msgpack<parseflag>::write_byte(const uint8_t b) noexcept {
*buff = b;
buff++;
}
template <int parseflag>
void rapidjson2msgpack<parseflag>::write_string(const char * c, size_t len) noexcept {
write_byte(0xdb);
write_uint32(uint32_t(len));
::memcpy(buff, c, len);
buff += len;
}
template <int parseflag>
void rapidjson2msgpack<parseflag>::write_uint32(const uint32_t w) noexcept {
::memcpy(buff, &w, sizeof(w));
buff += sizeof(w);
}
template <int parseflag>
void rapidjson2msgpack<parseflag>::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
::memcpy(p, &w, sizeof(w));
}
template <int parseflag>
void rapidjson2msgpack<parseflag>::recursive_processor(Value &v) {
switch (v.GetType()) {
case kArrayType:
write_byte(0xdd);
write_uint32(v.Size());
for (Value::ValueIterator i = v.Begin(); i != v.End(); ++i) {
recursive_processor(*i);
}
break;
case kObjectType:
write_byte(0xdf);
write_uint32(uint32_t(v.MemberEnd()-v.MemberBegin()));
for (Value::MemberIterator m = v.MemberBegin(); m != v.MemberEnd();
++m) {
write_string(m->name.GetString(), m->name.GetStringLength());
recursive_processor(m->value);
}
break;
case kStringType:
write_string(v.GetString(), v.GetStringLength());
break;
case kNumberType:
write_double(v.GetDouble());
break;
case kFalseType:
write_byte(0xc2);
break;
case kTrueType:
write_byte(0xc3);
break;
case kNullType:
write_byte(0xc0);
break;
}
}
template <int parseflag>
struct rapidjson_base {
using StringType = std::string_view;
rapidjson2msgpack<parseflag> parser{};
bool run(simdjson::padded_string &json, char *buffer,
std::string_view &result) {
result =
parser.to_msgpack(json.data(), reinterpret_cast<uint8_t *>(buffer));
return true;
}
};
using rapidjson_lossless = rapidjson_base<kParseValidateEncodingFlag|kParseFullPrecisionFlag>;
BENCHMARK_TEMPLATE(json2msgpack, rapidjson_lossless)->UseManualTime();
using rapidjson = rapidjson_base<kParseValidateEncodingFlag>;
BENCHMARK_TEMPLATE(json2msgpack, rapidjson)->UseManualTime();
using rapidjson_insitu = rapidjson_base<kParseValidateEncodingFlag|kParseInsituFlag>;
BENCHMARK_TEMPLATE(json2msgpack, rapidjson_insitu)->UseManualTime();
} // namespace json2msgpack
#endif // SIMDJSON_COMPETITION_RAPIDJSON
+131
View File
@@ -0,0 +1,131 @@
#pragma once
#ifdef SIMDJSON_COMPETITION_SAJSON
#include "json2msgpack.h"
namespace json2msgpack {
using namespace sajson;
struct sajson2msgpack {
inline std::string_view to_msgpack(char *json, size_t size, uint8_t *buf);
virtual ~sajson2msgpack() { free(ast_buffer); }
private:
inline void write_double(const double d) noexcept;
inline void write_byte(const uint8_t b) noexcept;
inline void write_uint32(const uint32_t w) noexcept;
inline void write_string(const char * s, size_t length) noexcept;
inline void recursive_processor(const sajson::value &v);
uint8_t *buff{};
size_t ast_buffer_size{0};
size_t *ast_buffer{nullptr};
};
std::string_view sajson2msgpack::to_msgpack(char *json, size_t size, uint8_t *buf) {
buff = buf;
if (!ast_buffer) {
ast_buffer_size = size;
ast_buffer = (size_t *)std::malloc(ast_buffer_size * sizeof(size_t));
}
auto doc = parse(
bounded_allocation(ast_buffer, ast_buffer_size),
mutable_string_view(size, json)
);
auto root = doc.get_root();
recursive_processor(root);
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
}
void sajson2msgpack::write_string(const char * c, size_t len) noexcept {
write_byte(0xdb);
write_uint32(uint32_t(len));
::memcpy(buff, c, len);
buff += len;
}
void sajson2msgpack::write_double(const double d) noexcept {
*buff++ = 0xcb;
::memcpy(buff, &d, sizeof(d));
buff += sizeof(d);
}
void sajson2msgpack::write_byte(const uint8_t b) noexcept {
*buff = b;
buff++;
}
void sajson2msgpack::write_uint32(const uint32_t w) noexcept {
::memcpy(buff, &w, sizeof(w));
buff += sizeof(w);
}
void sajson2msgpack::recursive_processor(const sajson::value &node) {
using namespace sajson;
switch (node.get_type()) {
case TYPE_NULL:
write_byte(0xc0);
break;
case TYPE_FALSE:
write_byte(0xc2);
break;
case TYPE_TRUE:
write_byte(0xc3);
break;
case TYPE_ARRAY: {
auto length = node.get_length();
write_byte(0xdf);
write_uint32(uint32_t(length));
for (size_t i = 0; i < length; ++i) {
recursive_processor(node.get_array_element(i));
}
break;
}
case TYPE_OBJECT: {
auto length = node.get_length();
write_byte(0xdd);
write_uint32(uint32_t(length));
for (auto i = 0u; i < length; ++i) {
auto s = node.get_object_key(i);
write_string(s.data(), s.length());
recursive_processor(node.get_object_value(i));
}
break;
}
case TYPE_STRING:
write_string(node.as_cstring(), node.get_string_length());
break;
case TYPE_DOUBLE:
case TYPE_INTEGER:
write_double(node.get_number_value());
break;
default:
assert(false && "unknown node type");
}
}
struct sajson {
using StringType = std::string_view;
sajson2msgpack parser{};
bool run(simdjson::padded_string &json, char *buffer,
std::string_view &result) {
result =
parser.to_msgpack(json.data(), json.size(), reinterpret_cast<uint8_t *>(buffer));
return true;
}
};
BENCHMARK_TEMPLATE(json2msgpack, sajson)->UseManualTime();
} // namespace json2msgpack
#endif // SIMDJSON_COMPETITION_SAJSON
+138
View File
@@ -0,0 +1,138 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "json2msgpack.h"
namespace json2msgpack {
using namespace simdjson;
struct simdjsondom2msgpack {
/**
* @brief Converts the provided JSON into msgpack.
*
* @param json JSON input
* @param buf temporary buffer (must be large enough, with simdjson::SIMDJSON_PADDING bytes
* of padding)
* @return std::string_view msgpack output, writting to the temporary buffer
*/
inline std::string_view to_msgpack(const simdjson::padded_string &json,
uint8_t *buf);
private:
simdjson_really_inline void write_double(const double d) noexcept;
simdjson_really_inline void write_string(const std::string_view v) noexcept;
simdjson_really_inline void write_byte(const uint8_t b) noexcept;
simdjson_really_inline void write_uint32(const uint32_t w) noexcept;
simdjson_really_inline uint8_t *skip_uint32() noexcept;
simdjson_really_inline void write_uint32_at(const uint32_t w,
uint8_t *p) noexcept;
inline void recursive_processor(simdjson::dom::element element);
dom::parser parser;
uint8_t *buff{};
};
std::string_view
simdjsondom2msgpack::to_msgpack(const simdjson::padded_string &json,
uint8_t *buf) {
buff = buf;
recursive_processor(parser.parse(json));
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
}
void simdjsondom2msgpack::write_string(const std::string_view v) noexcept {
write_byte(0xdb);
write_uint32(uint32_t(v.size()));
::memcpy(buff, v.data(), v.size());
buff += v.size();
}
void simdjsondom2msgpack::write_double(const double d) noexcept {
*buff++ = 0xcb;
::memcpy(buff, &d, sizeof(d));
buff += sizeof(d);
}
void simdjsondom2msgpack::write_byte(const uint8_t b) noexcept {
*buff = b;
buff++;
}
void simdjsondom2msgpack::write_uint32(const uint32_t w) noexcept {
::memcpy(buff, &w, sizeof(w));
buff += sizeof(w);
}
uint8_t *simdjsondom2msgpack::skip_uint32() noexcept {
uint8_t *ret = buff;
buff += sizeof(uint32_t);
return ret;
}
void simdjsondom2msgpack::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
::memcpy(p, &w, sizeof(w));
}
void simdjsondom2msgpack::recursive_processor(simdjson::dom::element element) {
switch (element.type()) {
case dom::element_type::ARRAY: {
uint32_t counter = 0;
write_byte(0xdd);
uint8_t *location = skip_uint32();
for (auto child : dom::array(element)) {
counter++;
recursive_processor(child);
}
write_uint32_at(counter, location);}
break;
case dom::element_type::OBJECT:{
uint32_t counter = 0;
write_byte(0xdf);
uint8_t *location = skip_uint32();
for (dom::key_value_pair field : dom::object(element)) {
counter++;
write_string(field.key);
recursive_processor(field.value);
}
write_uint32_at(counter, location);
}
break;
case dom::element_type::INT64:
case dom::element_type::UINT64:
case dom::element_type::DOUBLE:
write_double( double(element));
break;
case dom::element_type::STRING:
write_string(std::string_view(element));
break;
case dom::element_type::BOOL:
write_byte(0xc2 + bool(element));
break;
case dom::element_type::NULL_VALUE:
write_byte(0xc0);
break;
default:
break;
}
}
struct simdjson_dom {
using StringType = std::string_view;
simdjsondom2msgpack parser{};
bool run(simdjson::padded_string &json, char *buffer,
std::string_view &result) {
result = parser.to_msgpack(json, reinterpret_cast<uint8_t *>(buffer));
return true;
}
};
BENCHMARK_TEMPLATE(json2msgpack, simdjson_dom)->UseManualTime();
} // namespace json2msgpack
#endif // SIMDJSON_EXCEPTIONS
+182
View File
@@ -0,0 +1,182 @@
#pragma once
#if SIMDJSON_EXCEPTIONS
#include "json2msgpack.h"
namespace json2msgpack {
using namespace simdjson;
/**
* @brief The simdjson2msgpack struct is used to quickly convert
* JSON strings to msgpack views. You must provide a pointer to
* a large memory region where the msgpack gets written. The
* buffer should be large enough to store the msgpack output (which
* can never be 3x larger than the input JSON) with an additional
* simdjson::SIMDJSON_PADDING bytes.
*
* Recommended usage:
*
* simdjson2msgpack parser{};
* simdjson::padded_string json = "[1,2]"_padded; // some JSON
* uint8_t * buffer = new uint8_t[3*json.size() + simdjson::SIMDJSON_PADDING]; // large buffer
*
* std::string_view msgpack = parser.to_msgpack(json, buffer);
*
* The result (msgpack) is a string view to a msgpack serialization of the input JSON,
* it points inside the buffer you provided.
*
* You may reuse the simdjson2msgpack instance though you should use
* one per thread.
*/
struct simdjson2msgpack {
/**
* @brief Converts the provided JSON into msgpack.
*
* @param json JSON input
* @param buf temporary buffer (must be large enough, with simdjson::SIMDJSON_PADDING bytes
* of padding)
* @return std::string_view msgpack output, writting to the temporary buffer
*/
inline std::string_view to_msgpack(const simdjson::padded_string &json,
uint8_t *buf);
private:
simdjson_inline void write_double(const double d) noexcept;
simdjson_inline void write_byte(const uint8_t b) noexcept;
simdjson_inline void write_uint32(const uint32_t w) noexcept;
simdjson_inline uint8_t *skip_uint32() noexcept;
simdjson_inline void write_uint32_at(const uint32_t w,
uint8_t *p) noexcept;
simdjson_inline void
write_raw_string(simdjson::ondemand::raw_json_string rjs);
inline void recursive_processor(simdjson::ondemand::value element);
simdjson::ondemand::parser parser;
uint8_t *buff{};
};
std::string_view
simdjson2msgpack::to_msgpack(const simdjson::padded_string &json,
uint8_t *buf) {
buff = buf;
ondemand::document doc = parser.iterate(json);
if (doc.is_scalar()) {
// we have a special case where the JSON document is a single document...
switch (doc.type()) {
case simdjson::ondemand::json_type::number:
write_double(doc.get_double());
break;
case simdjson::ondemand::json_type::string:
write_raw_string(doc.get_raw_json_string());
break;
case simdjson::ondemand::json_type::boolean:
write_byte(0xc2 + doc.get_bool());
break;
case simdjson::ondemand::json_type::null:
write_byte(0xc0);
break;
case simdjson::ondemand::json_type::array:
case simdjson::ondemand::json_type::object:
default:
// impossible
break;
}
} else {
simdjson::ondemand::value val = doc;
recursive_processor(val);
}
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
}
void simdjson2msgpack::write_double(const double d) noexcept {
*buff++ = 0xcb;
::memcpy(buff, &d, sizeof(d));
buff += sizeof(d);
}
void simdjson2msgpack::write_byte(const uint8_t b) noexcept {
*buff = b;
buff++;
}
void simdjson2msgpack::write_uint32(const uint32_t w) noexcept {
::memcpy(buff, &w, sizeof(w));
buff += sizeof(w);
}
uint8_t *simdjson2msgpack::skip_uint32() noexcept {
uint8_t *ret = buff;
buff += sizeof(uint32_t);
return ret;
}
void simdjson2msgpack::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
::memcpy(p, &w, sizeof(w));
}
void simdjson2msgpack::write_raw_string(
simdjson::ondemand::raw_json_string in) {
write_byte(0xdb);
uint8_t *location = skip_uint32();
std::string_view v = parser.unescape(in, buff);
write_uint32_at(uint32_t(v.size()), location);
}
void simdjson2msgpack::recursive_processor(simdjson::ondemand::value element) {
switch (element.type()) {
case simdjson::ondemand::json_type::array: {
uint32_t counter = 0;
write_byte(0xdd);
uint8_t *location = skip_uint32();
for (auto child : element.get_array()) {
counter++;
recursive_processor(child.value());
}
write_uint32_at(counter, location);
} break;
case simdjson::ondemand::json_type::object: {
uint32_t counter = 0;
write_byte(0xdf);
uint8_t *location = skip_uint32();
for (auto field : element.get_object()) {
counter++;
write_raw_string(field.key());
recursive_processor(field.value());
}
write_uint32_at(counter, location);
} break;
case simdjson::ondemand::json_type::number:
write_double(element.get_double());
break;
case simdjson::ondemand::json_type::string:
write_raw_string(element.get_raw_json_string());
break;
case simdjson::ondemand::json_type::boolean:
write_byte(0xc2 + element.get_bool());
break;
case simdjson::ondemand::json_type::null:
write_byte(0xc0);
break;
default:
SIMDJSON_UNREACHABLE();
}
}
struct simdjson_ondemand {
using StringType = std::string_view;
simdjson2msgpack parser{};
bool run(simdjson::padded_string &json, char *buffer,
std::string_view &result) {
result = parser.to_msgpack(json, reinterpret_cast<uint8_t *>(buffer));
return true;
}
};
BENCHMARK_TEMPLATE(json2msgpack, simdjson_ondemand)->UseManualTime();
} // namespace json2msgpack
#endif // SIMDJSON_EXCEPTIONS
+122
View File
@@ -0,0 +1,122 @@
#pragma once
#ifdef SIMDJSON_COMPETITION_YYJSON
#include "json2msgpack.h"
namespace json2msgpack {
struct yyjson2msgpack {
inline std::string_view to_msgpack(yyjson_doc *doc, uint8_t *buf);
private:
inline void write_double(const double d) noexcept;
inline void write_byte(const uint8_t b) noexcept;
inline void write_uint32(const uint32_t w) noexcept;
inline void write_string(const char *s, size_t length) noexcept;
inline void recursive_processor(yyjson_val *obj);
uint8_t *buff{};
};
std::string_view yyjson2msgpack::to_msgpack(yyjson_doc *doc, uint8_t *buf) {
buff = buf;
yyjson_val *root = yyjson_doc_get_root(doc);
recursive_processor(root);
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
}
void yyjson2msgpack::write_string(const char *c, size_t len) noexcept {
write_byte(0xdb);
write_uint32(uint32_t(len));
::memcpy(buff, c, len);
buff += len;
}
void yyjson2msgpack::write_double(const double d) noexcept {
*buff++ = 0xcb;
::memcpy(buff, &d, sizeof(d));
buff += sizeof(d);
}
void yyjson2msgpack::write_byte(const uint8_t b) noexcept {
*buff = b;
buff++;
}
void yyjson2msgpack::write_uint32(const uint32_t w) noexcept {
::memcpy(buff, &w, sizeof(w));
buff += sizeof(w);
}
void yyjson2msgpack::recursive_processor(yyjson_val *obj) {
size_t idx, max;
yyjson_val *val;
yyjson_val *key;
switch (yyjson_get_type(obj)) {
case YYJSON_TYPE_STR:
write_string(yyjson_get_str(obj), yyjson_get_len(obj));
break;
case YYJSON_TYPE_ARR:
write_byte(0xdf);
write_uint32(uint32_t(yyjson_arr_size(obj)));
yyjson_arr_foreach(obj, idx, max, val) { recursive_processor(val); }
break;
case YYJSON_TYPE_OBJ:
write_byte(0xdd);
write_uint32(uint32_t(yyjson_obj_size(obj)));
yyjson_obj_foreach(obj, idx, max, key, val) {
write_string(yyjson_get_str(key), yyjson_get_len(key));
recursive_processor(val);
}
break;
case YYJSON_TYPE_BOOL:
write_byte(0xc2 + yyjson_get_bool(obj));
break;
case YYJSON_TYPE_NULL:
write_byte(0xc0);
break;
case YYJSON_TYPE_NUM:
switch (yyjson_get_subtype(obj)) {
case YYJSON_SUBTYPE_UINT:
write_double(double(yyjson_get_uint(obj)));
break;
case YYJSON_SUBTYPE_SINT:
write_double(double(yyjson_get_sint(obj)));
break;
case YYJSON_SUBTYPE_REAL:
write_double(yyjson_get_real(obj));
break;
default:
SIMDJSON_UNREACHABLE();
}
break;
default:
SIMDJSON_UNREACHABLE();
}
}
struct yyjson : yyjson2msgpack {
bool run(simdjson::padded_string &json, char *buffer,
std::string_view &result) {
yyjson_doc *doc = yyjson_read(json.data(), json.size(), 0);
result = to_msgpack(doc, reinterpret_cast<uint8_t*>(buffer));
return true;
}
};
BENCHMARK_TEMPLATE(json2msgpack, yyjson)->UseManualTime();
struct yyjson_insitu : yyjson2msgpack {
bool run(simdjson::padded_string &json, char *buffer,
std::string_view &result) {
yyjson_doc *doc =
yyjson_read_opts(json.data(), json.size(), YYJSON_READ_INSITU, 0, 0);
result = to_msgpack(doc, reinterpret_cast<uint8_t*>(buffer));
return true;
}
};
BENCHMARK_TEMPLATE(json2msgpack, yyjson_insitu)->UseManualTime();
} // namespace json2msgpack
#endif // SIMDJSON_COMPETITION_YYJSON
@@ -10,8 +10,8 @@ void maybe_display_implementation() {
static bool displayed_implementation = false; static bool displayed_implementation = false;
if(!displayed_implementation) { if(!displayed_implementation) {
displayed_implementation = true; displayed_implementation = true;
std::cout << "simdjson::dom implementation: " << simdjson::active_implementation->name() << std::endl; std::cout << "simdjson::dom implementation: " << simdjson::get_active_implementation()->name() << std::endl;
std::cout << "simdjson::ondemand implementation (stage 1): " << simdjson::active_implementation->name() << std::endl; std::cout << "simdjson::ondemand implementation (stage 1): " << simdjson::get_active_implementation()->name() << std::endl;
std::cout << "simdjson::ondemand implementation (stage 2): " << simdjson::builtin_implementation()->name() << std::endl; std::cout << "simdjson::ondemand implementation (stage 2): " << simdjson::builtin_implementation()->name() << std::endl;
} }
} }
@@ -58,10 +58,11 @@ template<typename B, typename R> static void run_json_benchmark(benchmark::State
if (collector.has_events()) { if (collector.has_events()) {
state.counters["instructions"] = events.instructions(); state.counters["instructions"] = events.instructions();
state.counters["cycles"] = events.cycles(); state.counters["cycles"] = events.cycles();
#if !SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
state.counters["branch_miss"] = events.branch_misses(); state.counters["branch_miss"] = events.branch_misses();
state.counters["cache_miss"] = events.cache_misses(); state.counters["cache_miss"] = events.cache_misses();
state.counters["cache_ref"] = events.cache_references(); state.counters["cache_ref"] = events.cache_references();
#endif
state.counters["instructions_per_byte"] = events.instructions() / double(bench.bytes_per_iteration()); state.counters["instructions_per_byte"] = events.instructions() / double(bench.bytes_per_iteration());
state.counters["instructions_per_cycle"] = events.instructions() / events.cycles(); state.counters["instructions_per_cycle"] = events.instructions() / events.cycles();
state.counters["cycles_per_byte"] = events.cycles() / double(bench.bytes_per_iteration()); state.counters["cycles_per_byte"] = events.cycles() / double(bench.bytes_per_iteration());
@@ -69,9 +70,11 @@ template<typename B, typename R> static void run_json_benchmark(benchmark::State
state.counters["best_instructions"] = events.best.instructions(); state.counters["best_instructions"] = events.best.instructions();
state.counters["best_cycles"] = events.best.cycles(); state.counters["best_cycles"] = events.best.cycles();
#if !SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
state.counters["best_branch_miss"] = events.best.branch_misses(); state.counters["best_branch_miss"] = events.best.branch_misses();
state.counters["best_cache_miss"] = events.best.cache_misses(); state.counters["best_cache_miss"] = events.best.cache_misses();
state.counters["best_cache_ref"] = events.best.cache_references(); state.counters["best_cache_ref"] = events.best.cache_references();
#endif
state.counters["best_instructions_per_byte"] = events.best.instructions() / double(bench.bytes_per_iteration()); state.counters["best_instructions_per_byte"] = events.best.instructions() / double(bench.bytes_per_iteration());
state.counters["best_instructions_per_cycle"] = events.best.instructions() / events.best.cycles(); state.counters["best_instructions_per_cycle"] = events.best.instructions() / events.best.cycles();
@@ -92,9 +95,11 @@ template<typename B, typename R> static void run_json_benchmark(benchmark::State
if (collector.has_events()) { if (collector.has_events()) {
label << " instructions=" << setw(12) << uint64_t(events.best.instructions()) << setw(0); label << " instructions=" << setw(12) << uint64_t(events.best.instructions()) << setw(0);
label << " cycles=" << setw(12) << uint64_t(events.best.cycles()) << setw(0); label << " cycles=" << setw(12) << uint64_t(events.best.cycles()) << setw(0);
#if !SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
label << " branch_miss=" << setw(8) << uint64_t(events.best.branch_misses()) << setw(0); label << " branch_miss=" << setw(8) << uint64_t(events.best.branch_misses()) << setw(0);
label << " cache_miss=" << setw(8) << uint64_t(events.best.cache_misses()) << setw(0); label << " cache_miss=" << setw(8) << uint64_t(events.best.cache_misses()) << setw(0);
label << " cache_ref=" << setw(10) << uint64_t(events.best.cache_references()) << setw(0); label << " cache_ref=" << setw(10) << uint64_t(events.best.cache_references()) << setw(0);
#endif
} }
label << " items=" << setw(10) << bench.items_per_iteration() << setw(0); label << " items=" << setw(10) << bench.items_per_iteration() << setw(0);
+1 -1
View File
@@ -79,7 +79,7 @@ static const simdjson::padded_string &get_built_json_array() {
struct simdjson_dom; struct simdjson_dom;
template<typename I> simdjson_really_inline static void kostya(benchmark::State &state) { template<typename I> simdjson_inline static void kostya(benchmark::State &state) {
run_json_benchmark<runner<I>, runner<simdjson_dom>>(state); run_json_benchmark<runner<I>, runner<simdjson_dom>>(state);
} }
+1 -1
View File
@@ -42,7 +42,7 @@ struct nlohmann_json_sax {
return true; return true;
} }
bool number_unsigned(number_unsigned_t val) override { // Need this event because coordinate value can be equal to 1 bool number_unsigned(number_unsigned_t val) override { // Need this event because coordinate value can be equal to 1
buffer[k] = val; buffer[k] = double(val);
if (k == 2) { if (k == 2) {
result.emplace_back(json_benchmark::point{buffer[0],buffer[1],buffer[2]}); result.emplace_back(json_benchmark::point{buffer[0],buffer[1],buffer[2]});
k = 0; k = 0;
+2 -2
View File
@@ -13,7 +13,7 @@ struct rapidjson_base {
Document doc; Document doc;
simdjson_really_inline double get_double(Value &object, std::string_view key) { simdjson_inline double get_double(Value &object, std::string_view key) {
auto field = object.FindMember(key.data()); auto field = object.FindMember(key.data());
if (field == object.MemberEnd()) { throw "Missing double field"; } if (field == object.MemberEnd()) { throw "Missing double field"; }
if (!field->value.IsNumber()) { throw "Field is not double"; } if (!field->value.IsNumber()) { throw "Field is not double"; }
@@ -51,7 +51,7 @@ BENCHMARK_TEMPLATE(kostya, rapidjson_lossless)->UseManualTime();
struct rapidjson_insitu : rapidjson_base { struct rapidjson_insitu : rapidjson_base {
bool run(simdjson::padded_string &json, std::vector<point> &result) { bool run(simdjson::padded_string &json, std::vector<point> &result) {
return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag>(json.data()), result); return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag|kParseInsituFlag>(json.data()), result);
} }
}; };
BENCHMARK_TEMPLATE(kostya, rapidjson_insitu)->UseManualTime(); BENCHMARK_TEMPLATE(kostya, rapidjson_insitu)->UseManualTime();
+2 -1
View File
@@ -11,8 +11,9 @@ struct sajson {
size_t ast_buffer_size{0}; size_t ast_buffer_size{0};
size_t *ast_buffer{nullptr}; size_t *ast_buffer{nullptr};
~sajson() { free(ast_buffer); }
simdjson_really_inline double get_double(const ::sajson::value &obj, std::string_view key) { simdjson_inline double get_double(const ::sajson::value &obj, std::string_view key) {
using namespace sajson; using namespace sajson;
auto val = obj.get_value_of_key({key.data(), key.length()}); auto val = obj.get_value_of_key({key.data(), key.length()});
+1 -1
View File
@@ -9,7 +9,7 @@ namespace kostya {
struct yyjson_base { struct yyjson_base {
static constexpr diff_flags DiffFlags = diff_flags::NONE; static constexpr diff_flags DiffFlags = diff_flags::NONE;
simdjson_really_inline double get_double(yyjson_val *obj, std::string_view key) { simdjson_inline double get_double(yyjson_val *obj, std::string_view key) {
yyjson_val *val = yyjson_obj_getn(obj, key.data(), key.length()); yyjson_val *val = yyjson_obj_getn(obj, key.data(), key.length());
if (!val) { throw "missing point field!"; } if (!val) { throw "missing point field!"; }
if (yyjson_get_type(val) != YYJSON_TYPE_NUM) { throw "Number is not a type!"; } if (yyjson_get_type(val) != YYJSON_TYPE_NUM) { throw "Number is not a type!"; }
@@ -6,6 +6,9 @@
namespace large_amazon_cellphones { namespace large_amazon_cellphones {
const bool UNTHREADED = false;
const bool THREADED = true;
static const simdjson::padded_string &get_built_json(); static const simdjson::padded_string &get_built_json();
using namespace json_benchmark; using namespace json_benchmark;
@@ -13,11 +16,11 @@ using namespace json_benchmark;
struct brand { struct brand {
double cumulative_rating; double cumulative_rating;
uint64_t reviews_count; uint64_t reviews_count;
simdjson_really_inline bool operator==(const brand &other) const { simdjson_inline bool operator==(const brand &other) const {
return cumulative_rating == other.cumulative_rating && return cumulative_rating == other.cumulative_rating &&
reviews_count == other.reviews_count; reviews_count == other.reviews_count;
} }
simdjson_really_inline bool operator!=(const brand &other) const { return !(*this == other); } simdjson_inline bool operator!=(const brand &other) const { return !(*this == other); }
}; };
simdjson_unused static std::ostream &operator<<(std::ostream &o, const brand &b) { simdjson_unused static std::ostream &operator<<(std::ostream &o, const brand &b) {
@@ -81,11 +84,11 @@ static const simdjson::padded_string &get_built_json() {
return json; return json;
} }
template<bool threaded>
struct simdjson_dom; struct simdjson_dom;
template<typename I> simdjson_really_inline static void large_amazon_cellphones(benchmark::State &state) { template<typename I> simdjson_inline static void large_amazon_cellphones(benchmark::State &state) {
run_json_benchmark<runner<I>, runner<simdjson_dom>>(state); run_json_benchmark<runner<I>, runner<simdjson_dom<UNTHREADED>>>(state);
} }
} // namespace large_amazon_cellphones } // namespace large_amazon_cellphones
@@ -9,12 +9,16 @@ namespace large_amazon_cellphones {
using namespace simdjson; using namespace simdjson;
template<bool threaded>
struct simdjson_dom { struct simdjson_dom {
using StringType = std::string; using StringType = std::string;
dom::parser parser{}; dom::parser parser{};
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) { bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
#ifdef SIMDJSON_THREADS_ENABLED
parser.threaded = threaded;
#endif
auto stream = parser.parse_many(json); auto stream = parser.parse_many(json);
auto i = stream.begin(); auto i = stream.begin();
++i; // Skip first line ++i; // Skip first line
@@ -38,7 +42,10 @@ struct simdjson_dom {
}; };
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_dom)->UseManualTime(); BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_dom<UNTHREADED>)->UseManualTime();
#ifdef SIMDJSON_THREADS_ENABLED
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_dom<THREADED>)->UseManualTime();
#endif
} // namespace large_amazon_cellphones } // namespace large_amazon_cellphones
@@ -8,17 +8,21 @@ namespace large_amazon_cellphones {
using namespace simdjson; using namespace simdjson;
template<bool threaded>
struct simdjson_ondemand { struct simdjson_ondemand {
using StringType = std::string; using StringType = std::string;
ondemand::parser parser{}; ondemand::parser parser{};
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) { bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
#ifdef SIMDJSON_THREADS_ENABLED
parser.threaded = threaded;
#endif
ondemand::document_stream stream = parser.iterate_many(json); ondemand::document_stream stream = parser.iterate_many(json);
ondemand::document_stream::iterator i = stream.begin(); ondemand::document_stream::iterator i = stream.begin();
++i; // Skip first line ++i; // Skip first line
for (;i != stream.end(); ++i) { for (;i != stream.end(); ++i) {
auto & doc = *i; auto doc = *i;
size_t index{0}; size_t index{0};
StringType copy; StringType copy;
double rating; double rating;
@@ -58,7 +62,10 @@ struct simdjson_ondemand {
}; };
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_ondemand)->UseManualTime(); BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_ondemand<UNTHREADED>)->UseManualTime();
#ifdef SIMDJSON_THREADS_ENABLED
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_ondemand<THREADED>)->UseManualTime();
#endif
} // namespace amazon_cellphones } // namespace amazon_cellphones
+1 -1
View File
@@ -34,7 +34,7 @@ struct nlohmann_json_sax {
return true; return true;
} }
bool number_unsigned(number_unsigned_t val) override { bool number_unsigned(number_unsigned_t val) override {
buffer[k] = val; buffer[k] = double(val);
if (k == 2) { if (k == 2) {
result.emplace_back(json_benchmark::point{buffer[0],buffer[1],buffer[2]}); result.emplace_back(json_benchmark::point{buffer[0],buffer[1],buffer[2]});
k = 0; k = 0;
+2 -2
View File
@@ -13,7 +13,7 @@ struct rapidjson_base {
Document doc; Document doc;
simdjson_really_inline double get_double(Value &object, std::string_view key) { simdjson_inline double get_double(Value &object, std::string_view key) {
auto field = object.FindMember(key.data()); auto field = object.FindMember(key.data());
if (field == object.MemberEnd()) { throw "Missing double field"; } if (field == object.MemberEnd()) { throw "Missing double field"; }
if (!field->value.IsNumber()) { throw "Field is not double"; } if (!field->value.IsNumber()) { throw "Field is not double"; }
@@ -48,7 +48,7 @@ BENCHMARK_TEMPLATE(large_random, rapidjson_lossless)->UseManualTime();
struct rapidjson_insitu : rapidjson_base { struct rapidjson_insitu : rapidjson_base {
bool run(simdjson::padded_string &json, std::vector<point> &result) { bool run(simdjson::padded_string &json, std::vector<point> &result) {
return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag>(json.data()), result); return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag|kParseInsituFlag>(json.data()), result);
} }
}; };
BENCHMARK_TEMPLATE(large_random, rapidjson_insitu)->UseManualTime(); BENCHMARK_TEMPLATE(large_random, rapidjson_insitu)->UseManualTime();
+2 -1
View File
@@ -11,8 +11,9 @@ struct sajson {
size_t ast_buffer_size{0}; size_t ast_buffer_size{0};
size_t *ast_buffer{nullptr}; size_t *ast_buffer{nullptr};
~sajson() { free(ast_buffer); }
simdjson_really_inline double get_double(const ::sajson::value &obj, std::string_view key) { simdjson_inline double get_double(const ::sajson::value &obj, std::string_view key) {
using namespace sajson; using namespace sajson;
auto val = obj.get_value_of_key({key.data(), key.length()}); auto val = obj.get_value_of_key({key.data(), key.length()});
+1 -1
View File
@@ -9,7 +9,7 @@ namespace large_random {
struct yyjson_base { struct yyjson_base {
static constexpr diff_flags DiffFlags = diff_flags::NONE; static constexpr diff_flags DiffFlags = diff_flags::NONE;
simdjson_really_inline double get_double(yyjson_val *obj, std::string_view key) { simdjson_inline double get_double(yyjson_val *obj, std::string_view key) {
yyjson_val *val = yyjson_obj_getn(obj, key.data(), key.length()); yyjson_val *val = yyjson_obj_getn(obj, key.data(), key.length());
if (!val) { throw "missing point field!"; } if (!val) { throw "missing point field!"; }
if (yyjson_get_type(val) != YYJSON_TYPE_NUM) { throw "Number is not a type!"; } if (yyjson_get_type(val) != YYJSON_TYPE_NUM) { throw "Number is not a type!"; }
+6 -6
View File
@@ -10,28 +10,28 @@ using namespace simdjson;
class Iter { class Iter {
public: public:
simdjson_really_inline bool Run(const padded_string &json); simdjson_inline bool Run(const padded_string &json);
simdjson_really_inline const std::vector<my_point> &Result() { return container; } simdjson_inline const std::vector<my_point> &Result() { return container; }
simdjson_really_inline size_t ItemCount() { return container.size(); } simdjson_inline size_t ItemCount() { return container.size(); }
private: private:
ondemand::parser parser{}; ondemand::parser parser{};
std::vector<my_point> container{}; std::vector<my_point> container{};
simdjson_really_inline double first_double(ondemand::json_iterator &iter) { simdjson_inline double first_double(ondemand::json_iterator &iter) {
if (iter.start_object().error() || iter.field_key().error() || iter.field_value()) { throw "Invalid field"; } if (iter.start_object().error() || iter.field_key().error() || iter.field_value()) { throw "Invalid field"; }
return iter.consume_double(); return iter.consume_double();
} }
simdjson_really_inline double next_double(ondemand::json_iterator &iter) { simdjson_inline double next_double(ondemand::json_iterator &iter) {
if (!iter.has_next_field() || iter.field_key().error() || iter.field_value()) { throw "Invalid field"; } if (!iter.has_next_field() || iter.field_key().error() || iter.field_value()) { throw "Invalid field"; }
return iter.consume_double(); return iter.consume_double();
} }
}; };
simdjson_really_inline bool Iter::Run(const padded_string &json) { simdjson_inline bool Iter::Run(const padded_string &json) {
container.clear(); container.clear();
auto iter = parser.iterate_raw(json).value(); auto iter = parser.iterate_raw(json).value();
+4 -4
View File
@@ -10,16 +10,16 @@ using namespace simdjson;
class OnDemand { class OnDemand {
public: public:
simdjson_really_inline bool Run(const padded_string &json); simdjson_inline bool Run(const padded_string &json);
simdjson_really_inline const std::vector<my_point> &Result() { return container; } simdjson_inline const std::vector<my_point> &Result() { return container; }
simdjson_really_inline size_t ItemCount() { return container.size(); } simdjson_inline size_t ItemCount() { return container.size(); }
private: private:
ondemand::parser parser{}; ondemand::parser parser{};
std::vector<my_point> container{}; std::vector<my_point> container{};
}; };
simdjson_really_inline bool OnDemand::Run(const padded_string &json) { simdjson_inline bool OnDemand::Run(const padded_string &json) {
container.clear(); container.clear();
auto doc = parser.iterate(json); auto doc = parser.iterate(json);
+16 -16
View File
@@ -11,13 +11,13 @@ using namespace simdjson::builtin::stage2;
class Sax { class Sax {
public: public:
simdjson_really_inline bool Run(const padded_string &json) noexcept; simdjson_inline bool Run(const padded_string &json) noexcept;
simdjson_really_inline const std::vector<my_point> &Result() { return container; } simdjson_inline const std::vector<my_point> &Result() { return container; }
simdjson_really_inline size_t ItemCount() { return container.size(); } simdjson_inline size_t ItemCount() { return container.size(); }
private: private:
simdjson_really_inline error_code RunNoExcept(const padded_string &json) noexcept; simdjson_inline error_code RunNoExcept(const padded_string &json) noexcept;
error_code Allocate(size_t new_capacity); error_code Allocate(size_t new_capacity);
std::unique_ptr<uint8_t[]> string_buf{}; std::unique_ptr<uint8_t[]> string_buf{};
size_t capacity{}; size_t capacity{};
@@ -34,21 +34,21 @@ public:
explicit sax_point_reader_visitor(std::vector<my_point> &_points) : points(_points) {} explicit sax_point_reader_visitor(std::vector<my_point> &_points) : points(_points) {}
simdjson_really_inline error_code visit_object_start(json_iterator &) { simdjson_inline error_code visit_object_start(json_iterator &) {
idx = 0; idx = 0;
return SUCCESS; return SUCCESS;
} }
simdjson_really_inline error_code visit_primitive(json_iterator &, const uint8_t *value) { simdjson_inline error_code visit_primitive(json_iterator &, const uint8_t *value) {
if(idx == GOT_SOMETHING_ELSE) { return simdjson::SUCCESS; } if(idx == GOT_SOMETHING_ELSE) { return simdjson::SUCCESS; }
return numberparsing::parse_double(value).get(buffer[idx]); return numberparsing::parse_double(value).get(buffer[idx]);
} }
simdjson_really_inline error_code visit_object_end(json_iterator &) { simdjson_inline error_code visit_object_end(json_iterator &) {
points.emplace_back(my_point{buffer[0], buffer[1], buffer[2]}); points.emplace_back(my_point{buffer[0], buffer[1], buffer[2]});
return SUCCESS; return SUCCESS;
} }
simdjson_really_inline error_code visit_document_start(json_iterator &) { return SUCCESS; } simdjson_inline error_code visit_document_start(json_iterator &) { return SUCCESS; }
simdjson_really_inline error_code visit_key(json_iterator &, const uint8_t * key) { simdjson_inline error_code visit_key(json_iterator &, const uint8_t * key) {
switch(key[1]) { switch(key[1]) {
// Technically, we should check the other characters // Technically, we should check the other characters
// in the key, but we are cheating to go as fast // in the key, but we are cheating to go as fast
@@ -67,13 +67,13 @@ public:
} }
return SUCCESS; return SUCCESS;
} }
simdjson_really_inline error_code visit_array_start(json_iterator &) { return SUCCESS; } simdjson_inline error_code visit_array_start(json_iterator &) { return SUCCESS; }
simdjson_really_inline error_code visit_array_end(json_iterator &) { return SUCCESS; } simdjson_inline error_code visit_array_end(json_iterator &) { return SUCCESS; }
simdjson_really_inline error_code visit_document_end(json_iterator &) { return SUCCESS; } simdjson_inline error_code visit_document_end(json_iterator &) { return SUCCESS; }
simdjson_really_inline error_code visit_empty_array(json_iterator &) { return SUCCESS; } simdjson_inline error_code visit_empty_array(json_iterator &) { return SUCCESS; }
simdjson_really_inline error_code visit_empty_object(json_iterator &) { return SUCCESS; } simdjson_inline error_code visit_empty_object(json_iterator &) { return SUCCESS; }
simdjson_really_inline error_code visit_root_primitive(json_iterator &, const uint8_t *) { return SUCCESS; } simdjson_inline error_code visit_root_primitive(json_iterator &, const uint8_t *) { return SUCCESS; }
simdjson_really_inline error_code increment_count(json_iterator &) { return SUCCESS; } simdjson_inline error_code increment_count(json_iterator &) { return SUCCESS; }
}; };
// NOTE: this assumes the dom_parser is already allocated // NOTE: this assumes the dom_parser is already allocated
+2 -2
View File
@@ -9,7 +9,7 @@ namespace partial_tweets {
struct nlohmann_json { struct nlohmann_json {
using StringType=std::string; using StringType=std::string;
simdjson_really_inline uint64_t nullable_int(nlohmann::json value) { simdjson_inline uint64_t nullable_int(nlohmann::json value) {
if (value.is_null()) { return 0; } if (value.is_null()) { return 0; }
return value; return value;
} }
@@ -37,4 +37,4 @@ BENCHMARK_TEMPLATE(partial_tweets, nlohmann_json)->UseManualTime();
} // namespace partial_tweets } // namespace partial_tweets
#endif // SIMDJSON_COMPETITION_NLOHMANN_JSON #endif // SIMDJSON_COMPETITION_NLOHMANN_JSON
+6 -6
View File
@@ -17,27 +17,27 @@ public:
displayed_implementation = true; displayed_implementation = true;
} }
} }
simdjson_really_inline bool Run(const padded_string &json); simdjson_inline bool Run(const padded_string &json);
simdjson_really_inline const std::vector<tweet> &Result() { return tweets; } simdjson_inline const std::vector<tweet> &Result() { return tweets; }
simdjson_really_inline size_t ItemCount() { return tweets.size(); } simdjson_inline size_t ItemCount() { return tweets.size(); }
private: private:
ondemand::parser parser{}; ondemand::parser parser{};
std::vector<tweet> tweets{}; std::vector<tweet> tweets{};
simdjson_really_inline uint64_t nullable_int(ondemand::value value) { simdjson_inline uint64_t nullable_int(ondemand::value value) {
if (value.is_null()) { return 0; } if (value.is_null()) { return 0; }
return value; return value;
} }
simdjson_really_inline twitter_user read_user(ondemand::object user) { simdjson_inline twitter_user read_user(ondemand::object user) {
return { user.find_field("id"), user.find_field("screen_name") }; return { user.find_field("id"), user.find_field("screen_name") };
} }
static inline bool displayed_implementation = false; static inline bool displayed_implementation = false;
}; };
simdjson_really_inline bool OnDemand::Run(const padded_string &json) { simdjson_inline bool OnDemand::Run(const padded_string &json) {
tweets.clear(); tweets.clear();
// Walk the document, parsing the tweets as we go // Walk the document, parsing the tweets as we go
+1 -1
View File
@@ -39,7 +39,7 @@ struct runner : public file_runner<I> {
struct simdjson_dom; struct simdjson_dom;
template<typename I> simdjson_really_inline static void partial_tweets(benchmark::State &state) { template<typename I> simdjson_inline static void partial_tweets(benchmark::State &state) {
run_json_benchmark<runner<I>, runner<simdjson_dom>>(state); run_json_benchmark<runner<I>, runner<simdjson_dom>>(state);
} }
+5 -5
View File
@@ -13,27 +13,27 @@ struct rapidjson_base {
Document doc{}; Document doc{};
simdjson_really_inline std::string_view get_string_view(Value &object, std::string_view key) { simdjson_inline std::string_view get_string_view(Value &object, std::string_view key) {
// TODO use version that supports passing string length? // TODO use version that supports passing string length?
auto field = object.FindMember(key.data()); auto field = object.FindMember(key.data());
if (field == object.MemberEnd()) { throw "Missing object field"; } if (field == object.MemberEnd()) { throw "Missing object field"; }
if (!field->value.IsString()) { throw "Field is not a string"; } if (!field->value.IsString()) { throw "Field is not a string"; }
return { field->value.GetString(), field->value.GetStringLength() }; return { field->value.GetString(), field->value.GetStringLength() };
} }
simdjson_really_inline uint64_t get_uint64(Value &object, std::string_view key) { simdjson_inline uint64_t get_uint64(Value &object, std::string_view key) {
auto field = object.FindMember(key.data()); auto field = object.FindMember(key.data());
if (field == object.MemberEnd()) { throw "Missing object field"; } if (field == object.MemberEnd()) { throw "Missing object field"; }
if (!field->value.IsUint64()) { throw "Field is not uint64"; } if (!field->value.IsUint64()) { throw "Field is not uint64"; }
return field->value.GetUint64(); return field->value.GetUint64();
} }
simdjson_really_inline uint64_t get_nullable_uint64(Value &object, std::string_view key) { simdjson_inline uint64_t get_nullable_uint64(Value &object, std::string_view key) {
auto field = object.FindMember(key.data()); auto field = object.FindMember(key.data());
if (field == object.MemberEnd()) { throw "Missing nullable uint64 field"; } if (field == object.MemberEnd()) { throw "Missing nullable uint64 field"; }
if (field->value.IsNull()) { return 0; } if (field->value.IsNull()) { return 0; }
if (!field->value.IsUint64()) { throw "Field is not nullable uint64"; } if (!field->value.IsUint64()) { throw "Field is not nullable uint64"; }
return field->value.GetUint64(); return field->value.GetUint64();
} }
simdjson_really_inline partial_tweets::twitter_user<std::string_view> get_user(Value &object, std::string_view key) { simdjson_inline partial_tweets::twitter_user<std::string_view> get_user(Value &object, std::string_view key) {
auto field = object.FindMember(key.data()); auto field = object.FindMember(key.data());
if (field == object.MemberEnd()) { throw "Missing user field"; } if (field == object.MemberEnd()) { throw "Missing user field"; }
if (!field->value.IsObject()) { throw "User field is not an object"; } if (!field->value.IsObject()) { throw "User field is not an object"; }
@@ -70,7 +70,7 @@ BENCHMARK_TEMPLATE(partial_tweets, rapidjson)->UseManualTime();
struct rapidjson_insitu : rapidjson_base { struct rapidjson_insitu : rapidjson_base {
bool run(simdjson::padded_string &json, std::vector<tweet<std::string_view>> &result) { bool run(simdjson::padded_string &json, std::vector<tweet<std::string_view>> &result) {
return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag>(json.data()), result); return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag|kParseInsituFlag>(json.data()), result);
} }
}; };
BENCHMARK_TEMPLATE(partial_tweets, rapidjson_insitu)->UseManualTime(); BENCHMARK_TEMPLATE(partial_tweets, rapidjson_insitu)->UseManualTime();
+7 -5
View File
@@ -11,12 +11,14 @@ struct sajson {
size_t ast_buffer_size{0}; size_t ast_buffer_size{0};
size_t *ast_buffer{nullptr}; size_t *ast_buffer{nullptr};
simdjson_really_inline std::string_view get_string_view(const ::sajson::value &obj, std::string_view key) { ~sajson() { free(ast_buffer); }
simdjson_inline std::string_view get_string_view(const ::sajson::value &obj, std::string_view key) {
auto val = obj.get_value_of_key({key.data(), key.length()}); auto val = obj.get_value_of_key({key.data(), key.length()});
if (val.get_type() != ::sajson::TYPE_STRING) { throw "field is not a string"; } if (val.get_type() != ::sajson::TYPE_STRING) { throw "field is not a string"; }
return { val.as_cstring(), val.get_string_length() }; return { val.as_cstring(), val.get_string_length() };
} }
simdjson_really_inline uint64_t get_uint52(const ::sajson::value &obj, std::string_view key) { simdjson_inline uint64_t get_uint52(const ::sajson::value &obj, std::string_view key) {
auto val = obj.get_value_of_key({key.data(), key.length()}); auto val = obj.get_value_of_key({key.data(), key.length()});
switch (val.get_type()) { switch (val.get_type()) {
case ::sajson::TYPE_INTEGER: { case ::sajson::TYPE_INTEGER: {
@@ -28,7 +30,7 @@ struct sajson {
throw "field not integer"; throw "field not integer";
} }
} }
simdjson_really_inline uint64_t get_str_uint64(const ::sajson::value &obj, std::string_view key) { simdjson_inline uint64_t get_str_uint64(const ::sajson::value &obj, std::string_view key) {
// Since sajson only supports 53-bit numbers, and IDs in twitter.json can be > 53 bits, we read the corresponding id_str and parse that. // Since sajson only supports 53-bit numbers, and IDs in twitter.json can be > 53 bits, we read the corresponding id_str and parse that.
auto val = obj.get_value_of_key({key.data(), key.length()}); auto val = obj.get_value_of_key({key.data(), key.length()});
if (val.get_type() != ::sajson::TYPE_STRING) { throw "field not a string"; } if (val.get_type() != ::sajson::TYPE_STRING) { throw "field not a string"; }
@@ -38,7 +40,7 @@ struct sajson {
if (endptr != &str[val.get_string_length()]) { throw "field is a string, but not an integer string"; } if (endptr != &str[val.get_string_length()]) { throw "field is a string, but not an integer string"; }
return result; return result;
} }
simdjson_really_inline uint64_t get_nullable_str_uint64(const ::sajson::value &obj, std::string_view key) { simdjson_inline uint64_t get_nullable_str_uint64(const ::sajson::value &obj, std::string_view key) {
auto val = obj.get_value_of_key({key.data(), key.length()}); auto val = obj.get_value_of_key({key.data(), key.length()});
if (val.get_type() == ::sajson::TYPE_NULL) { return 0; } if (val.get_type() == ::sajson::TYPE_NULL) { return 0; }
if (val.get_type() != ::sajson::TYPE_STRING) { throw "field not a string"; } if (val.get_type() != ::sajson::TYPE_STRING) { throw "field not a string"; }
@@ -48,7 +50,7 @@ struct sajson {
if (endptr != &str[val.get_string_length()]) { throw "field is a string, but not an integer string"; } if (endptr != &str[val.get_string_length()]) { throw "field is a string, but not an integer string"; }
return result; return result;
} }
simdjson_really_inline partial_tweets::twitter_user<std::string_view> get_user(const ::sajson::value &obj, std::string_view key) { simdjson_inline partial_tweets::twitter_user<std::string_view> get_user(const ::sajson::value &obj, std::string_view key) {
auto user = obj.get_value_of_key({key.data(), key.length()}); auto user = obj.get_value_of_key({key.data(), key.length()});
if (user.get_type() != ::sajson::TYPE_OBJECT) { throw "user is not an object"; } if (user.get_type() != ::sajson::TYPE_OBJECT) { throw "user is not an object"; }
return { get_str_uint64(user, "id_str"), get_string_view(user, "screen_name") }; return { get_str_uint64(user, "id_str"), get_string_view(user, "screen_name") };
+2 -2
View File
@@ -13,7 +13,7 @@ struct simdjson_dom {
dom::parser parser{}; dom::parser parser{};
simdjson_really_inline uint64_t nullable_int(dom::element element) { simdjson_inline uint64_t nullable_int(dom::element element) {
if (element.is_null()) { return 0; } if (element.is_null()) { return 0; }
return element; return element;
} }
@@ -40,4 +40,4 @@ BENCHMARK_TEMPLATE(partial_tweets, simdjson_dom)->UseManualTime();
} // namespace partial_tweets } // namespace partial_tweets
#endif // SIMDJSON_EXCEPTIONS #endif // SIMDJSON_EXCEPTIONS
+2 -2
View File
@@ -13,12 +13,12 @@ struct simdjson_ondemand {
ondemand::parser parser{}; ondemand::parser parser{};
simdjson_really_inline uint64_t nullable_int(ondemand::value value) { simdjson_inline uint64_t nullable_int(ondemand::value value) {
if (value.is_null()) { return 0; } if (value.is_null()) { return 0; }
return value; return value;
} }
simdjson_really_inline twitter_user<std::string_view> read_user(ondemand::object user) { simdjson_inline twitter_user<std::string_view> read_user(ondemand::object user) {
return { user.find_field("id"), user.find_field("screen_name") }; return { user.find_field("id"), user.find_field("screen_name") };
} }
+2 -2
View File
@@ -32,7 +32,7 @@ struct tweet {
uint64_t retweet_count{}; uint64_t retweet_count{};
uint64_t favorite_count{}; uint64_t favorite_count{};
template<typename OtherStringType> template<typename OtherStringType>
simdjson_really_inline bool operator==(const tweet<OtherStringType> &other) const { simdjson_inline bool operator==(const tweet<OtherStringType> &other) const {
return created_at == other.created_at && return created_at == other.created_at &&
id == other.id && id == other.id &&
result == other.result && result == other.result &&
@@ -42,7 +42,7 @@ struct tweet {
favorite_count == other.favorite_count; favorite_count == other.favorite_count;
} }
template<typename OtherStringType> template<typename OtherStringType>
simdjson_really_inline bool operator!=(const tweet<OtherStringType> &other) const { return !(*this == other); } simdjson_inline bool operator!=(const tweet<OtherStringType> &other) const { return !(*this == other); }
}; };
template<typename StringType> template<typename StringType>
+4 -4
View File
@@ -9,24 +9,24 @@ namespace partial_tweets {
struct yyjson_base { struct yyjson_base {
using StringType=std::string_view; using StringType=std::string_view;
simdjson_really_inline std::string_view get_string_view(yyjson_val *obj, std::string_view key) { simdjson_inline std::string_view get_string_view(yyjson_val *obj, std::string_view key) {
auto val = yyjson_obj_getn(obj, key.data(), key.length()); auto val = yyjson_obj_getn(obj, key.data(), key.length());
if (!yyjson_is_str(val)) { throw "field is not uint64 or null!"; } if (!yyjson_is_str(val)) { throw "field is not uint64 or null!"; }
return { yyjson_get_str(val), yyjson_get_len(val) }; return { yyjson_get_str(val), yyjson_get_len(val) };
} }
simdjson_really_inline uint64_t get_uint64(yyjson_val *obj, std::string_view key) { simdjson_inline uint64_t get_uint64(yyjson_val *obj, std::string_view key) {
auto val = yyjson_obj_getn(obj, key.data(), key.length()); auto val = yyjson_obj_getn(obj, key.data(), key.length());
if (!yyjson_is_uint(val)) { throw "field is not uint64 or null!"; } if (!yyjson_is_uint(val)) { throw "field is not uint64 or null!"; }
return yyjson_get_uint(val); return yyjson_get_uint(val);
} }
simdjson_really_inline uint64_t get_nullable_uint64(yyjson_val *obj, std::string_view key) { simdjson_inline uint64_t get_nullable_uint64(yyjson_val *obj, std::string_view key) {
auto val = yyjson_obj_getn(obj, key.data(), key.length()); auto val = yyjson_obj_getn(obj, key.data(), key.length());
if (!yyjson_is_uint(val)) { } if (!yyjson_is_uint(val)) { }
auto type = yyjson_get_type(val); auto type = yyjson_get_type(val);
if (type != YYJSON_TYPE_NUM && type != YYJSON_TYPE_NULL ) { throw "field is not uint64 or null!"; } if (type != YYJSON_TYPE_NUM && type != YYJSON_TYPE_NULL ) { throw "field is not uint64 or null!"; }
return yyjson_get_uint(val); return yyjson_get_uint(val);
} }
simdjson_really_inline partial_tweets::twitter_user<std::string_view> get_user(yyjson_val *obj, std::string_view key) { simdjson_inline partial_tweets::twitter_user<std::string_view> get_user(yyjson_val *obj, std::string_view key) {
auto user = yyjson_obj_getn(obj, key.data(), key.length()); auto user = yyjson_obj_getn(obj, key.data(), key.length());
if (!yyjson_is_obj(user)) { throw "missing twitter user field!"; } if (!yyjson_is_obj(user)) { throw "missing twitter user field!"; }
return { get_uint64(user, "id"), get_string_view(user, "screen_name") }; return { get_uint64(user, "id"), get_string_view(user, "screen_name") };
+1 -1
View File
@@ -48,7 +48,7 @@ struct nlohmann_json_sax {
} }
bool number_unsigned(number_unsigned_t val) override { bool number_unsigned(number_unsigned_t val) override {
if (values & key_rt && !(values & found_rt)) { // retweet_count if (values & key_rt && !(values & found_rt)) { // retweet_count
rt = val; rt = int(val);
values &= ~(key_rt); values &= ~(key_rt);
values |= (found_rt); values |= (found_rt);
if (rt <= max_rt && rt >= result.retweet_count) { // Check if current tweet has more retweet than previous top tweet if (rt <= max_rt && rt >= result.retweet_count) { // Check if current tweet has more retweet than previous top tweet
+1 -1
View File
@@ -59,7 +59,7 @@ BENCHMARK_TEMPLATE(top_tweet, rapidjson)->UseManualTime();
struct rapidjson_insitu : rapidjson_base { struct rapidjson_insitu : rapidjson_base {
bool run(simdjson::padded_string &json, int64_t max_retweet_count, top_tweet_result<StringType> &result) { bool run(simdjson::padded_string &json, int64_t max_retweet_count, top_tweet_result<StringType> &result) {
return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag>(json.data()), max_retweet_count, result); return rapidjson_base::run(doc.ParseInsitu<kParseValidateEncodingFlag|kParseInsituFlag>(json.data()), max_retweet_count, result);
} }
}; };
BENCHMARK_TEMPLATE(top_tweet, rapidjson_insitu)->UseManualTime(); BENCHMARK_TEMPLATE(top_tweet, rapidjson_insitu)->UseManualTime();
+1
View File
@@ -11,6 +11,7 @@ struct sajson {
size_t ast_buffer_size{0}; size_t ast_buffer_size{0};
size_t *ast_buffer{nullptr}; size_t *ast_buffer{nullptr};
~sajson() { free(ast_buffer); }
bool run(simdjson::padded_string &json, int32_t max_retweet_count, top_tweet_result<StringType> &result) { bool run(simdjson::padded_string &json, int32_t max_retweet_count, top_tweet_result<StringType> &result) {
if (!ast_buffer) { if (!ast_buffer) {
+3 -3
View File
@@ -13,13 +13,13 @@ struct top_tweet_result {
StringType screen_name{}; StringType screen_name{};
StringType text{}; StringType text{};
template<typename OtherStringType> template<typename OtherStringType>
simdjson_really_inline bool operator==(const top_tweet_result<OtherStringType> &other) const { simdjson_inline bool operator==(const top_tweet_result<OtherStringType> &other) const {
return retweet_count == other.retweet_count && return retweet_count == other.retweet_count &&
screen_name == other.screen_name && screen_name == other.screen_name &&
text == other.text; text == other.text;
} }
template<typename OtherStringType> template<typename OtherStringType>
simdjson_really_inline bool operator!=(const top_tweet_result<OtherStringType> &other) const { return !(*this == other); } simdjson_inline bool operator!=(const top_tweet_result<OtherStringType> &other) const { return !(*this == other); }
}; };
template<typename StringType> template<typename StringType>
@@ -60,7 +60,7 @@ struct runner : public file_runner<I> {
struct simdjson_dom; struct simdjson_dom;
template<typename I> simdjson_really_inline static void top_tweet(benchmark::State &state) { template<typename I> simdjson_inline static void top_tweet(benchmark::State &state) {
json_benchmark::run_json_benchmark<runner<I>, runner<simdjson_dom>>(state); json_benchmark::run_json_benchmark<runner<I>, runner<simdjson_dom>>(state);
} }
+18
View File
@@ -3,6 +3,12 @@
# #
add_library(simdjson-internal-flags INTERFACE) add_library(simdjson-internal-flags INTERFACE)
option(SIMDJSON_CHECK_EOF "Check for the end of the input buffer. The setting is unnecessary since we require padding of the inputs. You should expect tests to fail with this option turned on." OFF)
if(SIMDJSON_CHECK_EOF)
add_compile_definitions(SIMDJSON_CHECK_EOF=1)
endif()
option(SIMDJSON_SANITIZE_UNDEFINED "Sanitize undefined behavior" OFF) option(SIMDJSON_SANITIZE_UNDEFINED "Sanitize undefined behavior" OFF)
if(SIMDJSON_SANITIZE_UNDEFINED) if(SIMDJSON_SANITIZE_UNDEFINED)
add_compile_options(-fsanitize=undefined -fno-sanitize-recover=all) add_compile_options(-fsanitize=undefined -fno-sanitize-recover=all)
@@ -169,6 +175,18 @@ if(CMAKE_C_COMPILER_ID MATCHES "Intel")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-intel")
endif() endif()
option(
SIMDJSON_AVX512_ALLOWED
"Enable AVX-512 instructions (only affects processors and compilers with AVX-512 support)."
ON
)
if(SIMDJSON_AVX512_ALLOWED)
add_compile_definitions(SIMDJSON_AVX512_ALLOWED=1)
else()
add_compile_definitions(SIMDJSON_AVX512_ALLOWED=0)
message(STATUS "AVX-512 instructions are not allowed.")
endif()
include(CheckSymbolExists) include(CheckSymbolExists)
check_symbol_exists(fork unistd.h HAVE_POSIX_FORK) check_symbol_exists(fork unistd.h HAVE_POSIX_FORK)
check_symbol_exists(wait sys/wait.h HAVE_POSIX_WAIT) check_symbol_exists(wait sys/wait.h HAVE_POSIX_WAIT)
+2 -2
View File
@@ -1,7 +1,7 @@
# #
# Implementation selection # Implementation selection
# #
set(SIMDJSON_ALL_IMPLEMENTATIONS fallback westmere haswell arm64 ppc64) set(SIMDJSON_ALL_IMPLEMENTATIONS fallback westmere haswell icelake arm64 ppc64)
set( set(
SIMDJSON_IMPLEMENTATION "" SIMDJSON_IMPLEMENTATION ""
@@ -15,7 +15,7 @@ set(
SIMDJSON_EXCLUDE_IMPLEMENTATION "" SIMDJSON_EXCLUDE_IMPLEMENTATION ""
CACHE STRING "\ CACHE STRING "\
Semicolon-separated list of implementations to exclude \ Semicolon-separated list of implementations to exclude \
(haswell/westmere/arm64/ppc64/fallback). By default, excludes any \ (icelake/haswell/westmere/arm64/ppc64/fallback). By default, excludes any \
implementations that are unsupported at compile time or cannot be selected at \ implementations that are unsupported at compile time or cannot be selected at \
runtime." runtime."
) )
+4 -3
View File
@@ -13,8 +13,9 @@ cmake_dependent_option(SIMDJSON_GOOGLE_BENCHMARKS "compile the Google Benchmark
if(SIMDJSON_GOOGLE_BENCHMARKS) if(SIMDJSON_GOOGLE_BENCHMARKS)
set_off(BENCHMARK_ENABLE_TESTING) set_off(BENCHMARK_ENABLE_TESTING)
set_off(BENCHMARK_ENABLE_INSTALL) set_off(BENCHMARK_ENABLE_INSTALL)
set_off(BENCHMARK_ENABLE_WERROR)
import_dependency(google_benchmarks google/benchmark 8982e1e) import_dependency(google_benchmarks google/benchmark f91b6b4)
add_dependency(google_benchmarks) add_dependency(google_benchmarks)
endif() endif()
@@ -69,11 +70,11 @@ int main() {}
target_include_directories(jsmn SYSTEM PUBLIC "${jsmn_SOURCE_DIR}") target_include_directories(jsmn SYSTEM PUBLIC "${jsmn_SOURCE_DIR}")
target_compile_definitions(jsmn INTERFACE SIMDJSON_COMPETITION_JSMN) target_compile_definitions(jsmn INTERFACE SIMDJSON_COMPETITION_JSMN)
message(STATUS "Importing json (nlohmann/json@v3.9.1)") message(STATUS "Importing json (nlohmann/json@v3.10.5)")
set(nlohmann_json_SOURCE_DIR "${dep_root}/json") set(nlohmann_json_SOURCE_DIR "${dep_root}/json")
if(NOT EXISTS "${nlohmann_json_SOURCE_DIR}") if(NOT EXISTS "${nlohmann_json_SOURCE_DIR}")
file(DOWNLOAD file(DOWNLOAD
"https://github.com/nlohmann/json/releases/download/v3.9.1/json.hpp" "https://github.com/nlohmann/json/releases/download/v3.10.5/json.hpp"
"${nlohmann_json_SOURCE_DIR}/nlohmann/json.hpp") "${nlohmann_json_SOURCE_DIR}/nlohmann/json.hpp")
endif() endif()
add_library(nlohmann_json INTERFACE) add_library(nlohmann_json INTERFACE)
+192 -90
View File
@@ -79,6 +79,150 @@ license you like.
/// to prevent private header inclusion. /// to prevent private header inclusion.
#define JSON_IS_AMALGAMATION #define JSON_IS_AMALGAMATION
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/version.h
// //////////////////////////////////////////////////////////////////////
#ifndef JSON_VERSION_H_INCLUDED
#define JSON_VERSION_H_INCLUDED
// Note: version must be updated in three places when doing a release. This
// annoying process ensures that amalgamate, CMake, and meson all report the
// correct version.
// 1. /meson.build
// 2. /include/json/version.h
// 3. /CMakeLists.txt
// IMPORTANT: also update the SOVERSION!!
#define JSONCPP_VERSION_STRING "1.9.5"
#define JSONCPP_VERSION_MAJOR 1
#define JSONCPP_VERSION_MINOR 9
#define JSONCPP_VERSION_PATCH 5
#define JSONCPP_VERSION_QUALIFIER
#define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
(JSONCPP_VERSION_PATCH << 8))
#ifdef JSONCPP_USING_SECURE_MEMORY
#undef JSONCPP_USING_SECURE_MEMORY
#endif
#define JSONCPP_USING_SECURE_MEMORY 0
// If non-zero, the library zeroes any memory that it has allocated before
// it frees its memory.
#endif // JSON_VERSION_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
// End of content of file: include/json/version.h
// //////////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/allocator.h
// //////////////////////////////////////////////////////////////////////
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_ALLOCATOR_H_INCLUDED
#define JSON_ALLOCATOR_H_INCLUDED
#include <cstring>
#include <memory>
#pragma pack(push, 8)
namespace Json {
template <typename T> class SecureAllocator {
public:
// Type definitions
using value_type = T;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
/**
* Allocate memory for N items using the standard allocator.
*/
pointer allocate(size_type n) {
// allocate using "global operator new"
return static_cast<pointer>(::operator new(n * sizeof(T)));
}
/**
* Release memory which was allocated for N items at pointer P.
*
* The memory block is filled with zeroes before being released.
*/
void deallocate(pointer p, size_type n) {
// memset_s is used because memset may be optimized away by the compiler
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
// free using "global operator delete"
::operator delete(p);
}
/**
* Construct an item in-place at pointer P.
*/
template <typename... Args> void construct(pointer p, Args&&... args) {
// construct using "placement new" and "perfect forwarding"
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
}
size_type max_size() const { return size_t(-1) / sizeof(T); }
pointer address(reference x) const { return std::addressof(x); }
const_pointer address(const_reference x) const { return std::addressof(x); }
/**
* Destroy an item in-place at pointer P.
*/
void destroy(pointer p) {
// destroy using "explicit destructor"
p->~T();
}
// Boilerplate
SecureAllocator() {}
template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
template <typename U> struct rebind { using other = SecureAllocator<U>; };
};
template <typename T, typename U>
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
return true;
}
template <typename T, typename U>
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
return false;
}
} // namespace Json
#pragma pack(pop)
#endif // JSON_ALLOCATOR_H_INCLUDED
// //////////////////////////////////////////////////////////////////////
// End of content of file: include/json/allocator.h
// //////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////
// Beginning of content of file: include/json/config.h // Beginning of content of file: include/json/config.h
// ////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////
@@ -99,47 +243,38 @@ license you like.
#include <string> #include <string>
#include <type_traits> #include <type_traits>
/// If defined, indicates that json library is embedded in CppTL library.
//# define JSON_IN_CPPTL 1
/// If defined, indicates that json may leverage CppTL library
//# define JSON_USE_CPPTL 1
/// If defined, indicates that cpptl vector based map should be used instead of
/// std::map
/// as Value container.
//# define JSON_USE_CPPTL_SMALLMAP 1
// If non-zero, the library uses exceptions to report bad input instead of C // If non-zero, the library uses exceptions to report bad input instead of C
// assertion macros. The default is to use exceptions. // assertion macros. The default is to use exceptions.
#ifndef JSON_USE_EXCEPTION #ifndef JSON_USE_EXCEPTION
#define JSON_USE_EXCEPTION 1 #define JSON_USE_EXCEPTION 1
#endif #endif
// Temporary, tracked for removal with issue #982.
#ifndef JSON_USE_NULLREF
#define JSON_USE_NULLREF 1
#endif
/// If defined, indicates that the source file is amalgamated /// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion. /// to prevent private header inclusion.
/// Remarks: it is automatically defined in the generated amalgamated header. /// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION // #define JSON_IS_AMALGAMATION
#ifdef JSON_IN_CPPTL // Export macros for DLL visibility
#include <cpptl/config.h> #if defined(JSON_DLL_BUILD)
#ifndef JSON_USE_CPPTL
#define JSON_USE_CPPTL 1
#endif
#endif
#ifdef JSON_IN_CPPTL
#define JSON_API CPPTL_API
#elif defined(JSON_DLL_BUILD)
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllexport) #define JSON_API __declspec(dllexport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#elif defined(__GNUC__) || defined(__clang__)
#define JSON_API __attribute__((visibility("default")))
#endif // if defined(_MSC_VER) #endif // if defined(_MSC_VER)
#elif defined(JSON_DLL) #elif defined(JSON_DLL)
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllimport) #define JSON_API __declspec(dllimport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER) #endif // if defined(_MSC_VER)
#endif // ifdef JSON_IN_CPPTL #endif // ifdef JSON_DLL_BUILD
#if !defined(JSON_API) #if !defined(JSON_API)
#define JSON_API #define JSON_API
#endif #endif
@@ -152,8 +287,8 @@ license you like.
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
// As recommended at // As recommended at
// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 // https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
extern JSON_API int extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
msvc_pre1900_c99_snprintf(char* outBuf, size_t size, const char* format, ...); const char* format, ...);
#define jsoncpp_snprintf msvc_pre1900_c99_snprintf #define jsoncpp_snprintf msvc_pre1900_c99_snprintf
#else #else
#define jsoncpp_snprintf std::snprintf #define jsoncpp_snprintf std::snprintf
@@ -164,69 +299,30 @@ msvc_pre1900_c99_snprintf(char* outBuf, size_t size, const char* format, ...);
// Storages, and 64 bits integer support is disabled. // Storages, and 64 bits integer support is disabled.
// #define JSON_NO_INT64 1 // #define JSON_NO_INT64 1
#if defined(_MSC_VER) // MSVC
#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
#endif // defined(_MSC_VER)
// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools. // JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
// C++11 should be used directly in JSONCPP. // C++11 should be used directly in JSONCPP.
#define JSONCPP_OVERRIDE override #define JSONCPP_OVERRIDE override
#if __cplusplus >= 201103L
#define JSONCPP_NOEXCEPT noexcept
#define JSONCPP_OP_EXPLICIT explicit
#elif defined(_MSC_VER) && _MSC_VER < 1900
#define JSONCPP_NOEXCEPT throw()
#define JSONCPP_OP_EXPLICIT explicit
#elif defined(_MSC_VER) && _MSC_VER >= 1900
#define JSONCPP_NOEXCEPT noexcept
#define JSONCPP_OP_EXPLICIT explicit
#else
#define JSONCPP_NOEXCEPT throw()
#define JSONCPP_OP_EXPLICIT
#endif
#ifndef JSON_HAS_RVALUE_REFERENCES
#if defined(_MSC_VER)
#define JSON_HAS_RVALUE_REFERENCES 1
#endif // MSVC >= 2013
#ifdef __clang__
#if __has_feature(cxx_rvalue_references)
#define JSON_HAS_RVALUE_REFERENCES 1
#endif // has_feature
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
#define JSON_HAS_RVALUE_REFERENCES 1
#endif // GXX_EXPERIMENTAL
#endif // __clang__ || __GNUC__
#endif // not defined JSON_HAS_RVALUE_REFERENCES
#ifndef JSON_HAS_RVALUE_REFERENCES
#define JSON_HAS_RVALUE_REFERENCES 0
#endif
#ifdef __clang__ #ifdef __clang__
#if __has_extension(attribute_deprecated_with_message) #if __has_extension(attribute_deprecated_with_message)
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
#endif #endif
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc) #elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)) #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) #elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__)) #define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
#endif // GNUC version #endif // GNUC version
#endif // __clang__ || __GNUC__ #elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates
// MSVC)
#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
#endif // __clang__ || __GNUC__ || _MSC_VER
#if !defined(JSONCPP_DEPRECATED) #if !defined(JSONCPP_DEPRECATED)
#define JSONCPP_DEPRECATED(message) #define JSONCPP_DEPRECATED(message)
#endif // if !defined(JSONCPP_DEPRECATED) #endif // if !defined(JSONCPP_DEPRECATED)
#if __GNUC__ >= 6 #if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
#define JSON_USE_INT64_DOUBLE_CONVERSION 1 #define JSON_USE_INT64_DOUBLE_CONVERSION 1
#endif #endif
@@ -238,37 +334,37 @@ msvc_pre1900_c99_snprintf(char* outBuf, size_t size, const char* format, ...);
#endif // if !defined(JSON_IS_AMALGAMATION) #endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json { namespace Json {
typedef int Int; using Int = int;
typedef unsigned int UInt; using UInt = unsigned int;
#if defined(JSON_NO_INT64) #if defined(JSON_NO_INT64)
typedef int LargestInt; using LargestInt = int;
typedef unsigned int LargestUInt; using LargestUInt = unsigned int;
#undef JSON_HAS_INT64 #undef JSON_HAS_INT64
#else // if defined(JSON_NO_INT64) #else // if defined(JSON_NO_INT64)
// For Microsoft Visual use specific types as long long is not supported // For Microsoft Visual use specific types as long long is not supported
#if defined(_MSC_VER) // Microsoft Visual Studio #if defined(_MSC_VER) // Microsoft Visual Studio
typedef __int64 Int64; using Int64 = __int64;
typedef unsigned __int64 UInt64; using UInt64 = unsigned __int64;
#else // if defined(_MSC_VER) // Other platforms, use long long #else // if defined(_MSC_VER) // Other platforms, use long long
typedef int64_t Int64; using Int64 = int64_t;
typedef uint64_t UInt64; using UInt64 = uint64_t;
#endif // if defined(_MSC_VER) #endif // if defined(_MSC_VER)
typedef Int64 LargestInt; using LargestInt = Int64;
typedef UInt64 LargestUInt; using LargestUInt = UInt64;
#define JSON_HAS_INT64 #define JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64) #endif // if defined(JSON_NO_INT64)
template <typename T> template <typename T>
using Allocator = typename std::conditional<JSONCPP_USING_SECURE_MEMORY, using Allocator =
SecureAllocator<T>, typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
std::allocator<T>>::type; std::allocator<T>>::type;
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>; using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
using IStringStream = std::basic_istringstream<String::value_type, using IStringStream =
String::traits_type, std::basic_istringstream<String::value_type, String::traits_type,
String::allocator_type>; String::allocator_type>;
using OStringStream = std::basic_ostringstream<String::value_type, using OStringStream =
String::traits_type, std::basic_ostringstream<String::value_type, String::traits_type,
String::allocator_type>; String::allocator_type>;
using IStream = std::istream; using IStream = std::istream;
using OStream = std::ostream; using OStream = std::ostream;
} // namespace Json } // namespace Json
@@ -310,17 +406,23 @@ using JSONCPP_OSTREAM = Json::OStream;
namespace Json { namespace Json {
// writer.h // writer.h
class StreamWriter;
class StreamWriterBuilder;
class Writer;
class FastWriter; class FastWriter;
class StyledWriter; class StyledWriter;
class StyledStreamWriter;
// reader.h // reader.h
class Reader; class Reader;
class CharReader;
class CharReaderBuilder;
// features.h // json_features.h
class Features; class Features;
// value.h // value.h
typedef unsigned int ArrayIndex; using ArrayIndex = unsigned int;
class StaticString; class StaticString;
class Path; class Path;
class PathArgument; class PathArgument;
+541 -561
View File
File diff suppressed because it is too large Load Diff
+508 -604
View File
File diff suppressed because it is too large Load Diff
+843 -365
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -1,3 +1,5 @@
We take our documentation seriously. Please start reading the documentation before you attempt to use simdjson. We hope you will enjoy reading us.
* Basics: https://github.com/simdjson/simdjson/blob/master/doc/basics.md is an overview of how to use simdjson and its APIs. * Basics: https://github.com/simdjson/simdjson/blob/master/doc/basics.md is an overview of how to use simdjson and its APIs.
* parse_many: https://github.com/simdjson/simdjson/blob/master/doc/parse_many.md describes an interface providing features to work with files or streams containing multiple small JSON documents. As fast and convenient as possible. * parse_many: https://github.com/simdjson/simdjson/blob/master/doc/parse_many.md describes an interface providing features to work with files or streams containing multiple small JSON documents. As fast and convenient as possible.
* Performance: https://github.com/simdjson/simdjson/blob/master/doc/performance.md shows some more advanced scenarios and how to tune for them. * Performance: https://github.com/simdjson/simdjson/blob/master/doc/performance.md shows some more advanced scenarios and how to tune for them.

Some files were not shown because too many files have changed in this diff Show More