Compare commits

...

285 Commits

Author SHA1 Message Date
Daniel Lemire 15e378af3c Adding explicit popcnt 2023-06-05 08:59:36 -04:00
Daniel Lemire fbc9b7e3fb Tweaking. 2023-05-12 16:36:21 -04:00
Daniel Lemire 1b5a9267d6 Checking if the OS supports AVX-512 2023-05-12 14:32:09 -04:00
Daniel Lemire e3c795072c Fixing include 2023-05-05 22:28:58 -04:00
Daniel Lemire fb98cbdb3a Merge branch 'master' into dlemire/support 2023-05-05 22:13:39 -04:00
Daniel Lemire 21a2ccaeb8 Another fun one 2023-05-05 22:12:59 -04:00
Daniel Lemire b98883b5ae Setting the variable to zero. 2023-05-05 22:05:04 -04:00
Daniel Lemire d39ef515a0 Minor fix 2023-05-05 21:55:28 -04:00
Daniel Lemire 6cbb6ac89b On ARM processors, rapidjson may struggle. Let us help it out. (#1996) 2023-05-05 21:42:37 -04:00
Daniel Lemire 5bbf124690 Fix. 2023-05-05 18:44:28 -04:00
Daniel Lemire f51a32ebcd Fix. 2023-05-05 18:05:55 -04:00
Daniel Lemire e9b943bf32 Adding support for AVX-512 on macOS. 2023-05-05 18:02:21 -04:00
Dirk Stolle e9f0f1bb9b Mention IceLake in documentation about implementation selection. (#1995)
Since the creation of the IceLake implementation there are now
four available implementations on Intel/AMD x64 processors.
2023-04-28 21:29:01 -04:00
Serge Aleynikov 7ef1ebd4fb Add Erlang bindings (#1994) 2023-04-28 09:54:49 -04:00
Daniel Lemire 8de540e267 Update README.md 2023-04-27 14:27:05 -04:00
Daniel Lemire ebc51fbd1a Update bug_report.md 2023-04-24 08:05:26 -04:00
Daniel Lemire 84a31c1615 Update bug_report.md 2023-04-23 12:06:47 -04:00
Daniel Lemire f77ac963f4 Trying the undefined behaviour sanitizer (#1988)
* Trying the undefined behaviour sanitizer

* Trimming quiet
2023-04-23 11:50:05 -04:00
pjuhasz ae3d912f8d Add link to Perl binding (JSON::SIMD) (#1991)
Co-authored-by: Peter Juhasz <juhasz.peter@uhusystems.com>
2023-04-23 10:37:56 -04:00
Daniel Lemire abf3d7d440 Slightly safer linux counters 2023-04-21 13:26:49 -04:00
Daniel Lemire 3c313b8530 Removing old file. 2023-04-13 11:52:02 -04:00
Dirk Stolle f435fddda1 update string_view lite to version 1.7.0 (#1984)
This is the header as seen for the tag v1.7.0,
commit 7b1867b7c08f9ac010fb8b9dae79ff8c8359bafb, on
<https://github.com/martinmoene/string-view-lite>.
2023-04-11 13:58:38 -04:00
Daniel Lemire 14d927128b New release 2023-04-08 16:13:48 -04:00
Daniel Lemire 48152a0326 Fix for issue 1981 (#1982)
* Fix

* Rewording.

* Doing it differently.
2023-04-08 16:11:40 -04:00
Daniel Lemire b5cf53232c More documentation. 2023-04-06 10:52:18 -04:00
Daniel Lemire b3d0b732e6 Update README.md 2023-04-04 14:22:12 -04:00
Daniel Lemire 3c29f40f2f Trying to verify issue 1979 (#1980) 2023-04-04 11:03:37 -04:00
Daniel Lemire 4a89d79984 Guarding the benchmarks. 2023-04-01 18:39:11 -04:00
Daniel Lemire 9cb639dcd7 Update basics.md 2023-03-30 12:35:38 -04:00
Daniel Lemire 4699dd0ce2 Update basics.md 2023-03-30 10:49:19 -04:00
Daniel Lemire cfd337bb50 This PR adds an 'at_end()' method. (#1978)
* This PR adds an 'at_end()' method.

* Adding 1111 }

* Tweaking test.
2023-03-30 10:47:13 -04:00
Daniel Lemire 9bef628982 It is no longer necessary to check separately for trailing content. 2023-03-24 20:04:04 -04:00
Daniel Lemire 59025bc8b1 Avoiding the issue where doc.get_value().get_object() differs from doc.get_object() in how errors are reported. (#1975)
* Avoiding the issue where doc.get_value().get_object() differs from doc.get_object() in how errors are reported.

* Minor tweaks
2023-03-24 12:44:18 -04:00
Daniel Lemire ffe96dde19 Update HACKING.md 2023-03-22 09:02:24 -04:00
Daniel Lemire f9664cf184 Update HACKING.md 2023-03-22 08:56:12 -04:00
Daniel Lemire 830323f383 Update HACKING.md 2023-03-22 08:55:26 -04:00
Daniel Lemire eb8e15d9c0 Update HACKING.md 2023-03-22 08:53:44 -04:00
Daniel Lemire 3571f3a8d0 Additional documentation. 2023-03-18 16:38:16 -04:00
Daniel Lemire 4b13020d65 Patch release 2023-03-13 21:44:34 -04:00
Daniel Lemire 75c6c950e5 Ok. 2023-03-13 21:26:32 -04:00
Daniel Lemire 5ad7698af1 ... 2023-03-13 17:07:25 -04:00
Daniel Lemire f6f359d3eb Very silly. 2023-03-13 17:05:53 -04:00
Daniel Lemire 185e157e0c Silencing the stupid compiler warnings. 2023-03-13 16:06:10 -04:00
Daniel Lemire 3f3f6cde7c Bad compiler 2023-03-13 13:33:20 -04:00
Daniel Lemire 005054916d Bad compiler 2023-03-13 13:02:01 -04:00
Daniel Lemire 338224849d Disabling memory sanitizer with one function. Might help with issue 1965 (#1966)
* Might help with issue 1965

* Fix macro

* Adding test.

* Stupid compiler

* Silly compiler

* Stupid compilers

* Unnecessary fixes

* Update developer-options.cmake
2023-03-13 12:34:47 -04:00
Ashot Vardanian ada52641b4 Fix: Defining maximal DOM capacity (#1970) 2023-03-13 12:33:37 -04:00
Daniel Lemire ede9d57f22 Adding tests with _GLIBCXX_ASSERTIONS (#1969)
* Allowing users to specify -D_GLIBCXX_ASSERTIONS

* Adding CI tests for GLIBCXX_ASSERTIONS

* Adding curly brackets.
2023-03-13 12:32:43 -04:00
Daniel Lemire 7bf33f6c8a Bad compiler 2023-03-13 12:29:01 -04:00
Daniel Lemire d62b789cb3 More curly. 2023-03-13 10:49:15 -04:00
Daniel Lemire 33dbd44098 Better way to put -Og in debug mode (#1967)
* Better way to put -Og in debug mode

* Silly compiler

* Stupid compiler.

* Stupid compiler.

* Silly compiler
2023-03-13 10:11:33 -04:00
Daniel Lemire e0dcf8adc9 Silly compiler 2023-03-12 20:57:45 -04:00
Daniel Lemire 34dcd33a88 Patch. 2023-03-09 11:24:06 -05:00
Daniel Lemire 17a1a8e187 Adding -Og to debug builds. (#1964)
* Adding -Og to debug builds.

* Stupid compiler.

* bad, bad, bad compiler
2023-03-09 11:14:42 -05:00
Daniel Lemire 77ad00b63c Producing a minor patch release 2023-03-09 11:13:01 -05:00
Daniel Lemire 25e7f1765a Various tweaks. 2023-03-09 10:42:23 -05:00
Daniel Lemire 8d01255ceb Update basics.md 2023-03-09 08:27:32 -05:00
Daniel Lemire 8ec016b093 Update README.md 2023-03-08 15:30:52 -05:00
Daniel Lemire 9e726b9856 Removing obsolete badge 2023-03-08 14:50:37 -05:00
Daniel Lemire 312f1f26d3 Now obsolete. 2023-03-08 14:50:06 -05:00
Daniel Lemire ba50571d66 Merge branch 'master' of github.com:simdjson/simdjson 2023-03-06 16:05:10 -05:00
Daniel Lemire 4a587cb898 Adding guards. 2023-03-06 16:04:42 -05:00
Daniel Lemire bdf9123c92 Update README.md 2023-03-06 11:08:56 -05:00
Dominik Lohmann 6e4c29b7c5 Fix export component for simdjsonTargets.cmake (#1962)
This fixes a bug that caused simdjsonTargets.cmake not to be included in
CPack-generated packages, which—unlike `cmake --install`—does not
pick up this mislabeled install component.

I git-grepped through the code base, after this change all components
are either `simdjson_Development` or `simdjson_Runtime`.
2023-03-04 17:34:40 -05:00
Daniel Lemire ec0b48b772 Version bump. 2023-03-02 14:27:49 -05:00
Daniel Lemire d65acbd47b Tuning documentation. 2023-03-02 09:39:35 -05:00
Daniel Lemire 75240ad8e1 Update basics.md 2023-03-01 19:05:45 -05:00
Daniel Lemire 3efb44dc0f Adding link 2023-03-01 19:03:03 -05:00
Daniel Lemire 5c5cd5b42d [skip ci] rephrasing. 2023-03-01 10:08:00 -05:00
Daniel Lemire 12a1b6db53 This adds some examples to the documentation. (#1959)
* This adds some examples to the documentation.

* Fix
2023-02-28 22:59:42 -05:00
Daniel Lemire 37e87f6f99 Adding support for wobbly strings to On Demand and lossy trancoding from escaped (with replacement) (#1947)
* Adding support for wobbly strings.

* Minor tweak.

* Adopt substitution code point.

* Lossy

* Patching
2023-02-28 22:56:44 -05:00
wanweiqiangintel cd13b02bf0 add UTF-8 validation flag (#1957) 2023-02-28 09:47:08 -05:00
Daniel Lemire 624174d916 Minor doc. tweaks. 2023-02-22 21:14:15 -05:00
Daniel Lemire 8a247f1321 Patch release. 2023-02-22 20:39:31 -05:00
Daniel Lemire 7aa35bffd3 Fixing support for windows ARM64 (#1955)
* Fixing Windows ARM64 support

* Updating the singleheader files.
2023-02-22 20:34:51 -05:00
Rawley d6c910686b Update README.md (#1953) 2023-02-13 21:11:05 -05:00
Daniel Lemire 22cc523fd4 Patching release script. 2023-02-06 19:11:52 -05:00
Daniel Lemire 3177cd1b5d Fix. 2023-02-06 19:08:11 -05:00
Daniel Lemire 63d9ce3c58 Patch release. 2023-02-06 18:31:02 -05:00
Daniel Lemire 8e8180560d Fix for issue 1950 (#1951) 2023-02-06 18:28:54 -05:00
Daniel Lemire 1594af5d5d Tweak. 2023-02-06 08:51:11 -05:00
Dirk Stolle b207338365 Remove trailing whitespace in README.md (#1949)
This should make the whitespace test pass again.
2023-01-31 17:53:35 -05:00
Daniel Lemire 68be9c2170 Update README.md 2023-01-30 16:17:42 -05:00
Daniel Lemire 5347771091 Update documentation.yml 2023-01-30 15:14:27 -05:00
Daniel Lemire 8bf8315651 Update README.md 2023-01-30 14:50:06 -05:00
Daniel Lemire 269ae7ad6b [skip ci] stupid mistake 2023-01-30 14:37:40 -05:00
Daniel Lemire 2aa91f741f [skip ci] new doc runner 2023-01-30 14:29:48 -05:00
Daniel Lemire 5430544bbb [skip ci] improving documentation. (#1948) 2023-01-30 14:27:35 -05:00
Daniel Lemire 7b55f16682 Trying s390x in CI (#1945)
* Trying s390x

* Providing big endian testing.

* adding token.

* Fixing branch
2023-01-27 11:34:00 -05:00
Daniel Lemire d8fec59e85 Safer add-dependency script. (#1946) 2023-01-26 22:40:26 -05:00
Daniel Lemire 57b6034a0c Let verbose 2023-01-26 21:12:23 -05:00
Daniel Lemire 7500d7bb4f Patching. 2023-01-25 22:19:40 -05:00
Daniel Lemire 82c9876aec Preparing release. 2023-01-21 18:07:06 -05:00
Daniel Lemire b9234be80f complete number_in_string for documents, stringify the version macro and improving trailing content errors (#1934)
* This completes the '*_in_string' support within documents.

* Minor updates.

* Additional fixes.
2023-01-21 15:29:08 -05:00
Daniel Lemire 0a2563e13e Testing and fixing log issues. (#1939)
* Testing and fixing log issues.

* Cleaning it a bit.
2023-01-21 15:28:56 -05:00
Daniel Lemire 727ec73c33 The fuzzer needs to be updated. (#1941) 2023-01-21 15:28:25 -05:00
Daniel Lemire 9a55a830ec Adding clang14 ci (#1940) 2023-01-21 15:27:21 -05:00
Daniel Lemire 8c89ae0cd9 Removing extra ';'. 2023-01-13 09:17:05 -05:00
Daniel Lemire 8c71ca1b1d Update implementation-selection.md 2023-01-07 13:43:26 -05:00
Daniel Lemire c72b4bc0f4 Update basics.md 2023-01-07 13:42:01 -05:00
Daniel Lemire 8a26cb3c8e Adding a couple of string tests. (#1935)
* Adding a couple of string tests.
2023-01-05 21:18:54 -05:00
Daniel Lemire bf2ba5c675 Update basics.md 2023-01-05 08:38:16 -05:00
Daniel Lemire f151300a76 Disabling fallback kernel on systems where it is not needed (#1930)
* Fixing issue 1772

* More cleaning.

* Allow disabling other kernels.

* Minor tweaks.
2023-01-03 09:52:41 -05:00
Daniel Lemire 9aa3563d99 Updating Google Benchmark. (#1929) 2023-01-03 09:52:26 -05:00
Daniel Lemire 9444c1a04f Merge branch 'master' of github.com:simdjson/simdjson 2022-12-19 21:07:17 -05:00
Daniel Lemire 883901a81b Updating users. 2022-12-19 21:07:07 -05:00
Daniel Lemire a2c96c9cca Update basics.md 2022-12-16 22:12:25 -05:00
Daniel Lemire c63da0ef2c Added a remark regarding assemblers. 2022-12-16 21:22:48 -05:00
Daniel Lemire c61cefda85 Merge branch 'master' of github.com:simdjson/simdjson 2022-12-05 12:25:52 -05:00
Daniel Lemire bffcbb444d Clarifying comment. 2022-12-05 12:25:29 -05:00
Daniel Lemire 0b2891aaab Trying fuzzer with llvm 14. (#1922) 2022-12-01 14:26:17 -05:00
wanweiqiangintel 983fb41802 Update README.md (#1925)
Add a real-word usage
2022-11-30 17:26:58 -05:00
Daniel Lemire 0d2455029d Preparing patch release. 2022-11-23 10:59:48 -05:00
Daniel Lemire e94f027310 Serialize 0 as 0.0 (#1921)
* Serialize 0 as 0.0

* Extending the '.0'.
2022-11-23 10:31:42 -05:00
sean 2b766e4c09 Fix: Add padded_string_view overload for parser::parse (#1916) 2022-11-23 09:22:39 -05:00
Daniel Lemire a5db75e1a6 Adding more development checks to the DOM front-end (#1915)
* This adds SIMDJSON_DEVELOPMENT_CHECKS to the DOM API to help users
in the scenario of issue 1914.

* More documentation and warnings.

* Updating following comments by Tyson
2022-10-17 09:11:09 -04:00
Daniel Lemire 4bd66cb891 We branch on GCC for performance. (#1913) 2022-10-16 13:15:35 -04:00
Daniel Lemire 960a7ebba1 Switching to iterate_many 2022-10-06 11:59:12 -04:00
Daniel Lemire d520062f8e Bumping API 2022-10-06 11:50:33 -04:00
Daniel Lemire db08d78ed0 Documents better the type method and makes is_null return an error condition in some instances (#1909) 2022-10-06 11:47:40 -04:00
Daniel Lemire 46292b8d4b Update basics.md 2022-10-05 08:50:52 -04:00
Tyson Andre 46241287c6 Check for trailing tokens in json2msgpack ondemand benchmark (#1908)
Related to #1904

Users of the simdjson library will see json2msgpack as an available
example of how to recursively process json with the ondemand parser,
and checking for trailing tokens in a document is one part of json validation.

These checks shouldn't affect benchmark results performance.
The benchmark is run on the 631KB twitter.json file.
2022-10-05 08:49:09 -04:00
Daniel Lemire 137cb14bcc Documenting how one can check for the end of the document. (#1907) 2022-10-04 20:23:52 -04:00
Daniel Lemire 5e6be3ed7a Minor fix (documentation and safety) regarding max. depth in ondemand. (#1906) 2022-10-04 12:24:20 -04:00
Tyson Andre c6ab52eebb [skip ci] Add an .editorconfig for .cpp/.h/.md for whitespace settings (#1901)
Make it less likely to accidentally introduce tabs, trailing whitespace,
carriage returns, non-utf8 in files, or files without trailing newlines.

https://editorconfig.org/ has plugins for various editors/IDEs and is
enabled by default in some IDEs.
2022-10-03 11:14:00 -04:00
Daniel Lemire a1aab1fafe Preparing release 2.2.3 2022-10-02 16:32:37 -04:00
Daniel Lemire b92cbbe280 Fixing issue 1898 (#1899)
* Fixing issue 1898 Preserve sign for number with underflowing exponent (#1900)


Before this commit, simdjson parsed "-1e-999" and "-0e-999" and "-1e-342"
as 0.0.
After this commit, those JSON strings get parsed as -0.0.
(https://en.wikipedia.org/wiki/Signed_zero)

The old behavior was inconsistent with the way simdjson parsed "-0.0" as -0.0.

Co-authored-by: Daniel Lemire <daniel@lemire.me>

Co-authored-by: Tyson Andre <tysonandre775@hotmail.com>
2022-10-02 16:25:39 -04:00
Tyson Andre 6d2a09f8e5 [skip ci] Fix typo, formatting nit in HACKING.md (#1902)
vim syntax highlighting doesn't work properly without space between a
bulleted list and the start of a code snippet.
2022-10-02 16:19:34 -04:00
Tyson Andre 00564bf7d5 Micro-optimization for parsing surrogate pairs (#1897)
Load 2 bytes and compare the 2 bytes against `"\u"`
Compilers with optimizations turned on will turn this into a 16-bit load
then 16-bit compare on supported platforms
(with smaller compiled code size).

Make it obvious to the compiler that it's reading two
consecutive bytes of the same pointer

Add parse_surrogate_pairs to show the difference exists.
See discussion in #1896
2022-10-02 12:10:53 -04:00
Tyson Andre 5809e51ae4 fix: Reject surrogate pairs with invalid low surrogate (#1896)
Closes #1894

Reject low surrogates outside of the range U+DC00—U+DFFF

Related to https://unicodebook.readthedocs.io/unicode_encodings.html#utf-16-surrogate-pairs

A surrogate pair should consist of a high surrogate and low surrogate.
They're used to represent 0x010000-0x10FFFF in the JSON spec because
the JavaScript specification originally only supported `\uXXXX`.

Previously, simdjson would accept some combinations of valid high
surrogates and invalid low surrogates due to a bug in the check.
(e.g. `\uD888\u1234` was accepted)

U+D800—U+DBFF (1,024 code points): high surrogates
U+DC00—U+DFFF (1,024 code points): low surrogates
2022-09-30 12:13:16 -04:00
Tyson Andre d27e7cce71 Fix typos in doc/basics.md (#1893) 2022-09-30 08:34:37 -04:00
David Korenchuk f7dc03f93d Fix documentation of description() method in implementation (#1895) 2022-09-30 08:34:06 -04:00
sean d4ac1b51d0 Fix various warnings & if constexpr (#1888) 2022-09-27 23:22:47 -04:00
Daniel Lemire 6a4222da71 Adding a remark to the documentation. 2022-09-19 15:28:33 -04:00
Daniel Lemire bba88eb5e5 Fixing typo in the documentation. 2022-09-19 10:21:11 -04:00
Daniel Lemire 16b3816455 This fixes an error caused by overeager gcc static analyser (#1891) 2022-09-19 10:20:48 -04:00
Andrea Pappacoda e5a408386b build: add pkg-config support (#1767)
* build: add pkg-config support

The CMake build script now generates a simple pkg-config files that can
be easily used by non-CMake users.

The file is generated from a template file that gets filled in at
configure time.

As CMake doesn't have anything similar to Meson's pkg-config generator
the file is quite static, i.e. new simdjson public defines/dependencies
won't be picked up automatically.

This approach also suffers from one minor issue, mentioned in
[jtojnar/cmake-snips][]; in short, it doesn't work well when users
specify CMAKE_INSTALL_INCLUDEDIR and similar as absolute paths. It's not
a big deal, and it will easily fixable once you'll require CMake >=3.20.

Fixes #1763

[jtojnar/cmake-snips]: https://github.com/jtojnar/cmake-snips#concatenating-paths-when-building-pkg-config-files

* build: handle absolute paths in .pc generation

As mentioned in the previous commit message, correct concatenation of
paths is only available in CMake >=3.20, so handling absolute paths in
pkg-config file generation requires using jtojnar's JoinPaths module.

* ci: add debian job

This new jobs compiles simdjson on Debian Testing, a semi-rolling
release, so that new compilers are always tested.

This job also tests the pkg-config file introduced in commit
1096c3b299
2022-08-26 16:20:51 -04:00
Herman Semenov e65f28e61a Fixed if condition, Win64 _fseeki64, trivial constructors C++11 (#1883) 2022-08-18 14:16:46 -04:00
Daniel Lemire fbb46b99e2 Fixes and verifies issue 1878. (#1880)
* Fixes and verifies issue 1878.

* Changing how NULL is handled.

* Different design.
2022-08-08 22:00:38 -04:00
Daniel Lemire 933c2ebeac Preparing release 2022-07-28 21:46:45 -04:00
Daniel Lemire db3e813aa6 Verifying and fixing issue 1876 (#1877)
* Verifying and fixing issue 1876

* Typo
2022-07-28 21:45:54 -04:00
Daniel Lemire 9c95a48fe6 cleaning on-demand benchmarks (#1875)
* Setting RapidJSON and yyjson to their latest version.

* Let us stop dumping all of the benchmarks (it is confusing) on screen.
2022-07-28 20:28:29 -04:00
Daniel Lemire cb20f7e7df Update CONTRIBUTING.md 2022-07-20 09:46:52 -04:00
Dirk Stolle 18b9168eec remove empty if block (#1873)
I guess it will be thrown away by the compiler's optimizer
anyway, but there is no need to keep this in the code.
2022-07-19 20:36:51 -04:00
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
316 changed files with 32842 additions and 10191 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
+12
View File
@@ -0,0 +1,12 @@
# https://editorconfig.org/
root = true
# Conservatively avoid changing defaults for other file types, e.g. raw json files for test cases,
# Makefiles, etc.
[*.{cpp,h,md}]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
tab_width = 2
trim_trailing_whitespace = true
+1
View File
@@ -78,6 +78,7 @@
.gitattributes export-ignore .gitattributes export-ignore
.gitignore export-ignore .gitignore export-ignore
.editorconfig export-ignore
# Sources # Sources
*.c text eol=lf diff=c *.c text eol=lf diff=c
+8 -6
View File
@@ -12,24 +12,26 @@ Before submitting an issue, please ensure that you have read the documentation:
* Basics is an overview of how to use simdjson and its APIs: https://github.com/simdjson/simdjson/blob/master/doc/basics.md * Basics is an overview of how to use simdjson and its APIs: https://github.com/simdjson/simdjson/blob/master/doc/basics.md
* Performance shows some more advanced scenarios and how to tune for them: https://github.com/simdjson/simdjson/blob/master/doc/performance.md * Performance shows some more advanced scenarios and how to tune for them: https://github.com/simdjson/simdjson/blob/master/doc/performance.md
* Contributing: https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md * Contributing: https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md
* We follow the [JSON specification as described by RFC 8259](https://www.rfc-editor.org/rfc/rfc8259.txt) (T. Bray, 2017). * We follow the [JSON specification as described by RFC 8259](https://www.rfc-editor.org/rfc/rfc8259.txt) (T. Bray, 2017). If you wish to support features that are not part of RFC 8259, then you should not refer to your issue as a bug.
**Describe the bug** **Describe the bug**
A clear and concise description of what the bug is. A clear and concise description of what the bug is. A bug is a failure to build with normal compiler settings or a misbehaviour: when running the code, you get a result that differs from the expected result from our documentation.
A compiler or static-analyzer warning is not a bug. A compiler or static-analyzer warning is not a bug. It is possible with tools such as Visual Studio to require that rarely enabled warnings are considered errors. Do not report such cases as bugs. We do accept pull requests if you want to silence warnings issued by code analyzers, however.
We are committed to providing good documentation. We accept the lack of documentation or a misleading documentation as a bug (a 'documentation bug'). We are committed to providing good documentation. We accept the lack of documentation or a misleading documentation as a bug (a 'documentation bug').
An unexpected poor software performance can be accepted as a bug (a 'performance bug').
We accept the identification of an issue by a sanitizer or some checker tool (e.g., valgrind) as a bug, but you must first ensure that it is not a false positive. We accept the identification of an issue by a sanitizer or some checker tool (e.g., valgrind) as a bug, but you must first ensure that it is not a false positive.
We recommend that you run your tests using different optimization levels. We recommend that you run your tests using different optimization levels. In particular, we recommend your run tests with the simdjson library and you code compiled in debug mode. The simdjson then sets the SIMDJSON_DEVELOPMENT_CHECKS macro to 1, and this triggers additional checks on your code and on the internals of the library. If possible, we recommend that you run tests with sanitizers (e.g., see [No more leaks with sanitize flags in gcc and clang](https://lemire.me/blog/2016/04/20/no-more-leaks-with-sanitize-flags-in-gcc-and-clang/)). You can compile the library with sanitizers for debugging purposes (e.g., set SIMDJSON_SANITIZE to ON using CMake), but you should also turn on sanitizers on your own code. You may also use tools like valgrind or the commercial equivalent.
Before reporting a bug, please ensure that you have read our documentation. Before reporting a bug, please ensure that you have read our documentation.
**To Reproduce** **To Reproduce**
Steps to reproduce the behaviour: provide a code sample if possible. Steps to reproduce the behaviour: provide a code sample if possible. Please provide a complete test with data. Remember that a bug is either a failure to build or an unexpected result when running the code.
If we cannot reproduce the issue, then we cannot address it. Note that a stack trace from your own program is not enough. A sample of your source code is insufficient: please provide a complete test for us to reproduce the issue. Please reduce the issue: use as small and as simple an example of the bug as possible. If we cannot reproduce the issue, then we cannot address it. Note that a stack trace from your own program is not enough. A sample of your source code is insufficient: please provide a complete test for us to reproduce the issue. Please reduce the issue: use as small and as simple an example of the bug as possible.
@@ -51,6 +53,6 @@ We support up-to-date 64-bit ARM and x64 FreeBSD, macOS, Windows and Linux syste
**Indicate whether you are willing or able to provide a bug fix as a pull request** **Indicate whether you are willing or able to provide a bug fix as a pull request**
If you plan to contribute to simdjson, please read our If you plan to contribute to simdjson, please read our guide:
* CONTRIBUTING guide: https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md and our * CONTRIBUTING guide: https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md and our
* HACKING guide: https://github.com/simdjson/simdjson/blob/master/HACKING.md * HACKING guide: https://github.com/simdjson/simdjson/blob/master/HACKING.md
+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
+33
View File
@@ -0,0 +1,33 @@
name: Debian
on: [push, pull_request]
defaults:
run:
shell: sh
permissions:
contents: read
jobs:
pkg-config:
runs-on: ubuntu-latest
container:
image: debian:testing
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: |
apt -y update
apt -y --no-install-recommends install g++ cmake make pkg-config
- name: Build and install
run: |
cmake -B build
cmake --build build
cmake --install build
- name: Test pkg-config
run: g++ examples/quickstart/quickstart.cpp $(pkg-config --cflags --libs simdjson)
+34
View File
@@ -0,0 +1,34 @@
name: Doxygen GitHub Pages
on:
push:
branches:
- master
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
permissions:
contents: write
pages: write
id-token: write
jobs:
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Doxygen
run: sudo apt-get install doxygen graphviz -y
- run: mkdir docs
- name: Install theme
run: ./tools/prepare_doxygen.sh
- name: Generate Doxygen Documentation
run: doxygen
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: doc/api/html
@@ -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
+10 -10
View File
@@ -24,7 +24,7 @@ jobs:
implementations: haswell westmere fallback implementations: haswell westmere fallback
UBSAN_OPTIONS: halt_on_error=1 UBSAN_OPTIONS: halt_on_error=1
MAXLEN: -max_len=4000 MAXLEN: -max_len=4000
CLANGVERSION: 11 CLANGVERSION: 15
# which optimization level to use for the sanitizer build (see build_fuzzer.variants.sh) # which optimization level to use for the sanitizer build (see build_fuzzer.variants.sh)
OPTLEVEL: -O3 OPTLEVEL: -O3
@@ -32,30 +32,30 @@ jobs:
- name: Install packages necessary for building - name: Install packages necessary for building
run: | run: |
sudo apt update sudo apt update
sudo apt-get install --quiet ninja-build valgrind zip unzip sudo apt-get install --quiet ninja-build valgrind zip unzip lsb-release wget software-properties-common gnupg
wget https://apt.llvm.org/llvm.sh wget https://apt.llvm.org/llvm.sh
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/
key: corpus-${{ github.run_id }} key: corpus-${{ github.run_id }}
restore-keys: corpus- restore-keys: corpus-
- name: show statistics for the cached corpus - name: show statistics for the cached corpus
run: | run: |
echo number of files in github action corpus cache: echo number of files in github action corpus cache:
find out -type f |wc -l find out -type f |wc -l
- name: Create and prepare the initial seed corpus - name: Create and prepare the initial seed corpus
run: | run: |
fuzz/build_corpus.sh fuzz/build_corpus.sh
@@ -92,7 +92,7 @@ jobs:
export SIMDJSON_FORCE_IMPLEMENTATION=$implementation export SIMDJSON_FORCE_IMPLEMENTATION=$implementation
build-sanitizers$OPTLEVEL/fuzz/fuzz_$fuzzer out/$fuzzer $others seedcorpus -max_total_time=20 $MAXLEN build-sanitizers$OPTLEVEL/fuzz/fuzz_$fuzzer out/$fuzzer $others seedcorpus -max_total_time=20 $MAXLEN
done done
echo now have $(ls out/$fuzzer |wc -l) files in corpus echo now have $(ls out/$fuzzer |wc -l) files in corpus
done done
- name: Fuzz differential impl. fuzzers with sanitizer+asserts (good at detecting errors) - name: Fuzz differential impl. fuzzers with sanitizer+asserts (good at detecting errors)
@@ -119,7 +119,7 @@ jobs:
- name: Package the corpus into an artifact - name: Package the corpus into an artifact
run: | run: |
for fuzzer in $defaultimplfuzzers $implfuzzers; do for fuzzer in $defaultimplfuzzers $implfuzzers; do
tar rf corpus.tar out/$fuzzer tar rf corpus.tar out/$fuzzer
done done
@@ -141,7 +141,7 @@ jobs:
run: | run: |
for fuzzer in $defaultimplfuzzers $implfuzzers; do for fuzzer in $defaultimplfuzzers $implfuzzers; do
find out/$fuzzer -type f |sort|head -n200|xargs -n40 valgrind build-replay/fuzz/fuzz_$fuzzer 2>&1|tee valgrind-$fuzzer.txt find out/$fuzzer -type f |sort|head -n200|xargs -n40 valgrind build-replay/fuzz/fuzz_$fuzzer 2>&1|tee valgrind-$fuzzer.txt
done done
- name: Compress the valgrind output - name: Compress the valgrind output
run: tar cf valgrind.tar valgrind-*.txt run: tar cf valgrind.tar valgrind-*.txt
+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') }}
+29
View File
@@ -0,0 +1,29 @@
name: Ubuntu s390x (GCC 11)
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: uraimo/run-on-arch-action@v2
name: Test
id: runcmd
with:
arch: s390x
distro: ubuntu_latest
githubToken: ${{ github.token }}
install: |
apt-get update -q -y
apt-get install -y cmake make g++
run: |
cmake -DCMAKE_BUILD_TYPE=Release -B build
cmake --build build -j=2
ctest --output-on-failure --test-dir build
-29
View File
@@ -1,29 +0,0 @@
name: Performance check on Ubuntu 18.04 CI (GCC 7)
on:
push:
branches:
- master
pull_request:
branches:
- master
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
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Use cmake
run: |
mkdir build &&
cd build &&
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_ENABLE_DOM_CHECKPERF=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
cmake --build . --target checkperf &&
ctest --output-on-failure -R checkperf ubuntu18-checkperf.yml
-30
View File
@@ -1,30 +0,0 @@
name: Ubuntu 18.04 CI (GCC 7) with Thread Sanitizer
on:
push:
branches:
- master
pull_request:
branches:
- master
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
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: dependencies/.cache
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
- name: Use cmake
run: |
mkdir build &&
cd build &&
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_SANITIZE_THREADS=ON .. &&
cmake --build . --target document_stream_tests --target ondemand_document_stream_tests --target parse_many_test &&
ctest --output-on-failure -R parse_many_test &&
ctest --output-on-failure -R document_stream_tests
+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') }}
+30
View File
@@ -0,0 +1,30 @@
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 with address sanitizer
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
- name: Use cmake with undefined sanitizer
run: |
mkdir builddebugundefsani &&
cd builddebugundefsani &&
cmake -DSIMDJSON_SANITIZE_UNDEFINED=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 (CLANG 14)
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++-14
run: sudo apt-get install -y clang++-14
- name: Use cmake
run: |
mkdir build &&
cd build &&
CXX=clang++-14 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
@@ -0,0 +1,24 @@
name: Ubuntu 22.04 CI GCC 12 with GLIBCXX_ASSERTIONS
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 -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GLIBCXX_ASSERTIONS=ON -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON .. &&
cmake --build . &&
ctest . -E avoid_
@@ -1,31 +1,33 @@
name: Ubuntu 18.04 CI (GCC 7) name: Ubuntu 22.04 CI (GCC 11)
on: on: [push, pull_request]
push:
branches:
- master
pull_request:
branches:
- master
jobs: jobs:
ubuntu-build: ubuntu-build:
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]')
runs-on: ubuntu-18.04 runs-on: ubuntu-22.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') }}
- name: Use cmake - name: Use cmake
run: | run: |
mkdir build && mkdir builddebug &&
cd build && cd builddebug &&
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. && cmake -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
cmake --build . && cmake --build . &&
ctest -j --output-on-failure -LE explicitonly && ctest -j --output-on-failure -LE explicitonly &&
make install && cd .. &&
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 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
+14 -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,19 @@
"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",
"span": "cpp"
} }
} }
+47 -17
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 3.1.7
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 "15.0.0" CACHE STRING "simdjson library version")
set(SIMDJSON_LIB_SOVERSION "8" CACHE STRING "simdjson library soversion") set(SIMDJSON_LIB_SOVERSION "15" 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 ----
@@ -104,6 +95,21 @@ if(
) )
endif() endif()
# GCC and Clang have horrendous Debug builds when using SIMD.
# A common fix is to use '-Og' instead.
# bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54412
if(
(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR
CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
)
message(STATUS "Adding -Og to compile flag")
simdjson_add_props(
target_compile_options PRIVATE
$<$<CONFIG:DEBUG>:-Og>
)
endif()
if(SIMDJSON_ENABLE_THREADS) if(SIMDJSON_ENABLE_THREADS)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
simdjson_add_props(target_link_libraries PUBLIC Threads::Threads) simdjson_add_props(target_link_libraries PUBLIC Threads::Threads)
@@ -158,7 +164,25 @@ install(
EXPORT simdjsonTargets EXPORT simdjsonTargets
NAMESPACE simdjson:: NAMESPACE simdjson::
DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}" DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}"
COMPONENT example_Development COMPONENT simdjson_Development
)
# pkg-config
include(cmake/JoinPaths.cmake)
join_paths(PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
join_paths(PKGCONFIG_LIBDIR "\${prefix}" "${CMAKE_INSTALL_LIBDIR}")
if(SIMDJSON_ENABLE_THREADS)
set(PKGCONFIG_CFLAGS "-DSIMDJSON_THREADS_ENABLED=1")
if(CMAKE_THREAD_LIBS_INIT)
set(PKGCONFIG_LIBS_PRIVATE "Libs.private: ${CMAKE_THREAD_LIBS_INIT}")
endif()
endif()
configure_file("simdjson.pc.in" "simdjson.pc" @ONLY)
install(
FILES "${CMAKE_CURRENT_BINARY_DIR}/simdjson.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
) )
# #
@@ -179,10 +203,14 @@ endif()
# ---- Developer mode extras ---- # ---- Developer mode extras ----
if(is_top_project AND NOT SIMDJSON_DEVELOPER_MODE)
message(STATUS "Building only the library. Advanced users and contributors may want to turn SIMDJSON_DEVELOPER_MODE to ON, e.g., via -D SIMDJSON_DEVELOPER_MODE=ON.")
elseif(SIMDJSON_DEVELOPER_MODE AND NOT is_top_project)
message(AUTHOR_WARNING "Developer mode in simdjson is intended for the developers of simdjson")
endif()
if(NOT SIMDJSON_DEVELOPER_MODE) if(NOT SIMDJSON_DEVELOPER_MODE)
return() return()
elseif(NOT is_top_project)
message(AUTHOR_WARNING "Developer mode is intended for developers of simdjson")
endif() endif()
simdjson_apply_props(simdjson-internal-flags) simdjson_apply_props(simdjson-internal-flags)
@@ -223,7 +251,9 @@ add_subdirectory(singleheader)
# #
add_subdirectory(tests) add_subdirectory(tests)
add_subdirectory(examples) add_subdirectory(examples)
add_subdirectory(benchmark) if(CMAKE_SIZEOF_VOID_P EQUAL 8) # we only include the benchmarks on 64-bit systems.
add_subdirectory(benchmark)
endif()
add_subdirectory(fuzz) add_subdirectory(fuzz)
# #
+5 -5
View File
@@ -54,7 +54,7 @@ Contributors are encouraged to :
- Document their changes. Though we do not enforce a rule regarding code comments, we prefer that non-trivial algorithms and techniques be somewhat documented in the code. - Document their changes. Though we do not enforce a rule regarding code comments, we prefer that non-trivial algorithms and techniques be somewhat documented in the code.
- Follow as much as possible the existing code style. We do not enforce a specific code style, but we prefer consistency. - Follow as much as possible the existing code style. We do not enforce a specific code style, but we prefer consistency.
- Modify as few lines of code as possible when working on an issue. The more lines you modify, the harder it is for your fellow human beings to understand what is going on. - Modify as few lines of code as possible when working on an issue. The more lines you modify, the harder it is for your fellow human beings to understand what is going on.
- Tools may report "problems" with the code, but we never delegate programming to tools: if there is a problem with the code, we need to understand it. Thus we will not "fix" code merely to please a static analyzer if we do not understand. - Tools may report "problems" with the code, but we never delegate programming to tools: if there is a problem with the code, we need to understand it. Thus we will not "fix" code merely to please a static analyzer.
- Provide tests for any new feature. We will not merge a new feature without tests. - Provide tests for any new feature. We will not merge a new feature without tests.
Pull Requests Pull Requests
@@ -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!
+11 -5
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 = "3.1.7"
# 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
@@ -829,7 +829,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = doc include INPUT = doc include/simdjson include/simdjson/dom include/simdjson/generic
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -1246,7 +1246,10 @@ HTML_STYLESHEET =
# list). For an example see the documentation. # list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_STYLESHEET = theme/doxygen-awesome.css \
theme/doxygen-awesome-sidebar-only.css \
theme/doxygen-awesome-sidebar-only-darkmode-toggle.css
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note # other source files which should be copied to the HTML output directory. Note
@@ -1256,7 +1259,10 @@ HTML_EXTRA_STYLESHEET =
# files will be copied as-is; there are no commands or markers available. # files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES = HTML_EXTRA_FILES = theme/doxygen-awesome-darkmode-toggle.js \
theme/doxygen-awesome-interactive-toc.js \
theme/doxygen-awesome-fragment-copy-button.js \
theme/doxygen-awesome-paragraph-link.js
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to # will adjust the colors in the style sheet and background images according to
@@ -1543,7 +1549,7 @@ DISABLE_INDEX = NO
# The default value is: NO. # The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO GENERATE_TREEVIEW = YES
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation. # doxygen will group on one line in the generated HTML documentation.
+18 -5
View File
@@ -1,3 +1,4 @@
Hacking simdjson Hacking simdjson
================ ================
@@ -6,6 +7,16 @@ Here is wisdom about how to build, test and run simdjson from within the reposit
If you plan to contribute to simdjson, please read our [CONTRIBUTING](https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md) guide. If you plan to contribute to simdjson, please read our [CONTRIBUTING](https://github.com/simdjson/simdjson/blob/master/CONTRIBUTING.md) guide.
- [Design notes](#design-notes)
- [Developer mode](#developer-mode)
- [Directory Structure and Source](#directory-structure-and-source)
- [Runtime Dispatching](#runtime-dispatching)
- [Regenerating Single-Header Files](#regenerating-single-header-files)
- [Usage (CMake on 64-bit platforms like Linux, FreeBSD or macOS)](#usage-cmake-on-64-bit-platforms-like-linux-freebsd-or-macos)
- [Usage (CMake on 64-bit Windows using Visual Studio 2019)](#usage-cmake-on-64-bit-windows-using-visual-studio-2019)
- [Various References](#various-references)
Design notes Design notes
------------------------------ ------------------------------
@@ -82,7 +93,7 @@ Other important files and directories:
* **singleheader/amalgamate.py:** Generates `singleheader/simdjson.h` and `singleheader/simdjson.cpp` for release (python script). * **singleheader/amalgamate.py:** Generates `singleheader/simdjson.h` and `singleheader/simdjson.cpp` for release (python script).
* **benchmark:** This is where we do benchmarking. Benchmarking is core to every change we make; the * **benchmark:** This is where we do benchmarking. Benchmarking is core to every change we make; the
cardinal rule is don't regress performance without knowing exactly why, and what you're trading cardinal rule is don't regress performance without knowing exactly why, and what you're trading
for it. Many of our benchmarks are microbenchmarks. We are effectively doing controlled scientific experiments for the purpose of understanding what affects our performance. So we simplify as much as possible. We try to avoid irrelevant factors such as page faults, interrupts, unnnecessary system calls. We recommend checking the performance as follows: for it. Many of our benchmarks are microbenchmarks. We are effectively doing controlled scientific experiments for the purpose of understanding what affects our performance. So we simplify as much as possible. We try to avoid irrelevant factors such as page faults, interrupts, unnecessary system calls. We recommend checking the performance as follows:
```bash ```bash
mkdir build mkdir build
cd build cd build
@@ -114,7 +125,7 @@ Other important files and directories:
* `json2json mydoc.json` parses the document, constructs a model and then dumps back the result to standard output. * `json2json mydoc.json` parses the document, constructs a model and then dumps back the result to standard output.
* `json2json -d mydoc.json` parses the document, constructs a model and then dumps model (as a tape) to standard output. The tape format is described in the accompanying file `tape.md`. * `json2json -d mydoc.json` parses the document, constructs a model and then dumps model (as a tape) to standard output. The tape format is described in the accompanying file `tape.md`.
* `minify mydoc.json` minifies the JSON document, outputting the result to standard output. Minifying means to remove the unneeded white space characters. * `minify mydoc.json` minifies the JSON document, outputting the result to standard output. Minifying means to remove the unneeded white space characters.
*`jsonpointer mydoc.json <jsonpath> <jsonpath> ... <jsonpath>` parses the document, constructs a model and then processes a series of [JSON Pointer paths](https://tools.ietf.org/html/rfc6901). The result is itself a JSON document. * `jsonpointer mydoc.json <jsonpath> <jsonpath> ... <jsonpath>` parses the document, constructs a model and then processes a series of [JSON Pointer paths](https://tools.ietf.org/html/rfc6901). The result is itself a JSON document.
> **Don't modify the files in singleheader/ directly; these are automatically generated.** > **Don't modify the files in singleheader/ directly; these are automatically generated.**
@@ -193,7 +204,7 @@ point it gets included (but only once per header). singleheader/simdjson.cpp is
src/simdjson.cpp the same way, except files under generic/ may be included and copy/pasted multiple src/simdjson.cpp the same way, except files under generic/ may be included and copy/pasted multiple
times. times.
### Usage (CMake on 64-bit platforms like Linux, FreeBSD or macOS) ## Usage (CMake on 64-bit platforms like Linux, FreeBSD or macOS)
Requirements: In addition to git, we require a recent version of CMake as well as bash. Requirements: In addition to git, we require a recent version of CMake as well as bash.
@@ -256,7 +267,9 @@ Note that the name of directory (`build`) is arbitrary, you can name it as you w
### Usage (CMake on 64-bit Windows using Visual Studio 2019) ## Usage (CMake on 64-bit Windows using Visual Studio 2019 or better)
Recent versions of Visual Studio support CMake natively, [please refer to the Visual Studio documentation](https://learn.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio?view=msvc-170).
We assume you have a common 64-bit Windows PC with at least Visual Studio 2019. We assume you have a common 64-bit Windows PC with at least Visual Studio 2019.
@@ -285,7 +298,7 @@ Furthermore, if you have installed LLVM clang on Windows, for example as a compo
- `cmake --build . -config Release` - `cmake --build . -config Release`
### Various References ## Various References
- [How to implement atoi using SIMD?](https://stackoverflow.com/questions/35127060/how-to-implement-atoi-using-simd) - [How to implement atoi using SIMD?](https://stackoverflow.com/questions/35127060/how-to-implement-atoi-using-simd)
- [Parsing JSON is a Minefield 💣](http://seriot.ch/parsing_json.php) - [Parsing JSON is a Minefield 💣](http://seriot.ch/parsing_json.php)
+1 -1
View File
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier same "printed page" as the copyright notice for easier
identification within third-party archives. identification within third-party archives.
Copyright 2018-2019 The simdjson authors Copyright 2018-2023 The simdjson authors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
+24 -8
View File
@@ -1,9 +1,11 @@
![Ubuntu 18.04 CI](https://github.com/simdjson/simdjson/workflows/Ubuntu%2018.04%20CI%20(GCC%207)/badge.svg)
[![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)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/simdjson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:simdjson)
![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.github.io/simdjson/)
simdjson : Parsing gigabytes of JSON per second simdjson : Parsing gigabytes of JSON per second
=============================================== ===============================================
@@ -53,6 +55,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 +81,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 +113,19 @@ 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)
- [Intel PCM](https://github.com/intel/pcm)
- [WatermelonDB](https://github.com/Nozbe/WatermelonDB)
- [Apache Doris](https://github.com/apache/doris)
- [Dgraph](https://github.com/dgraph-io/dgraph)
- [UJRPC](https://github.com/unum-cloud/ujrpc)
- [fastgltf](https://github.com/spnda/fastgltf)
- [Clang Build Analyzer](https://github.com/aras-p/ClangBuildAnalyzer)
- [vast](https://github.com/tenzir/vast)
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.
@@ -136,8 +148,12 @@ We distinguish between "bindings" (which just wrap the C++ code) and a port to a
- [simdjson-go](https://github.com/minio/simdjson-go): Go port using Golang assembly. - [simdjson-go](https://github.com/minio/simdjson-go): Go port using Golang assembly.
- [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.
- [simdjsone](https://github.com/saleyn/simdjsone): 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.
- [JSON-Simd](https://github.com/rawleyfowler/JSON-simd): Raku bindings.
- [JSON::SIMD](https://metacpan.org/pod/JSON::SIMD): Perl bindings; fully-featured JSON module that uses simdjson for decoding.
About simdjson About simdjson
-------------- --------------
@@ -158,7 +174,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
------- -------
@@ -180,7 +196,7 @@ License
This code is made available under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html). This code is made available under the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0.html).
Under Windows, we build some tools using the windows/dirent_portable.h file (which is outside our library code): it under the liberal (business-friendly) MIT license. Under Windows, we build some tools using the windows/dirent_portable.h file (which is outside our library code): it is under the liberal (business-friendly) MIT license.
For compilers that do not support [C++17](https://en.wikipedia.org/wiki/C%2B%2B17), we bundle the string-view library which is published under the [Boost license](http://www.boost.org/LICENSE_1_0.txt). Like the Apache license, the Boost license is a permissive license allowing commercial redistribution. For compilers that do not support [C++17](https://en.wikipedia.org/wiki/C%2B%2B17), we bundle the string-view library which is published under the [Boost license](http://www.boost.org/LICENSE_1_0.txt). Like the Apache license, the Boost license is a permissive license allowing commercial redistribution.
-69
View File
@@ -1,69 +0,0 @@
# 0.5
## Highlights
Performance
* Faster and simpler UTF-8 validation with the lookup4 algorithm https://github.com/simdjson/simdjson/pull/993
* We improved the performance of simdjson under Visual Studio by about 25%. Users will still get better performance with clang-cl (+30%) but the gap has been reduced. https://github.com/simdjson/simdjson/pull/1031
Code usability
* In `parse_many`, when parsing streams of JSON documetns, we give to the users runtime control as to whether threads are used (via the parser.threaded attribute). https://github.com/simdjson/simdjson/issues/925
* Prefixed public macros to avoid name clashes with other libraries. https://github.com/simdjson/simdjson/issues/1035
* Better documentation regarding package managers (brew, MSYS2, conan, apt, vcpkg, FreeBSD package manager, etc.).
* Better documentation regarding CMake usage.
Standards
* We improved standard compliance with respect to both the JSON RFC 8259 and JSON Pointer RFC 6901. We added the at_pointer method to nodes for standard-compliant JSON Pointer queries. The legacy `at(std::string_view)` method remains but is deprecated since it is not standard-compliant as per RFC 6901.
* We removed computed GOTOs without sacrificing performance thus improving the C++ standard compliance (since computed GOTOs are compiler-specific extensions).
* Better support for C++20 https://github.com/simdjson/simdjson/pull/1050
# 0.4
## Highlights
- Test coverage has been greatly improved and we have resolved many static-analysis warnings on different systems.
- We added a fast (8GB/s) minifier that works directly on JSON strings.
- We added fast (10GB/s) UTF-8 validator that works directly on strings (any strings, including non-JSON).
- The array and object elements have a constant-time size() method.
- Performance improvements to the API (type(), get<>()).
- The parse_many function (ndjson) has been entirely reworked. It now uses a single secondary thread instead of several new threads.
- We have introduced a faster UTF-8 validation algorithm (lookup3) for all kernels (ARM, x64 SSE, x64 AVX).
- C++11 support for older compilers and systems.
- FreeBSD support (and tests).
- We support the clang front-end compiler (clangcl) under Visual Studio.
- It is now possible to target ARM platforms under Visual Studio.
- The simdjson library will never abort or print to standard output/error.
# 0.3
## Highlights
- **Multi-Document Parsing:** Read a bundle of JSON documents (ndjson) 2-4x faster than doing it
individually. [API docs](https://github.com/simdjson/simdjson/blob/master/doc/basics.md#newline-delimited-json-ndjson-and-json-lines) / [Design Details](https://github.com/simdjson/simdjson/blob/master/doc/parse_many.md)
- **Simplified API:** The API has been completely revamped for ease of use, including a new JSON
navigation API and fluent support for error code *and* exception styles of error handling with a
single API. [Docs](https://github.com/simdjson/simdjson/blob/master/doc/basics.md#the-basics-loading-and-parsing-json-documents)
- **Exact Float Parsing:** Now simdjson parses floats flawlessly *without* any performance loss,
thanks to [great work by @michaeleisel and @lemire](https://github.com/simdjson/simdjson/pull/558).
[Blog Post](https://lemire.me/blog/2020/03/10/fast-float-parsing-in-practice/)
- **Even Faster:** The fastest parser got faster! With a [shiny new UTF-8 validator](https://github.com/simdjson/simdjson/pull/387)
and meticulously refactored SIMD core, simdjson 0.3 is 15% faster than before, running at 2.5 GB/s
(where 0.2 ran at 2.2 GB/s).
## Minor Highlights
- Fallback implementation: simdjson now has a non-SIMD fallback implementation, and can run even on
very old 64-bit machines.
- Automatic allocation: as part of API simplification, the parser no longer has to be preallocated--
it will adjust automatically when it encounters larger files.
- Runtime selection API: We've exposed simdjson's runtime CPU detection and implementation selection
as an API, so you can tell what implementation we detected and test with other implementations.
- Error handling your way: Whether you use exceptions or check error codes, simdjson lets you handle
errors in your style. APIs that can fail return simdjson_result<T>, letting you check the error
code before using the result. But if you are more comfortable with exceptions, skip the error code
and cast straight to T, and exceptions will be thrown automatically if an error happens. Use the
same API either way!
- Error chaining: We also worked to keep non-exception error-handling short and sweet. Instead of
having to check the error code after every single operation, now you can *chain* JSON navigation
calls like looking up an object field or array element, or casting to a string, so that you only
have to check the error code once at the very end.
@@ -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
+27 -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>
@@ -563,7 +564,7 @@ static void error_code_twitter_default_profile(State& state) noexcept {
for (dom::element tweet : tweets) { for (dom::element tweet : tweets) {
dom::object user; dom::object user;
if ((error = tweet["user"].get(user))) { return; } if ((error = tweet["user"].get(user))) { return; }
bool default_profile; bool default_profile{};
if ((error = user["default_profile"].get(default_profile))) { return; } if ((error = user["default_profile"].get(default_profile))) { return; }
if (default_profile) { if (default_profile) {
std::string_view screen_name; std::string_view screen_name;
@@ -655,6 +656,31 @@ static void error_code_twitter_image_sizes(State& state) noexcept {
} }
BENCHMARK(error_code_twitter_image_sizes); BENCHMARK(error_code_twitter_image_sizes);
static void parse_surrogate_pairs(State& state) {
// NOTE: This mostly exists to show there's a tiny benefit to
// loading and comparing both bytes of "\\u" simultaneously.
// (which should also reduce the compiled code size).
// The repeated surrogate pairs make this easier to measure.
dom::parser parser;
const std::string_view data = "\"\\uD834\\uDD1E\\uD834\\uDD1E\\uD834\\uDD1E\\uD834\\uDD1E\\uD834\\uDD1E\\uD834\\uDD1E\\uD834\\uDD1E\\uD834\\uDD1E\\uD834\\uDD1E\\uD834\\uDD1E\"";
padded_string docdata{data};
// we do not want mem. alloc. in the loop.
auto error = parser.allocate(docdata.size());
if (error) {
cout << error << endl;
return;
}
for (simdjson_unused auto _ : state) {
dom::element doc;
if ((error = parser.parse(docdata).get(doc))) {
cerr << "could not parse string" << error << endl;
return;
}
}
}
BENCHMARK(parse_surrogate_pairs);
#ifndef SIMDJSON_DISABLE_DEPRECATED_API #ifndef SIMDJSON_DISABLE_DEPRECATED_API
SIMDJSON_PUSH_DISABLE_WARNINGS SIMDJSON_PUSH_DISABLE_WARNINGS
+105 -57
View File
@@ -25,6 +25,111 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
#include <benchmark/benchmark.h> #include <benchmark/benchmark.h>
SIMDJSON_POP_DISABLE_WARNINGS SIMDJSON_POP_DISABLE_WARNINGS
#include "json2msgpack/simdjson_ondemand.h"
#include "json2msgpack/simdjson_dom.h"
#include "json2msgpack/yyjson.h"
#include "json2msgpack/rapidjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "json2msgpack/sajson.h"
#endif // SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "json2msgpack/nlohmann_json.h"
#include "partial_tweets/simdjson_ondemand.h"
#include "partial_tweets/simdjson_dom.h"
#include "partial_tweets/yyjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "partial_tweets/sajson.h"
#endif // SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "partial_tweets/rapidjson.h"
#if SIMDJSON_COMPETITION_SAX
#include "partial_tweets/rapidjson_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "partial_tweets/nlohmann_json.h"
#if SIMDJSON_COMPETITION_SAX
#include "partial_tweets/nlohmann_json_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "distinct_user_id/simdjson_ondemand.h"
#include "distinct_user_id/simdjson_ondemand_json_pointer.h"
#include "distinct_user_id/simdjson_dom.h"
#include "distinct_user_id/simdjson_dom_json_pointer.h"
#include "distinct_user_id/yyjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "distinct_user_id/sajson.h"
#endif // SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "distinct_user_id/rapidjson.h"
#if SIMDJSON_COMPETITION_SAX
#include "distinct_user_id/rapidjson_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "distinct_user_id/nlohmann_json.h"
#if SIMDJSON_COMPETITION_SAX
#include "distinct_user_id/nlohmann_json_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "find_tweet/simdjson_ondemand.h"
#include "find_tweet/simdjson_dom.h"
#include "find_tweet/yyjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "find_tweet/sajson.h"
#endif // SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "find_tweet/rapidjson.h"
#if SIMDJSON_COMPETITION_SAX
#include "find_tweet/rapidjson_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "find_tweet/nlohmann_json.h"
#if SIMDJSON_COMPETITION_SAX
#include "find_tweet/nlohmann_json_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "top_tweet/simdjson_ondemand.h"
#include "top_tweet/simdjson_dom.h"
#include "top_tweet/yyjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "top_tweet/sajson.h"
#endif // SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "top_tweet/rapidjson.h"
#if SIMDJSON_COMPETITION_SAX
#include "top_tweet/rapidjson_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "top_tweet/nlohmann_json.h"
#if SIMDJSON_COMPETITION_SAX
#include "top_tweet/nlohmann_json_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "kostya/simdjson_ondemand.h"
#include "kostya/simdjson_dom.h"
#include "kostya/yyjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "kostya/sajson.h"
#endif // SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "kostya/rapidjson.h"
#if SIMDJSON_COMPETITION_SAX
#include "kostya/rapidjson_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "kostya/nlohmann_json.h"
#if SIMDJSON_COMPETITION_SAX
#include "kostya/nlohmann_json_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "large_random/simdjson_ondemand.h"
#if SIMDJSON_COMPETITION_ONDEMAND_UNORDERED
#include "large_random/simdjson_ondemand_unordered.h"
#endif // SIMDJSON_COMPETITION_ONDEMAND_UNORDERED
#include "large_random/simdjson_dom.h"
#include "large_random/yyjson.h"
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "large_random/sajson.h"
#endif // SIMDJSON_COMPETITION_ONDEMAND_SAJSON
#include "large_random/rapidjson.h"
#if SIMDJSON_COMPETITION_SAX
#include "large_random/rapidjson_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "large_random/nlohmann_json.h"
#if SIMDJSON_COMPETITION_SAX
#include "large_random/nlohmann_json_sax.h"
#endif // SIMDJSON_COMPETITION_SAX
#include "amazon_cellphones/simdjson_dom.h" #include "amazon_cellphones/simdjson_dom.h"
#include "amazon_cellphones/simdjson_ondemand.h" #include "amazon_cellphones/simdjson_ondemand.h"
@@ -32,61 +137,4 @@ SIMDJSON_POP_DISABLE_WARNINGS
#include "large_amazon_cellphones/simdjson_dom.h" #include "large_amazon_cellphones/simdjson_dom.h"
#include "large_amazon_cellphones/simdjson_ondemand.h" #include "large_amazon_cellphones/simdjson_ondemand.h"
#include "partial_tweets/simdjson_dom.h"
#include "partial_tweets/simdjson_ondemand.h"
#include "partial_tweets/yyjson.h"
#include "partial_tweets/sajson.h"
#include "partial_tweets/rapidjson.h"
#include "partial_tweets/rapidjson_sax.h"
#include "partial_tweets/nlohmann_json.h"
#include "partial_tweets/nlohmann_json_sax.h"
#include "large_random/simdjson_dom.h"
#include "large_random/simdjson_ondemand.h"
#include "large_random/simdjson_ondemand_unordered.h"
#include "large_random/yyjson.h"
#include "large_random/sajson.h"
#include "large_random/rapidjson.h"
#include "large_random/rapidjson_sax.h"
#include "large_random/nlohmann_json.h"
#include "large_random/nlohmann_json_sax.h"
#include "kostya/simdjson_dom.h"
#include "kostya/simdjson_ondemand.h"
#include "kostya/yyjson.h"
#include "kostya/sajson.h"
#include "kostya/rapidjson.h"
#include "kostya/rapidjson_sax.h"
#include "kostya/nlohmann_json.h"
#include "kostya/nlohmann_json_sax.h"
#include "distinct_user_id/simdjson_dom.h"
#include "distinct_user_id/simdjson_dom_json_pointer.h"
#include "distinct_user_id/simdjson_ondemand.h"
#include "distinct_user_id/simdjson_ondemand_json_pointer.h"
#include "distinct_user_id/yyjson.h"
#include "distinct_user_id/sajson.h"
#include "distinct_user_id/rapidjson.h"
#include "distinct_user_id/rapidjson_sax.h"
#include "distinct_user_id/nlohmann_json.h"
#include "distinct_user_id/nlohmann_json_sax.h"
#include "find_tweet/simdjson_dom.h"
#include "find_tweet/simdjson_ondemand.h"
#include "find_tweet/yyjson.h"
#include "find_tweet/sajson.h"
#include "find_tweet/rapidjson.h"
#include "find_tweet/rapidjson_sax.h"
#include "find_tweet/nlohmann_json.h"
#include "find_tweet/nlohmann_json_sax.h"
#include "top_tweet/simdjson_dom.h"
#include "top_tweet/simdjson_ondemand.h"
#include "top_tweet/yyjson.h"
#include "top_tweet/sajson.h"
#include "top_tweet/rapidjson.h"
#include "top_tweet/rapidjson_sax.h"
#include "top_tweet/nlohmann_json.h"
#include "top_tweet/nlohmann_json_sax.h"
BENCHMARK_MAIN(); BENCHMARK_MAIN();
+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);
} }
+3 -2
View File
@@ -46,13 +46,14 @@ struct rapidjson : rapidjson_base {
}; };
BENCHMARK_TEMPLATE(distinct_user_id, rapidjson)->UseManualTime(); BENCHMARK_TEMPLATE(distinct_user_id, rapidjson)->UseManualTime();
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
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();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // namespace partial_tweets } // namespace partial_tweets
#endif // SIMDJSON_COMPETITION_RAPIDJSON #endif // SIMDJSON_COMPETITION_RAPIDJSON
+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"; }
+2 -1
View File
@@ -49,13 +49,14 @@ struct yyjson : yyjson_base {
}; };
BENCHMARK_TEMPLATE(distinct_user_id, yyjson)->UseManualTime(); BENCHMARK_TEMPLATE(distinct_user_id, yyjson)->UseManualTime();
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
struct yyjson_insitu : yyjson_base { struct yyjson_insitu : yyjson_base {
bool run(simdjson::padded_string &json, std::vector<uint64_t> &result) { bool run(simdjson::padded_string &json, std::vector<uint64_t> &result) {
return yyjson_base::run(yyjson_read_opts(json.data(), json.size(), YYJSON_READ_INSITU, 0, 0), result); return yyjson_base::run(yyjson_read_opts(json.data(), json.size(), YYJSON_READ_INSITU, 0, 0), result);
} }
}; };
BENCHMARK_TEMPLATE(distinct_user_id, yyjson_insitu)->UseManualTime(); BENCHMARK_TEMPLATE(distinct_user_id, yyjson_insitu)->UseManualTime();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // namespace distinct_user_id } // namespace distinct_user_id
#endif // SIMDJSON_COMPETITION_YYJSON #endif // SIMDJSON_COMPETITION_YYJSON
+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 {
+29 -6
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 {
@@ -116,13 +134,18 @@ 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(simdjson_unused 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
}, quiet) {} #endif
}) {}
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);
} }
+3 -2
View File
@@ -40,13 +40,14 @@ struct rapidjson : rapidjson_base {
}; };
BENCHMARK_TEMPLATE(find_tweet, rapidjson)->UseManualTime(); BENCHMARK_TEMPLATE(find_tweet, rapidjson)->UseManualTime();
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
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();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // namespace find_tweet } // namespace find_tweet
#endif // SIMDJSON_COMPETITION_RAPIDJSON #endif // SIMDJSON_COMPETITION_RAPIDJSON
+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"; }
+2 -2
View File
@@ -40,14 +40,14 @@ struct yyjson : yyjson_base {
} }
}; };
BENCHMARK_TEMPLATE(find_tweet, yyjson)->UseManualTime(); BENCHMARK_TEMPLATE(find_tweet, yyjson)->UseManualTime();
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
struct yyjson_insitu : yyjson_base { struct yyjson_insitu : yyjson_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 yyjson_base::run(yyjson_read_opts(json.data(), json.size(), YYJSON_READ_INSITU, 0, 0), find_id, result); return yyjson_base::run(yyjson_read_opts(json.data(), json.size(), YYJSON_READ_INSITU, 0, 0), find_id, result);
} }
}; };
BENCHMARK_TEMPLATE(find_tweet, yyjson_insitu)->UseManualTime(); BENCHMARK_TEMPLATE(find_tweet, yyjson_insitu)->UseManualTime();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // namespace find_tweet } // namespace find_tweet
#endif // SIMDJSON_COMPETITION_YYJSON #endif // SIMDJSON_COMPETITION_YYJSON
+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
+142
View File
@@ -0,0 +1,142 @@
#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 = rapidjson_base<kParseValidateEncodingFlag|kParseFullPrecisionFlag>;
BENCHMARK_TEMPLATE(json2msgpack, rapidjson)->UseManualTime();
#if SIMDJSON_COMPETITION_ONDEMAND_APPROX
using rapidjson_approx = rapidjson_base<kParseValidateEncodingFlag>;
BENCHMARK_TEMPLATE(json2msgpack, rapidjson_approx)->UseManualTime();
#endif // SIMDJSON_COMPETITION_ONDEMAND_APPROX
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
using rapidjson_insitu = rapidjson_base<kParseValidateEncodingFlag|kParseInsituFlag>;
BENCHMARK_TEMPLATE(json2msgpack, rapidjson_insitu)->UseManualTime();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // 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
+250
View File
@@ -0,0 +1,250 @@
#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);
inline void recursive_processor_ref(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:
// We check that the value is indeed null
// otherwise: an error is thrown.
if(doc.is_null()) {
write_byte(0xc0);
}
break;
case simdjson::ondemand::json_type::array:
case simdjson::ondemand::json_type::object:
default:
// impossible
SIMDJSON_UNREACHABLE();
}
} else {
simdjson::ondemand::value val = doc;
#define SIMDJSON_GCC_COMPILER ((__GNUC__) && !(__clang__) && !(__INTEL_COMPILER))
#if SIMDJSON_GCC_COMPILER
// the GCC compiler does well with by-value passing.
// GCC has superior recursive inlining:
// https://stackoverflow.com/questions/29186186/why-does-gcc-generate-a-faster-program-than-clang-in-this-recursive-fibonacci-co
// https://godbolt.org/z/TeK4doE51
recursive_processor(val);
#else
recursive_processor_ref(val);
#endif
}
if (!doc.at_end()) {
throw "There are unexpectedly tokens after the end of the json in the json2msgpack sample data";
}
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:
// We check that the value is indeed null
// otherwise: an error is thrown.
if(element.is_null()) {
write_byte(0xc0);
}
break;
default:
SIMDJSON_UNREACHABLE();
}
}
void simdjson2msgpack::recursive_processor_ref(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++;
simdjson::ondemand::value v = child.value();
recursive_processor_ref(v);
}
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());
simdjson::ondemand::value v = field.value();
recursive_processor_ref(v);
}
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:
// We check that the value is indeed null
// otherwise: an error is thrown.
if(element.is_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
+123
View File
@@ -0,0 +1,123 @@
#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();
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
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();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // 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;
+10 -9
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"; }
@@ -34,28 +34,29 @@ struct rapidjson_base {
return true; return true;
} }
}; };
#if SIMDJSON_COMPETITION_ONDEMAND_APPROX
struct rapidjson : rapidjson_base { struct rapidjson_approx : 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.Parse<kParseValidateEncodingFlag>(json.data()), result); return rapidjson_base::run(doc.Parse<kParseValidateEncodingFlag>(json.data()), result);
} }
}; };
BENCHMARK_TEMPLATE(kostya, rapidjson)->UseManualTime(); BENCHMARK_TEMPLATE(kostya, rapidjson_approx)->UseManualTime();
#endif // SIMDJSON_COMPETITION_ONDEMAND_APPROX
struct rapidjson_lossless : rapidjson_base { struct rapidjson : 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.Parse<kParseValidateEncodingFlag | kParseFullPrecisionFlag>(json.data()), result); return rapidjson_base::run(doc.Parse<kParseValidateEncodingFlag | kParseFullPrecisionFlag>(json.data()), result);
} }
}; };
BENCHMARK_TEMPLATE(kostya, rapidjson_lossless)->UseManualTime(); BENCHMARK_TEMPLATE(kostya, rapidjson)->UseManualTime();
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
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();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // namespace kostya } // namespace kostya
#endif // SIMDJSON_COMPETITION_RAPIDJSON #endif // SIMDJSON_COMPETITION_RAPIDJSON
+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()});
+3 -3
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!"; }
@@ -53,14 +53,14 @@ struct yyjson : yyjson_base {
} }
}; };
BENCHMARK_TEMPLATE(kostya, yyjson)->UseManualTime(); BENCHMARK_TEMPLATE(kostya, yyjson)->UseManualTime();
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
struct yyjson_insitu : yyjson_base { struct yyjson_insitu : yyjson_base {
bool run(simdjson::padded_string &json, std::vector<point> &result) { bool run(simdjson::padded_string &json, std::vector<point> &result) {
return yyjson_base::run(yyjson_read_opts(json.data(), json.size(), YYJSON_READ_INSITU, 0, 0), result); return yyjson_base::run(yyjson_read_opts(json.data(), json.size(), YYJSON_READ_INSITU, 0, 0), result);
} }
}; };
BENCHMARK_TEMPLATE(kostya, yyjson_insitu)->UseManualTime(); BENCHMARK_TEMPLATE(kostya, yyjson_insitu)->UseManualTime();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // namespace kostya } // namespace kostya
#endif // SIMDJSON_COMPETITION_YYJSON #endif // SIMDJSON_COMPETITION_YYJSON
@@ -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;
+10 -8
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"; }
@@ -31,28 +31,30 @@ struct rapidjson_base {
return true; return true;
} }
}; };
#if SIMDJSON_COMPETITION_ONDEMAND_APPROX
struct rapidjson : rapidjson_base { struct rapidjson_approx : 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.Parse<kParseValidateEncodingFlag>(json.data()), result); return rapidjson_base::run(doc.Parse<kParseValidateEncodingFlag>(json.data()), result);
} }
}; };
BENCHMARK_TEMPLATE(large_random, rapidjson)->UseManualTime(); BENCHMARK_TEMPLATE(large_random, rapidjson_approx)->UseManualTime();
#endif // SIMDJSON_COMPETITION_ONDEMAND_APPROX
struct rapidjson_lossless : rapidjson_base { struct rapidjson : 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.Parse<kParseValidateEncodingFlag | kParseFullPrecisionFlag>(json.data()), result); return rapidjson_base::run(doc.Parse<kParseValidateEncodingFlag | kParseFullPrecisionFlag>(json.data()), result);
} }
}; };
BENCHMARK_TEMPLATE(large_random, rapidjson_lossless)->UseManualTime(); BENCHMARK_TEMPLATE(large_random, rapidjson)->UseManualTime();
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
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();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // namespace large_random } // namespace large_random
+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()});
+3 -3
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!"; }
@@ -51,14 +51,14 @@ struct yyjson : yyjson_base {
} }
}; };
BENCHMARK_TEMPLATE(large_random, yyjson)->UseManualTime(); BENCHMARK_TEMPLATE(large_random, yyjson)->UseManualTime();
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
struct yyjson_insitu : yyjson_base { struct yyjson_insitu : yyjson_base {
bool run(simdjson::padded_string &json, std::vector<point> &result) { bool run(simdjson::padded_string &json, std::vector<point> &result) {
return yyjson_base::run(yyjson_read_opts(json.data(), json.size(), YYJSON_READ_INSITU, 0, 0), result); return yyjson_base::run(yyjson_read_opts(json.data(), json.size(), YYJSON_READ_INSITU, 0, 0), result);
} }
}; };
BENCHMARK_TEMPLATE(large_random, yyjson_insitu)->UseManualTime(); BENCHMARK_TEMPLATE(large_random, yyjson_insitu)->UseManualTime();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // namespace large_random } // namespace large_random
#endif // SIMDJSON_COMPETITION_YYJSON #endif // SIMDJSON_COMPETITION_YYJSON
+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
+19 -34
View File
@@ -1,22 +1,13 @@
// https://github.com/WojciechMula/toys/blob/master/000helpers/linux-perf-events.h
#pragma once #pragma once
#ifdef __linux__ #ifdef __linux__
#ifdef __has_include
#if __has_include(<asm/unistd.h>)
#include <asm/unistd.h> // for __NR_perf_event_open #include <asm/unistd.h> // for __NR_perf_event_open
#else
#warning "Header asm/unistd.h cannot be found though it is a linux system. Are linux headers missing?"
#endif
#else // no __has_include
// Please insure that linux headers have been installed.
#include <asm/unistd.h> // for __NR_perf_event_open
#endif
#include <linux/perf_event.h> // for perf event constants #include <linux/perf_event.h> // for perf event constants
#include <sys/ioctl.h> // for ioctl #include <sys/ioctl.h> // for ioctl
#include <unistd.h> // for syscall #include <unistd.h> // for syscall
#include <cerrno> // for errno #include <cerrno> // for errno
#include <cstring> // for std::memset #include <cstring> // for memset
#include <stdexcept> #include <stdexcept>
#include <iostream> #include <iostream>
@@ -28,13 +19,11 @@ template <int TYPE = PERF_TYPE_HARDWARE> class LinuxEvents {
perf_event_attr attribs{}; perf_event_attr attribs{};
size_t num_events{}; size_t num_events{};
std::vector<uint64_t> temp_result_vec{}; std::vector<uint64_t> temp_result_vec{};
std::vector<uint64_t> result{}; std::vector<uint64_t> ids{};
std::vector<int> fds{};
bool quiet;
public: public:
explicit LinuxEvents(std::vector<int> config_vec, bool _quiet=false) : fd(0), working(true), quiet{_quiet} { explicit LinuxEvents(std::vector<int> config_vec) : fd(0), working(true) {
std::memset(&attribs, 0, sizeof(attribs)); memset(&attribs, 0, sizeof(attribs));
attribs.type = TYPE; attribs.type = TYPE;
attribs.size = sizeof(attribs); attribs.size = sizeof(attribs);
attribs.disabled = 1; attribs.disabled = 1;
@@ -49,7 +38,7 @@ public:
int group = -1; // no group int group = -1; // no group
num_events = config_vec.size(); num_events = config_vec.size();
result.resize(config_vec.size()); ids.resize(config_vec.size());
uint32_t i = 0; uint32_t i = 0;
for (auto config : config_vec) { for (auto config : config_vec) {
attribs.config = config; attribs.config = config;
@@ -57,22 +46,17 @@ public:
if (_fd == -1) { if (_fd == -1) {
report_error("perf_event_open"); report_error("perf_event_open");
} }
fd = _fd; // fd tracks the last _fd value. ioctl(_fd, PERF_EVENT_IOC_ID, &ids[i++]);
fds.push_back(fd);
ioctl(fd, PERF_EVENT_IOC_ID, &result[i++]);
if (group == -1) { if (group == -1) {
group = fd; group = _fd;
fd = _fd;
} }
} }
temp_result_vec.resize(num_events * 2 + 1); temp_result_vec.resize(num_events * 2 + 1);
} }
~LinuxEvents() { ~LinuxEvents() { if (fd != -1) { close(fd); } }
for (auto tfd : fds) {
if (tfd != -1) { close(tfd); }
}
}
inline void start() { inline void start() {
if (fd != -1) { if (fd != -1) {
@@ -97,10 +81,16 @@ public:
} }
} }
// our actual results are in slots 1,3,5, ... of this structure // our actual results are in slots 1,3,5, ... of this structure
// we really should be checking our result obtained earlier to be safe
for (uint32_t i = 1; i < temp_result_vec.size(); i += 2) { for (uint32_t i = 1; i < temp_result_vec.size(); i += 2) {
results[i / 2] = temp_result_vec[i]; results[i / 2] = temp_result_vec[i];
} }
for (uint32_t i = 2; i < temp_result_vec.size(); i += 2) {
if(ids[i/2-1] != temp_result_vec[i]) {
report_error("event mismatch");
}
}
} }
bool is_working() { bool is_working() {
@@ -108,13 +98,8 @@ public:
} }
private: private:
void report_error(const std::string &context) { void report_error(const std::string &) {
if (!quiet) {
if (working) {
std::cerr << (context + ": " + std::string(strerror(errno))) << std::endl;
}
}
working = false; working = false;
} }
}; };
#endif #endif
+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);
} }
+7 -7
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"; }
@@ -67,14 +67,14 @@ struct rapidjson : rapidjson_base {
} }
}; };
BENCHMARK_TEMPLATE(partial_tweets, rapidjson)->UseManualTime(); BENCHMARK_TEMPLATE(partial_tweets, rapidjson)->UseManualTime();
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
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();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // namespace partial_tweets } // namespace partial_tweets
#endif // SIMDJSON_COMPETITION_RAPIDJSON #endif // SIMDJSON_COMPETITION_RAPIDJSON
+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>
+6 -6
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") };
@@ -66,14 +66,14 @@ struct yyjson : yyjson_base {
} }
}; };
BENCHMARK_TEMPLATE(partial_tweets, yyjson)->UseManualTime(); BENCHMARK_TEMPLATE(partial_tweets, yyjson)->UseManualTime();
#if SIMDJSON_COMPETITION_ONDEMAND_INSITU
struct yyjson_insitu : yyjson_base { struct yyjson_insitu : yyjson_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 yyjson_base::run(yyjson_read_opts(json.data(), json.size(), YYJSON_READ_INSITU, 0, 0), result); return yyjson_base::run(yyjson_read_opts(json.data(), json.size(), YYJSON_READ_INSITU, 0, 0), result);
} }
}; };
BENCHMARK_TEMPLATE(partial_tweets, yyjson_insitu)->UseManualTime(); BENCHMARK_TEMPLATE(partial_tweets, yyjson_insitu)->UseManualTime();
#endif // SIMDJSON_COMPETITION_ONDEMAND_INSITU
} // namespace partial_tweets } // namespace partial_tweets
#endif // SIMDJSON_COMPETITION_YYJSON #endif // SIMDJSON_COMPETITION_YYJSON
+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

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