mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
176 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3620e9d151 | |||
| d017cd7ca4 | |||
| d9d1ff5856 | |||
| eb8f2bce14 | |||
| 2a4ff73468 | |||
| 77fc2b8447 | |||
| ba8b66a633 | |||
| 66eec5feaf | |||
| 3964f3e5d2 | |||
| ee8515122d | |||
| 5d35e7ca1f | |||
| deefc88b9c | |||
| c80dda7c58 | |||
| d2954ef68b | |||
| ac719827ff | |||
| 6ea77392a7 | |||
| e2f879751c | |||
| bf7834179c | |||
| 69ab8848bf | |||
| 7288323e36 | |||
| 3f381cf3ee | |||
| 52406402ed | |||
| 799d8e3fc9 | |||
| 6c647d9f3b | |||
| 8519e24f12 | |||
| fffb62743c | |||
| c888075f8d | |||
| 9b8aac5f22 | |||
| 40b414d184 | |||
| c85e8a7db1 | |||
| 83f390f8e7 | |||
| 82563dcf70 | |||
| 646bd3f2c3 | |||
| 4b0a908bb2 | |||
| 4c98e51c53 | |||
| 58e3d5d9cc | |||
| a22a92dc72 | |||
| c4654553dd | |||
| 5997f82c37 | |||
| bee410b315 | |||
| b115e3ef61 | |||
| 669229df5d | |||
| b6a2286e62 | |||
| 3a97c57773 | |||
| e1c6a778f8 | |||
| d413dd5b0e | |||
| a33fdc2770 | |||
| 87f5f7a250 | |||
| 9923d27994 | |||
| 876be23545 | |||
| 2028bdaeac | |||
| 1ac3a00ca9 | |||
| 6d7cc2c7c1 | |||
| 61a52287fc | |||
| 37a9aaad48 | |||
| 78325888ea | |||
| a90cb5d900 | |||
| 34a01ec3af | |||
| e510ed2774 | |||
| dabac13dde | |||
| aef7111c05 | |||
| 0c08894a54 | |||
| 2fe3a1467d | |||
| 167a46a0e7 | |||
| 2b532489cc | |||
| 85163df88c | |||
| 6a5be0f0db | |||
| 710a3c7241 | |||
| c93e02e172 | |||
| 517143aec4 | |||
| 9feda5e703 | |||
| cda198b7b9 | |||
| aad17a6a8d | |||
| 32d072a208 | |||
| 5eab555053 | |||
| 6430fbd39a | |||
| 4d2fc31b27 | |||
| 33610b59eb | |||
| 23290ae48d | |||
| eb3a085e0f | |||
| 4c8ec35a48 | |||
| 88bf5cb6d9 | |||
| 9b0435d864 | |||
| ddecadde86 | |||
| 02bee7d1b9 | |||
| 6ef555e6fb | |||
| 6952f8dfce | |||
| 03d0a4731a | |||
| 185ff4e8fe | |||
| 5bf6d9f3f0 | |||
| 2fa729922e | |||
| ebd09cb2a3 | |||
| 3978b9f159 | |||
| edc36a87ab | |||
| 6060be2fdf | |||
| 3251f61c9d | |||
| 561ffcd519 | |||
| 5541e78402 | |||
| 9a9ed0e2da | |||
| bca8d3e277 | |||
| 97196fa969 | |||
| 23fab307ca | |||
| 0a14e05ec7 | |||
| b88f831dbd | |||
| 71a73c2c47 | |||
| 07603aa7f7 | |||
| b8a6b889c7 | |||
| 7898234bb3 | |||
| f52533538a | |||
| 3bb2f0a186 | |||
| d6551bf278 | |||
| 0173eaaad7 | |||
| 5459dbd6c6 | |||
| 9c45f1f292 | |||
| 665cbba159 | |||
| a26f664907 | |||
| 17cb457ffd | |||
| 8b2af0473a | |||
| f1bfa43385 | |||
| 29fbbee852 | |||
| baa7d961ce | |||
| 6412b27c7e | |||
| 503da5ec83 | |||
| 9dd6e9c959 | |||
| 6db330c1a2 | |||
| 993ac4b87c | |||
| 35e87896f0 | |||
| f7e281cadc | |||
| 13405afd4b | |||
| 24b44309fb | |||
| e11ad58aad | |||
| 1875ed6550 | |||
| 80d26298a0 | |||
| 25b5015c09 | |||
| 26f8c566c7 | |||
| ff77ac801e | |||
| e0699994ef | |||
| 68ba9a1b2a | |||
| 6fed6bd29b | |||
| cc24bb4114 | |||
| 14ec0ca8f4 | |||
| 8dabd02c3a | |||
| c9692005fd | |||
| 2e0a9397c9 | |||
| f7922075c3 | |||
| b2e20e04c9 | |||
| adc9d18efd | |||
| bf849e3619 | |||
| c09e8dc225 | |||
| 5bf585ef02 | |||
| caff09cafc | |||
| f043db4dca | |||
| e3bd0828d1 | |||
| 9408298e0e | |||
| 573bbac2d2 | |||
| ac78c625df | |||
| 390a66c6e8 | |||
| 210e0a56a1 | |||
| 084f662f32 | |||
| c878ff2500 | |||
| 06afe9ecb3 | |||
| e658502adb | |||
| 6e7d415040 | |||
| 2ccd5b9c97 | |||
| 1cdcbf79b3 | |||
| 7013ed98cc | |||
| b383c717d7 | |||
| b8743bced0 | |||
| ae9ba2bed2 | |||
| 939844d79f | |||
| 4f4e81668e | |||
| bb54946b78 | |||
| 4dec6ed5a7 | |||
| 1dfd48195d | |||
| 23afc6b695 | |||
| 80bc9e5051 |
@@ -1,5 +1,8 @@
|
||||
CompileFlags:
|
||||
CompilationDatabase: build
|
||||
Add:
|
||||
- -Werror -Wall -Wextra -Weffc++ -Wsign-compare -Wshadow -Wwrite-strings -Wpointer-arith -Winit-self -Wconversion -Wno-sign-conversion
|
||||
- -Wundefined-inline
|
||||
Diagnostics:
|
||||
Suppress:
|
||||
- misc-unused-alias-decls
|
||||
@@ -16,10 +19,28 @@ If:
|
||||
CompileFlags:
|
||||
Add:
|
||||
- -Wno-unneeded-internal-declaration
|
||||
- -Wno-undefined-inline # TODO fix and remove these violations
|
||||
- -Wno-undefined-internal # TODO fix and remove these violations
|
||||
- -Wno-unused-function
|
||||
- -Wno-unused-const-variable
|
||||
Diagnostics:
|
||||
Suppress:
|
||||
- pp_including_mainfile_in_preamble
|
||||
---
|
||||
# Amalgamated files that require or partly define an implementation
|
||||
If:
|
||||
PathMatch:
|
||||
- .*/(arm64|fallback|haswell|icelake|ppc64|westmere)/begin.h
|
||||
- .*/generic/.*
|
||||
Diagnostics:
|
||||
Suppress:
|
||||
- pragma_attribute_no_pop_eof
|
||||
---
|
||||
# clang has a bad time detecting the push/pop together in src/ for some reason
|
||||
If:
|
||||
PathMatch:
|
||||
- include/simdjson/.*/end.h
|
||||
- src/(arm64|fallback|haswell|icelake|ppc64|westmere).cpp
|
||||
Diagnostics:
|
||||
Suppress:
|
||||
- pragma_attribute_no_pop_eof
|
||||
- pragma_attribute_stack_mismatch
|
||||
|
||||
@@ -45,11 +45,15 @@ It is fine to report bugs against our main branch, but if that is what you are d
|
||||
|
||||
**Configuration (please complete the following information if relevant)**
|
||||
- OS: [e.g. Ubuntu 16.04.6 LTS]
|
||||
- Compiler [e.g. Apple clang version 11.0.3 (clang-1103.0.32.59) x86_64-apple-darwin19.4.0]
|
||||
- Compiler* [e.g. Apple clang version 11.0.3 (clang-1103.0.32.59) x86_64-apple-darwin19.4.0]
|
||||
- Version [e.g. 22]
|
||||
- Optimization setting (e.g., -O3)
|
||||
|
||||
We support up-to-date 64-bit ARM and x64 FreeBSD, macOS, Windows and Linux systems. Please ensure that your configuration is supported before labelling the issue as a bug. In particular, we do not support legacy 32-bit systems.
|
||||
We support up-to-date 64-bit ARM and x64 FreeBSD, macOS, Windows and Linux systems. Please ensure that your configuration is supported before labelling the issue as a bug.
|
||||
|
||||
* We do not support unreleased or experimental compilers. If you encounter an issue with a
|
||||
pre-release version of a compiler, do not report it as a bug to simdjson. However, we always
|
||||
invite contributions either in the form an analysis or of a code contribution.
|
||||
|
||||
**Indicate whether you are willing or able to provide a bug fix as a pull request**
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ A clear and concise description of any alternative solutions or features you've
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
** Are you willing to contribute code or documentation toward this new feature? **
|
||||
**Are you willing to contribute code or documentation toward this new feature?**
|
||||
If you plan to contribute to simdjson, please read 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
|
||||
|
||||
@@ -9,8 +9,8 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
image: debian:testing
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install Doxygen
|
||||
run: sudo apt-get install doxygen graphviz -y
|
||||
- run: mkdir docs
|
||||
|
||||
@@ -6,7 +6,7 @@ jobs:
|
||||
whitespace:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Remove whitespace and check the diff
|
||||
run: |
|
||||
set -eu
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
# fuzzers that change behaviour with SIMDJSON_FORCE_IMPLEMENTATION
|
||||
defaultimplfuzzers: atpointer dump dump_raw_tape element minify parser print_json
|
||||
# fuzzers that loop over the implementations themselves, or don't need to switch.
|
||||
implfuzzers: implementations minifyimpl ndjson ondemand padded utf8 # TODO add singlestage
|
||||
implfuzzers: implementations minifyimpl ndjson ondemand padded utf8
|
||||
implementations: haswell westmere fallback
|
||||
UBSAN_OPTIONS: halt_on_error=1
|
||||
MAXLEN: -max_len=4000
|
||||
@@ -34,17 +34,18 @@ jobs:
|
||||
sudo apt update
|
||||
sudo apt-get install --quiet ninja-build valgrind zip unzip lsb-release wget software-properties-common gnupg
|
||||
wget https://apt.llvm.org/llvm.sh
|
||||
sudo apt-get purge --auto-remove llvm python3-lldb-15 llvm-15
|
||||
chmod +x llvm.sh
|
||||
sudo ./llvm.sh $CLANGVERSION
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
id: cache-corpus
|
||||
with:
|
||||
path: out/
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
name: LoongArch64-CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
loongarch64:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform:
|
||||
- { toolchain-version: 2023.08.08 }
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install build requirements
|
||||
run: |
|
||||
sudo apt-get update -y
|
||||
sudo apt-get install -y --no-install-recommends cmake
|
||||
|
||||
- uses: actions/cache/restore@v4
|
||||
id: restore-cache
|
||||
with:
|
||||
path: /opt/cross-tools
|
||||
key: loongarch64-${{ matrix.platform.toolchain-version }}
|
||||
|
||||
- name: Download LoongArch64 gcc+glibc toolchain
|
||||
if: ${{ !steps.restore-cache.outputs.cache-hit }}
|
||||
run: |
|
||||
url="https://github.com/loongson/build-tools/releases/download/${{ matrix.platform.toolchain-version }}/x86_64-cross-tools-loongarch64-gcc-libc.tar.xz"
|
||||
|
||||
wget "$url" -O /tmp/toolchain.tar.xz
|
||||
|
||||
mkdir -p /opt
|
||||
tar -C /opt -x -f /tmp/toolchain.tar.xz
|
||||
|
||||
- uses: actions/cache/save@v3
|
||||
if: ${{ !steps.restore-cache.outputs.cache-hit }}
|
||||
with:
|
||||
path: /opt/cross-tools
|
||||
key: loongarch64-${{ matrix.platform.toolchain-version }}
|
||||
|
||||
- name: setup Loongarch64 build environment
|
||||
run: |
|
||||
echo "/opt/cross-tools/bin" >> $GITHUB_PATH
|
||||
echo "CC=loongarch64-unknown-linux-gnu-gcc" >> $GITHUB_ENV
|
||||
echo "CXX=loongarch64-unknown-linux-gnu-g++" >> $GITHUB_ENV
|
||||
- name: configure
|
||||
run: cmake -B build -DCMAKE_SYSTEM_PROCESSOR=loongarch64 -DARCH=lonngarch64 -DCMAKE_SYSTEM_NAME=Linux -DCMAKE_C_COMPILER=loongarch64-unknown-linux-gnu-gcc -DCMAKE_CXX_COMPILER=loongarch64-unknown-linux-gnu-g++
|
||||
- name: build
|
||||
run: cmake --build build
|
||||
@@ -9,8 +9,8 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
@@ -31,3 +31,14 @@ jobs:
|
||||
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 .
|
||||
- name: Use cmake (shared)
|
||||
run: |
|
||||
mkdir buildshared &&
|
||||
cd buildshared &&
|
||||
cmake -DSIMDJSON_GOOGLE_BENCHMARKS=ON -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||
cmake --build . &&
|
||||
ctest --output-on-failure -LE explicitonly -j &&
|
||||
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 buildshared && cd buildshared && cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildshared/destination .. && cmake --build .
|
||||
|
||||
@@ -24,8 +24,8 @@ jobs:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
|
||||
@@ -26,8 +26,8 @@ jobs:
|
||||
CMAKE_GENERATOR: Ninja
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
name: short fuzz on the power arch
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
armv7_job:
|
||||
if: >-
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
# The host should always be Linux
|
||||
runs-on: ubuntu-20.04
|
||||
name: Build on ubuntu-20.04 ppc64le
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: uraimo/run-on-arch-action@v2.0.5
|
||||
name: Run commands
|
||||
id: runcmd
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
with:
|
||||
arch: ppc64le
|
||||
distro: buster
|
||||
|
||||
# Not required, but speeds up builds by storing container images in
|
||||
# a GitHub package registry.
|
||||
githubToken: ${{ github.token }}
|
||||
|
||||
run: |
|
||||
export CLANGSUFFIX="-7"
|
||||
apt-get -qq update
|
||||
apt-get install -q -y clang-7 libfuzzer-7-dev git wget zip ninja-build gnupg software-properties-common
|
||||
wget -q -O - "https://raw.githubusercontent.com/simdjson/debian-ppa/master/key.gpg" | apt-key add -
|
||||
apt-add-repository "deb https://raw.githubusercontent.com/simdjson/debian-ppa/master simdjson main"
|
||||
apt-get -qq update
|
||||
apt-get purge cmake cmake-data
|
||||
apt-get -t simdjson -y install cmake
|
||||
mkdir -p build ; cd build
|
||||
cmake .. -GNinja \
|
||||
-DCMAKE_CXX_COMPILER=clang++$CLANGSUFFIX \
|
||||
-DCMAKE_C_COMPILER=clang$CLANGSUFFIX \
|
||||
-DBUILD_SHARED_LIBS=OFF \
|
||||
-DSIMDJSON_DEVELOPER_MODE=ON \
|
||||
-DSIMDJSON_ENABLE_FUZZING=On \
|
||||
-DSIMDJSON_COMPETITION=OFF \
|
||||
-DSIMDJSON_GOOGLE_BENCHMARKS=OFF \
|
||||
-DSIMDJSON_DISABLE_DEPRECATED_API=On \
|
||||
-DSIMDJSON_FUZZ_LDFLAGS=-lFuzzer \
|
||||
-DCMAKE_CXX_FLAGS="-fsanitize=fuzzer-no-link -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=" \
|
||||
-DCMAKE_C_FLAGS="-fsanitize=fuzzer-no-link" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DSIMDJSON_FUZZ_LINKMAIN=Off
|
||||
cd ..
|
||||
builddir=build
|
||||
cmake --build $builddir
|
||||
wget -O corpus.tar.gz https://readonly:readonly@www.pauldreik.se/fuzzdata/index.php?project=simdjson
|
||||
tar xf corpus.tar.gz
|
||||
fuzzernames=$(cmake --build $builddir --target print_all_fuzzernames |tail -n1)
|
||||
for fuzzer in $fuzzernames ; do
|
||||
exe=$builddir/fuzz/$fuzzer
|
||||
shortname=$(echo $fuzzer |cut -f2- -d_)
|
||||
echo found fuzzer $shortname with executable $exe
|
||||
mkdir -p out/$shortname
|
||||
others=$(find out -type d -not -name $shortname -not -name out -not -name cmin)
|
||||
$exe -max_total_time=20 -max_len=4000 out/$shortname $others
|
||||
echo "*************************************************************************"
|
||||
done
|
||||
echo "all is good, no errors found in any of these fuzzers: $fuzzernames"
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
name: Test
|
||||
id: runcmd
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
name: Ubuntu riscv64 (GCC 11)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
name: Test
|
||||
id: runcmd
|
||||
with:
|
||||
arch: riscv64
|
||||
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
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
name: Test
|
||||
id: runcmd
|
||||
|
||||
@@ -15,8 +15,8 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
|
||||
@@ -12,8 +12,8 @@ jobs:
|
||||
CXX: g++-8
|
||||
CC: gcc-8
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
|
||||
@@ -9,8 +9,8 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
|
||||
@@ -9,8 +9,8 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
|
||||
@@ -3,14 +3,14 @@ name: Ubuntu 20.04 CI (GCC 9) With Memory Sanitizer
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
ubuntu-build:
|
||||
ubuntu-build-address-sanitizier:
|
||||
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
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
@@ -21,6 +21,17 @@ jobs:
|
||||
cmake -DSIMDJSON_SANITIZE=ON -DCMAKE_BUILD_TYPE=Debug -DSIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_DEVELOPER_MODE=ON -DBUILD_SHARED_LIBS=OFF .. &&
|
||||
cmake --build . &&
|
||||
ctest --output-on-failure -LE explicitonly -j
|
||||
ubuntu-build-undefined-sanitizer:
|
||||
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@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
- name: Use cmake with undefined sanitizer
|
||||
run: |
|
||||
mkdir builddebugundefsani &&
|
||||
|
||||
@@ -9,11 +9,25 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
- name: Use cmake to build just the library
|
||||
run: |
|
||||
mkdir buildjustlib &&
|
||||
cd buildjustlib &&
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_DEVELOPER_MODE=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||
cmake --build . &&
|
||||
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 &&
|
||||
cd ../tests/installation_tests/find &&
|
||||
mkdir buildjustlib &&
|
||||
cd buildjustlib &&
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildjustlib/destination .. &&
|
||||
cmake --build .
|
||||
- name: Use cmake
|
||||
run: |
|
||||
mkdir builddebug &&
|
||||
|
||||
@@ -9,13 +9,11 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
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 &&
|
||||
|
||||
@@ -9,13 +9,11 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
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 &&
|
||||
|
||||
@@ -9,8 +9,8 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
|
||||
@@ -9,13 +9,11 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
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 &&
|
||||
|
||||
@@ -8,8 +8,8 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
name: Ubuntu 20.04 CI (GCC 9) with Thread Sanitizer
|
||||
name: Ubuntu 22.04 CI (GCC 12) with Thread Sanitizer
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
@@ -7,10 +7,10 @@ jobs:
|
||||
if: >-
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
run: |
|
||||
mkdir build &&
|
||||
cd build &&
|
||||
cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_SANITIZE_THREADS=ON .. &&
|
||||
CXX=g++-12 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
|
||||
@@ -9,11 +9,25 @@ jobs:
|
||||
! contains(toJSON(github.event.commits.*.message), '[skip github]')
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
- name: Use cmake to build just the library
|
||||
run: |
|
||||
mkdir buildjustlib &&
|
||||
cd buildjustlib &&
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DSIMDJSON_DEVELOPER_MODE=OFF -DCMAKE_INSTALL_PREFIX:PATH=destination .. &&
|
||||
cmake --build . &&
|
||||
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 &&
|
||||
cd ../tests/installation_tests/find &&
|
||||
mkdir buildjustlib &&
|
||||
cd buildjustlib &&
|
||||
cmake -DCMAKE_INSTALL_PREFIX:PATH=../../../buildjustlib/destination .. &&
|
||||
cmake --build .
|
||||
- name: Use cmake
|
||||
run: |
|
||||
mkdir builddebug &&
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
name: Ubuntu 24.04 CI
|
||||
|
||||
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-24.04
|
||||
strategy:
|
||||
matrix:
|
||||
shared: [ON, OFF]
|
||||
cxx: [g++-13, clang++-16]
|
||||
sanitizer: [ON, OFF]
|
||||
steps:
|
||||
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
|
||||
- name: Prepare
|
||||
run: cmake -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_SANITIZE=${{matrix.sanitizer}} -DBUILD_SHARED_LIBS=${{matrix.shared}} -B build
|
||||
env:
|
||||
CXX: ${{matrix.cxx}}
|
||||
- name: Build
|
||||
run: cmake --build build -j=2
|
||||
- name: Test
|
||||
run: ctest --output-on-failure --test-dir build
|
||||
@@ -12,10 +12,11 @@ jobs:
|
||||
include:
|
||||
- {arch: ARM}
|
||||
- {arch: ARM64}
|
||||
- {arch: ARM64EC}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Use cmake
|
||||
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_SYSTEM_VERSION="10.0.22621.0" -DCMAKE_CROSSCOMPILING=1 -DSIMDJSON_DEVELOPER_MODE=ON -D SIMDJSON_GOOGLE_BENCHMARKS=OFF -DSIMDJSON_EXCEPTIONS=OFF -B build &&
|
||||
cmake --build build --verbose
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
- {gen: Visual Studio 17 2022, arch: x64, shared: OFF}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -DSIMDJSON_CXX_STANDARD=20 -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DBUILD_SHARED_LIBS=${{matrix.shared}} -B build
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
- {gen: Visual Studio 17 2022, arch: x64, shared: OFF}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -DBUILD_SHARED_LIBS=${{matrix.shared}} -B build
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
- {gen: Visual Studio 17 2022, arch: x64}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Configure
|
||||
run: |
|
||||
cmake -G "${{matrix.gen}}" -A ${{matrix.arch}} -T ClangCL -DSIMDJSON_DEVELOPER_MODE=ON -DSIMDJSON_COMPETITION=OFF -B build
|
||||
|
||||
@@ -7,8 +7,8 @@ jobs:
|
||||
name: windows-vs17
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: dependencies/.cache
|
||||
key: ${{ hashFiles('dependencies/CMakeLists.txt') }}
|
||||
|
||||
Vendored
+12
-1
@@ -98,6 +98,17 @@
|
||||
"queue": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"ranges": "cpp",
|
||||
"span": "cpp"
|
||||
"span": "cpp",
|
||||
"__verbose_abort": "cpp",
|
||||
"charconv": "cpp",
|
||||
"source_location": "cpp",
|
||||
"strstream": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numbers": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"cfenv": "cpp"
|
||||
}
|
||||
}
|
||||
+50
-5
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
|
||||
project(
|
||||
simdjson
|
||||
# The version number is modified by tools/release.py
|
||||
VERSION 3.2.1
|
||||
VERSION 3.9.4
|
||||
DESCRIPTION "Parsing gigabytes of JSON per second"
|
||||
HOMEPAGE_URL "https://simdjson.org/"
|
||||
LANGUAGES CXX C
|
||||
@@ -20,8 +20,10 @@ string(
|
||||
# ---- Options, variables ----
|
||||
|
||||
# These version numbers are modified by tools/release.py
|
||||
set(SIMDJSON_LIB_VERSION "16.0.0" CACHE STRING "simdjson library version")
|
||||
set(SIMDJSON_LIB_SOVERSION "16" CACHE STRING "simdjson library soversion")
|
||||
set(SIMDJSON_LIB_VERSION "22.0.0" CACHE STRING "simdjson library version")
|
||||
set(SIMDJSON_LIB_SOVERSION "22" CACHE STRING "simdjson library soversion")
|
||||
|
||||
option(SIMDJSON_BUILD_STATIC_LIB "Build simdjson_static library along with simdjson" OFF)
|
||||
|
||||
option(SIMDJSON_ENABLE_THREADS "Link with thread support" ON)
|
||||
|
||||
@@ -56,8 +58,17 @@ include(cmake/developer-options.cmake)
|
||||
|
||||
# ---- simdjson library ----
|
||||
|
||||
add_library(simdjson src/simdjson.cpp)
|
||||
set(SIMDJSON_SOURCES src/simdjson.cpp)
|
||||
|
||||
add_library(simdjson ${SIMDJSON_SOURCES})
|
||||
add_library(simdjson::simdjson ALIAS simdjson)
|
||||
set(SIMDJSON_LIBRARIES simdjson)
|
||||
|
||||
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||
add_library(simdjson_static STATIC ${SIMDJSON_SOURCES})
|
||||
add_library(simdjson::simdjson_static ALIAS simdjson_static)
|
||||
list(APPEND SIMDJSON_LIBRARIES simdjson_static)
|
||||
endif()
|
||||
|
||||
set_target_properties(
|
||||
simdjson PROPERTIES
|
||||
@@ -95,6 +106,24 @@ if(
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(loongarch64)$")
|
||||
option(SIMDJSON_PREFER_LSX "Prefer LoongArch SX" ON)
|
||||
include(CheckCXXCompilerFlag)
|
||||
check_cxx_compiler_flag(-mlasx COMPILER_SUPPORTS_LASX)
|
||||
check_cxx_compiler_flag(-mlsx COMPILER_SUPPORTS_LSX)
|
||||
if(COMPILER_SUPPORTS_LASX AND NOT SIMDJSON_PREFER_LSX)
|
||||
simdjson_add_props(
|
||||
target_compile_options PRIVATE
|
||||
-mlasx
|
||||
)
|
||||
elseif(COMPILER_SUPPORTS_LSX)
|
||||
simdjson_add_props(
|
||||
target_compile_options PRIVATE
|
||||
-mlsx
|
||||
)
|
||||
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
|
||||
@@ -117,6 +146,9 @@ if(SIMDJSON_ENABLE_THREADS)
|
||||
endif()
|
||||
|
||||
simdjson_apply_props(simdjson)
|
||||
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||
simdjson_apply_props(simdjson_static)
|
||||
endif()
|
||||
|
||||
# ---- Install rules ----
|
||||
|
||||
@@ -138,7 +170,6 @@ install(
|
||||
ARCHIVE COMPONENT simdjson_Development
|
||||
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
)
|
||||
|
||||
configure_file(cmake/simdjson-config.cmake.in simdjson-config.cmake @ONLY)
|
||||
|
||||
write_basic_package_version_file(
|
||||
@@ -167,6 +198,20 @@ install(
|
||||
COMPONENT simdjson_Development
|
||||
)
|
||||
|
||||
if(SIMDJSON_BUILD_STATIC_LIB)
|
||||
install(
|
||||
TARGETS simdjson_static
|
||||
EXPORT simdjson_staticTargets
|
||||
ARCHIVE COMPONENT simdjson_Development
|
||||
)
|
||||
install(
|
||||
EXPORT simdjson_staticTargets
|
||||
NAMESPACE simdjson::
|
||||
DESTINATION "${SIMDJSON_INSTALL_CMAKEDIR}"
|
||||
COMPONENT simdjson_Development
|
||||
)
|
||||
endif()
|
||||
|
||||
# pkg-config
|
||||
include(cmake/JoinPaths.cmake)
|
||||
join_paths(PKGCONFIG_INCLUDEDIR "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
|
||||
+2
-1
@@ -52,10 +52,11 @@ General Guidelines
|
||||
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.
|
||||
- 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. We avoid contractions (isn't, aren't) in the comments.
|
||||
- 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.
|
||||
- Provide tests for any new feature. We will not merge a new feature without tests.
|
||||
- Run before/after benchmarks so that we can appreciate the effect of the changes on the performance.
|
||||
|
||||
Pull Requests
|
||||
--------------
|
||||
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = simdjson
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = "3.2.1"
|
||||
PROJECT_NUMBER = "3.9.4"
|
||||
|
||||
# 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
|
||||
|
||||
+3
-7
@@ -80,7 +80,7 @@ simdjson's source structure, from the top level, looks like this:
|
||||
* simdjson/internal/*.h: the `simdjson::internal` namespace. Private classes and functions used by the rest of simdjson.
|
||||
* simdjson/dom.h: the `simdjson::dom` namespace. Includes all public DOM classes.
|
||||
* simdjson/dom/*.h: Declarations/definitions for individual DOM classes.
|
||||
* simdjson/arm64|fallback|haswell|icelake|ppc64|westmere.h: `simdjson::<implementation>` namesapce. Common implementation-specific tools like number and string parsing, as well as minification.
|
||||
* simdjson/arm64|fallback|haswell|icelake|ppc64|westmere.h: `simdjson::<implementation>` namespace. Common implementation-specific tools like number and string parsing, as well as minification.
|
||||
* simdjson/arm64|fallback|haswell|icelake|ppc64|westmere/*.h: implementation-specific functions such as , etc.
|
||||
* simdjson/generic/*.h: the bulk of the actual code, written generically and compiled for each implementation, using functions defined in the implementation's .h files.
|
||||
* simdjson/generic/dependencies.h: dependencies on common, non-implementation-specific simdjson classes. This will be included before including amalgamated.h.
|
||||
@@ -283,8 +283,6 @@ If your compiler does not default on C++11 support or better you may get failing
|
||||
|
||||
Note that the name of directory (`build`) is arbitrary, you can name it as you want (e.g., `buildgcc`) and you can have as many different such directories as you would like (one per configuration).
|
||||
|
||||
|
||||
|
||||
## 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).
|
||||
@@ -304,17 +302,15 @@ Though having Visual Studio installed is necessary, one can build simdjson using
|
||||
- `mkdir build`
|
||||
- `cd build`
|
||||
- `cmake ..`
|
||||
- `cmake --build . -config Release`
|
||||
- `cmake --build . --config Release`
|
||||
|
||||
|
||||
Furthermore, if you have installed LLVM clang on Windows, for example as a component of Visual Studio 2019, you can configure and build simdjson using LLVM clang on Windows using cmake:
|
||||
|
||||
|
||||
- `mkdir build`
|
||||
- `cd build`
|
||||
- `cmake -T ClangCL ..`
|
||||
- `cmake --build . -config Release`
|
||||
|
||||
- `cmake --build . --config Release`
|
||||
|
||||
## Various References
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
|
||||
[/badge.svg)](https://simdjson.org/plots.html)
|
||||

|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:simdjson)
|
||||

|
||||
[![][license img]][license]
|
||||
|
||||
[](https://simdjson.github.io/simdjson/)
|
||||
@@ -31,6 +29,7 @@ Table of Contents
|
||||
* [Real-world usage](#real-world-usage)
|
||||
* [Quick Start](#quick-start)
|
||||
* [Documentation](#documentation)
|
||||
* [Godbolt](#godbolt)
|
||||
* [Performance results](#performance-results)
|
||||
* [Bindings and Ports of simdjson](#bindings-and-ports-of-simdjson)
|
||||
* [About simdjson](#about-simdjson)
|
||||
@@ -42,8 +41,10 @@ Table of Contents
|
||||
Real-world usage
|
||||
----------------
|
||||
|
||||
- [Node.js](https://nodejs.org/)
|
||||
- [ClickHouse](https://github.com/ClickHouse/ClickHouse)
|
||||
- [Facebook/Meta Velox](https://velox-lib.io)
|
||||
- [Meta Velox](https://velox-lib.io)
|
||||
- [Google Pax](https://github.com/google/paxml)
|
||||
- [milvus](https://github.com/milvus-io/milvus)
|
||||
- [Clang Build Analyzer](https://github.com/aras-p/ClangBuildAnalyzer)
|
||||
- [Shopify HeapProfiler](https://github.com/Shopify/heap-profiler)
|
||||
@@ -58,6 +59,7 @@ Real-world usage
|
||||
- [vast](https://github.com/tenzir/vast)
|
||||
- [ada-url](https://github.com/ada-url/ada)
|
||||
- [fastgron](https://github.com/adamritter/fastgron)
|
||||
- [WasmEdge](https://wasmedge.org)
|
||||
|
||||
If you are planning to use simdjson in a product, please work from one of our releases.
|
||||
|
||||
@@ -68,9 +70,9 @@ The simdjson library is easily consumable with a single .h and .cpp file.
|
||||
|
||||
0. Prerequisites: `g++` (version 7 or better) or `clang++` (version 6 or better), and a 64-bit
|
||||
system with a command-line shell (e.g., Linux, macOS, freeBSD). We also support programming
|
||||
environments like Visual Studio and Xcode, but different steps are needed.
|
||||
environments like Visual Studio and Xcode, but different steps are needed. Users of clang++ may need to specify the C++ version (e.g., `c++ -std=c++17`) since clang++ tends to default on C++98.
|
||||
1. Pull [simdjson.h](singleheader/simdjson.h) and [simdjson.cpp](singleheader/simdjson.cpp) into a
|
||||
directory, along with the sample file [twitter.json](jsonexamples/twitter.json).
|
||||
directory, along with the sample file [twitter.json](jsonexamples/twitter.json). You can download them with the `wget` utility:
|
||||
|
||||
```
|
||||
wget https://raw.githubusercontent.com/simdjson/simdjson/master/singleheader/simdjson.h https://raw.githubusercontent.com/simdjson/simdjson/master/singleheader/simdjson.cpp https://raw.githubusercontent.com/simdjson/simdjson/master/jsonexamples/twitter.json
|
||||
@@ -95,6 +97,7 @@ int main(void) {
|
||||
100 results.
|
||||
```
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
@@ -106,11 +109,12 @@ Usage documentation is available:
|
||||
how you can work with it.
|
||||
* [API](https://simdjson.github.io/simdjson/) contains the automatically generated API documentation.
|
||||
|
||||
Godbolt
|
||||
-------------
|
||||
|
||||
Some users may want to browse code along with the compiled assembly. You want to check out the following lists of examples:
|
||||
|
||||
* [simdjson examples with errors handled through exceptions](https://godbolt.org/z/98Kx9Kqjn)
|
||||
* [simdjson examples with errors without exceptions](https://godbolt.org/z/PKG7GdbPo)
|
||||
* [simdjson examples with errors handled through exceptions](https://godbolt.org/z/7G5qE4sr9)
|
||||
* [simdjson examples with errors without exceptions](https://godbolt.org/z/e9dWb9E4v)
|
||||
|
||||
Performance results
|
||||
-------------------
|
||||
@@ -165,6 +169,8 @@ We distinguish between "bindings" (which just wrap the C++ code) and a port to a
|
||||
- [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.
|
||||
- [gemmaJSON](https://github.com/sainttttt/gemmaJSON): Nim JSON parser based on simdjson bindings.
|
||||
- [simdjson-java](https://github.com/simdjson/simdjson-java): Java port.
|
||||
|
||||
About simdjson
|
||||
--------------
|
||||
@@ -173,7 +179,11 @@ The simdjson library takes advantage of modern microarchitectures, parallelizing
|
||||
instructions, reducing branch misprediction, and reducing data dependency to take advantage of each
|
||||
CPU's multiple execution cores.
|
||||
|
||||
Some people [enjoy reading our paper](https://arxiv.org/abs/1902.08318): A description of the design
|
||||
Our default front-end is called On Demand, and we wrote a paper about it:
|
||||
|
||||
- John Keiser, Daniel Lemire, [On-Demand JSON: A Better Way to Parse Documents?](http://arxiv.org/abs/2312.17149), Software: Practice and Experience 54 (6), 2024.
|
||||
|
||||
Some people [enjoy reading the first (2019) simdjson paper](https://arxiv.org/abs/1902.08318): A description of the design
|
||||
and implementation of simdjson is in our research article:
|
||||
- Geoff Langdale, Daniel Lemire, [Parsing Gigabytes of JSON per Second](https://arxiv.org/abs/1902.08318), VLDB Journal 28 (6), 2019.
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# Security Policy
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please use the following contact information for reporting a vulnerability:
|
||||
|
||||
- [Daniel Lemire](https://github.com/lemire) - daniel@lemire.me
|
||||
@@ -26,6 +26,9 @@ if (TARGET benchmark::benchmark)
|
||||
if(TARGET nlohmann_json)
|
||||
target_link_libraries(bench_ondemand PRIVATE nlohmann_json)
|
||||
endif()
|
||||
if(TARGET boostjson)
|
||||
target_link_libraries(bench_ondemand PRIVATE boostjson)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "amazon_cellphones.h"
|
||||
|
||||
namespace amazon_cellphones {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
template<bool threaded>
|
||||
struct simdjson_singlestage {
|
||||
using StringType = std::string;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
||||
#ifdef SIMDJSON_THREADS_ENABLED
|
||||
parser.threaded = threaded;
|
||||
#endif
|
||||
singlestage::document_stream stream = parser.iterate_many(json);
|
||||
singlestage::document_stream::iterator i = stream.begin();
|
||||
++i; // Skip first line
|
||||
for (;i != stream.end(); ++i) {
|
||||
auto doc = *i;
|
||||
size_t index{0};
|
||||
StringType copy;
|
||||
double rating;
|
||||
uint64_t reviews;
|
||||
for ( auto value : doc ) {
|
||||
switch (index)
|
||||
{
|
||||
case 1:
|
||||
copy = StringType(std::string_view(value));
|
||||
break;
|
||||
case 5:
|
||||
rating = double(value);
|
||||
break;
|
||||
case 7:
|
||||
reviews = uint64_t(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
auto x = result.find(copy);
|
||||
if (x == result.end()) { // If key not found, add new key
|
||||
result.emplace(copy, amazon_cellphones::brand{
|
||||
rating * reviews,
|
||||
reviews
|
||||
});
|
||||
} else { // Otherwise, update key data
|
||||
x->second.cumulative_rating += rating * reviews;
|
||||
x->second.reviews_count += reviews;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_singlestage<UNTHREADED>)->UseManualTime();
|
||||
#ifdef SIMDJSON_THREADS_ENABLED
|
||||
BENCHMARK_TEMPLATE(amazon_cellphones, simdjson_singlestage<THREADED>)->UseManualTime();
|
||||
#endif
|
||||
|
||||
} // namespace amazon_cellphones
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
File diff suppressed because it is too large
Load Diff
@@ -473,28 +473,6 @@ static void twitter_count(State& state) {
|
||||
}
|
||||
BENCHMARK(twitter_count);
|
||||
|
||||
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||
SIMDJSON_DISABLE_DEPRECATED_WARNING
|
||||
static void iterator_twitter_count(State& state) {
|
||||
// Prints the number of results in twitter.json
|
||||
padded_string json = padded_string::load(TWITTER_JSON);
|
||||
ParsedJson pj = build_parsed_json(json);
|
||||
for (simdjson_unused auto _ : state) {
|
||||
ParsedJson::Iterator iter(pj);
|
||||
// uint64_t result_count = doc["search_metadata"]["count"];
|
||||
if (!iter.move_to_key("search_metadata")) { return; }
|
||||
if (!iter.move_to_key("count")) { return; }
|
||||
if (!iter.is_integer()) { return; }
|
||||
int64_t result_count = iter.get_integer();
|
||||
|
||||
if (result_count != 100) { return; }
|
||||
}
|
||||
}
|
||||
BENCHMARK(iterator_twitter_count);
|
||||
SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#endif // SIMDJSON_DISABLE_DEPRECATED_API
|
||||
|
||||
static void twitter_default_profile(State& state) {
|
||||
// Count unique users with a default profile.
|
||||
dom::parser parser;
|
||||
@@ -578,54 +556,6 @@ static void error_code_twitter_default_profile(State& state) noexcept {
|
||||
}
|
||||
BENCHMARK(error_code_twitter_default_profile);
|
||||
|
||||
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
||||
|
||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||
SIMDJSON_DISABLE_DEPRECATED_WARNING
|
||||
|
||||
static void iterator_twitter_default_profile(State& state) {
|
||||
// Count unique users with a default profile.
|
||||
padded_string json;
|
||||
auto error = padded_string::load(TWITTER_JSON).get(json);
|
||||
if (error) { std::cerr << error << std::endl; return; }
|
||||
ParsedJson pj = build_parsed_json(json);
|
||||
for (simdjson_unused auto _ : state) {
|
||||
set<string_view> default_users;
|
||||
ParsedJson::Iterator iter(pj);
|
||||
|
||||
// for (dom::object tweet : doc["statuses"]) {
|
||||
if (!(iter.move_to_key("statuses") && iter.is_array())) { return; }
|
||||
if (iter.down()) { // first status
|
||||
do {
|
||||
|
||||
// dom::object user = tweet["user"];
|
||||
if (!(iter.move_to_key("user") && iter.is_object())) { return; }
|
||||
|
||||
// if (user["default_profile"]) {
|
||||
if (iter.move_to_key("default_profile")) {
|
||||
if (iter.is_true()) {
|
||||
if (!iter.up()) { return; } // back to user
|
||||
|
||||
// default_users.insert(user["screen_name"]);
|
||||
if (!(iter.move_to_key("screen_name") && iter.is_string())) { return; }
|
||||
default_users.emplace(iter.get_string(), iter.get_string_length());
|
||||
}
|
||||
if (!iter.up()) { return; } // back to user
|
||||
}
|
||||
|
||||
if (!iter.up()) { return; } // back to status
|
||||
|
||||
} while (iter.next()); // next status
|
||||
}
|
||||
|
||||
if (default_users.size() != 86) { return; }
|
||||
}
|
||||
}
|
||||
|
||||
SIMDJSON_POP_DISABLE_WARNINGS
|
||||
BENCHMARK(iterator_twitter_default_profile);
|
||||
#endif // SIMDJSON_DISABLE_DEPRECATED_API
|
||||
|
||||
static void error_code_twitter_image_sizes(State& state) noexcept {
|
||||
// Count unique image sizes
|
||||
dom::parser parser;
|
||||
@@ -680,92 +610,4 @@ static void parse_surrogate_pairs(State& state) {
|
||||
}
|
||||
BENCHMARK(parse_surrogate_pairs);
|
||||
|
||||
|
||||
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
||||
|
||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||
SIMDJSON_DISABLE_DEPRECATED_WARNING
|
||||
static void iterator_twitter_image_sizes(State& state) {
|
||||
// Count unique image sizes
|
||||
padded_string json;
|
||||
auto error = padded_string::load(TWITTER_JSON).get(json);
|
||||
if (error) { std::cerr << error << std::endl; return; }
|
||||
ParsedJson pj = build_parsed_json(json);
|
||||
for (simdjson_unused auto _ : state) {
|
||||
set<tuple<uint64_t, uint64_t>> image_sizes;
|
||||
ParsedJson::Iterator iter(pj);
|
||||
|
||||
// for (dom::object tweet : doc["statuses"]) {
|
||||
if (!(iter.move_to_key("statuses") && iter.is_array())) { return; }
|
||||
if (iter.down()) { // first status
|
||||
do {
|
||||
|
||||
// dom::object media;
|
||||
// not_found = tweet["entities"]["media"].get(media);
|
||||
// if (!not_found) {
|
||||
if (iter.move_to_key("entities")) {
|
||||
if (!iter.is_object()) { return; }
|
||||
if (iter.move_to_key("media")) {
|
||||
if (!iter.is_array()) { return; }
|
||||
|
||||
// for (dom::object image : media) {
|
||||
if (iter.down()) { // first media
|
||||
do {
|
||||
|
||||
// for (auto [key, size] : dom::object(image["sizes"])) {
|
||||
if (!(iter.move_to_key("sizes") && iter.is_object())) { return; }
|
||||
if (iter.down()) { // first size
|
||||
do {
|
||||
iter.move_to_value();
|
||||
|
||||
// image_sizes.insert({ size["w"], size["h"] });
|
||||
if (!(iter.move_to_key("w")) && !iter.is_integer()) { return; }
|
||||
uint64_t width = iter.get_integer();
|
||||
if (!iter.up()) { return; } // back to size
|
||||
if (!(iter.move_to_key("h")) && !iter.is_integer()) { return; }
|
||||
uint64_t height = iter.get_integer();
|
||||
if (!iter.up()) { return; } // back to size
|
||||
image_sizes.emplace(width, height);
|
||||
|
||||
} while (iter.next()); // next size
|
||||
if (!iter.up()) { return; } // back to sizes
|
||||
}
|
||||
if (!iter.up()) { return; } // back to image
|
||||
} while (iter.next()); // next image
|
||||
if (!iter.up()) { return; } // back to media
|
||||
}
|
||||
if (!iter.up()) { return; } // back to entities
|
||||
}
|
||||
if (!iter.up()) { return; } // back to status
|
||||
}
|
||||
} while (iter.next()); // next status
|
||||
}
|
||||
|
||||
if (image_sizes.size() != 15) { return; };
|
||||
}
|
||||
}
|
||||
BENCHMARK(iterator_twitter_image_sizes);
|
||||
|
||||
#endif // SIMDJSON_DISABLE_DEPRECATED_API
|
||||
|
||||
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
||||
static void print_json(State& state) noexcept {
|
||||
// Prints the number of results in twitter.json
|
||||
dom::parser parser;
|
||||
|
||||
padded_string json;
|
||||
auto error = padded_string::load(TWITTER_JSON).get(json);
|
||||
if (error) { std::cerr << error << std::endl; return; }
|
||||
|
||||
int code = json_parse(json, parser);
|
||||
if (code) { cerr << error_message(code) << endl; return; }
|
||||
for (simdjson_unused auto _ : state) {
|
||||
std::stringstream s;
|
||||
if (!parser.print_json(s)) { cerr << "print_json failed" << endl; return; }
|
||||
}
|
||||
}
|
||||
BENCHMARK(print_json);
|
||||
#endif // SIMDJSON_DISABLE_DEPRECATED_API
|
||||
SIMDJSON_POP_DISABLE_WARNINGS
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
||||
@@ -21,12 +21,15 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS
|
||||
#include <nlohmann/json.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef SIMDJSON_COMPETITION_BOOSTJSON
|
||||
#include <boost/json.hpp>
|
||||
#endif
|
||||
|
||||
// This has to be last, for reasons I don't yet understand
|
||||
#include <benchmark/benchmark.h>
|
||||
|
||||
SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#include "json2msgpack/simdjson_ondemand.h"
|
||||
#include "json2msgpack/simdjson_singlestage.h"
|
||||
#include "json2msgpack/simdjson_dom.h"
|
||||
#include "json2msgpack/yyjson.h"
|
||||
#include "json2msgpack/rapidjson.h"
|
||||
@@ -34,9 +37,9 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#include "json2msgpack/sajson.h"
|
||||
#endif // SIMDJSON_COMPETITION_ONDEMAND_SAJSON
|
||||
#include "json2msgpack/nlohmann_json.h"
|
||||
#include "json2msgpack/boostjson.h"
|
||||
|
||||
#include "partial_tweets/simdjson_ondemand.h"
|
||||
#include "partial_tweets/simdjson_singlestage.h"
|
||||
#include "partial_tweets/simdjson_dom.h"
|
||||
#include "partial_tweets/yyjson.h"
|
||||
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
|
||||
@@ -50,12 +53,11 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#if SIMDJSON_COMPETITION_SAX
|
||||
#include "partial_tweets/nlohmann_json_sax.h"
|
||||
#endif // SIMDJSON_COMPETITION_SAX
|
||||
#include "partial_tweets/boostjson.h"
|
||||
|
||||
|
||||
#include "distinct_user_id/simdjson_ondemand.h"
|
||||
#include "distinct_user_id/simdjson_ondemand_json_pointer.h"
|
||||
#include "distinct_user_id/simdjson_singlestage.h"
|
||||
#include "distinct_user_id/simdjson_singlestage_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"
|
||||
@@ -70,9 +72,9 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#if SIMDJSON_COMPETITION_SAX
|
||||
#include "distinct_user_id/nlohmann_json_sax.h"
|
||||
#endif // SIMDJSON_COMPETITION_SAX
|
||||
#include "distinct_user_id/boostjson.h"
|
||||
|
||||
#include "find_tweet/simdjson_ondemand.h"
|
||||
#include "find_tweet/simdjson_singlestage.h"
|
||||
#include "find_tweet/simdjson_dom.h"
|
||||
#include "find_tweet/yyjson.h"
|
||||
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
|
||||
@@ -86,9 +88,9 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#if SIMDJSON_COMPETITION_SAX
|
||||
#include "find_tweet/nlohmann_json_sax.h"
|
||||
#endif // SIMDJSON_COMPETITION_SAX
|
||||
#include "find_tweet/boostjson.h"
|
||||
|
||||
#include "top_tweet/simdjson_ondemand.h"
|
||||
#include "top_tweet/simdjson_singlestage.h"
|
||||
#include "top_tweet/simdjson_dom.h"
|
||||
#include "top_tweet/yyjson.h"
|
||||
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
|
||||
@@ -102,10 +104,10 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#if SIMDJSON_COMPETITION_SAX
|
||||
#include "top_tweet/nlohmann_json_sax.h"
|
||||
#endif // SIMDJSON_COMPETITION_SAX
|
||||
#include "top_tweet/boostjson.h"
|
||||
|
||||
|
||||
#include "kostya/simdjson_ondemand.h"
|
||||
#include "kostya/simdjson_singlestage.h"
|
||||
#include "kostya/simdjson_dom.h"
|
||||
#include "kostya/yyjson.h"
|
||||
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
|
||||
@@ -119,15 +121,12 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#if SIMDJSON_COMPETITION_SAX
|
||||
#include "kostya/nlohmann_json_sax.h"
|
||||
#endif // SIMDJSON_COMPETITION_SAX
|
||||
#include "kostya/boostjson.h"
|
||||
|
||||
#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_singlestage.h"
|
||||
#if SIMDJSON_COMPETITION_SINGLESTAGE_UNORDERED
|
||||
#include "large_random/simdjson_singlestage_unordered.h"
|
||||
#endif // SIMDJSON_COMPETITION_SINGLESTAGE_UNORDERED
|
||||
#include "large_random/simdjson_dom.h"
|
||||
#include "large_random/yyjson.h"
|
||||
#if SIMDJSON_COMPETITION_ONDEMAND_SAJSON
|
||||
@@ -141,13 +140,12 @@ SIMDJSON_POP_DISABLE_WARNINGS
|
||||
#if SIMDJSON_COMPETITION_SAX
|
||||
#include "large_random/nlohmann_json_sax.h"
|
||||
#endif // SIMDJSON_COMPETITION_SAX
|
||||
#include "large_random/boostjson.h"
|
||||
|
||||
#include "amazon_cellphones/simdjson_dom.h"
|
||||
#include "amazon_cellphones/simdjson_ondemand.h"
|
||||
#include "amazon_cellphones/simdjson_singlestage.h"
|
||||
|
||||
#include "large_amazon_cellphones/simdjson_dom.h"
|
||||
#include "large_amazon_cellphones/simdjson_ondemand.h"
|
||||
#include "large_amazon_cellphones/simdjson_singlestage.h"
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
||||
@@ -169,22 +169,6 @@ BENCHMARK(parse_gsoc)->Repetitions(10)->ComputeStatistics("max", [](const std::v
|
||||
})->DisplayAggregatesOnly(true);
|
||||
|
||||
|
||||
|
||||
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||
SIMDJSON_DISABLE_DEPRECATED_WARNING
|
||||
static void json_parse(State& state) {
|
||||
ParsedJson pj;
|
||||
if (!pj.allocate_capacity(EMPTY_ARRAY.length())) { return; }
|
||||
for (simdjson_unused auto _ : state) {
|
||||
auto error = json_parse(EMPTY_ARRAY, pj);
|
||||
if (error) { return; }
|
||||
}
|
||||
}
|
||||
SIMDJSON_POP_DISABLE_WARNINGS
|
||||
BENCHMARK(json_parse);
|
||||
#endif // SIMDJSON_DISABLE_DEPRECATED_API
|
||||
|
||||
static void parser_parse_error_code(State& state) {
|
||||
dom::parser parser;
|
||||
if (parser.allocate(EMPTY_ARRAY.length())) { return; }
|
||||
@@ -213,20 +197,6 @@ BENCHMARK(parser_parse_exception);
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
|
||||
#ifndef SIMDJSON_DISABLE_DEPRECATED_API
|
||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||
SIMDJSON_DISABLE_DEPRECATED_WARNING
|
||||
static void build_parsed_json(State& state) {
|
||||
for (simdjson_unused auto _ : state) {
|
||||
dom::parser parser = simdjson::build_parsed_json(EMPTY_ARRAY);
|
||||
if (!parser.valid) { return; }
|
||||
}
|
||||
}
|
||||
SIMDJSON_POP_DISABLE_WARNINGS
|
||||
|
||||
BENCHMARK(build_parsed_json);
|
||||
#endif
|
||||
|
||||
static void document_parse_error_code(State& state) {
|
||||
for (simdjson_unused auto _ : state) {
|
||||
dom::parser parser;
|
||||
|
||||
+13
-9
@@ -445,7 +445,7 @@ struct benchmarker {
|
||||
return 100.0 * a / b;
|
||||
}
|
||||
|
||||
void print(bool tabbed_output) const {
|
||||
void print(bool tabbed_output, bool stage1_only) const {
|
||||
if (tabbed_output) {
|
||||
char* filename_copy = reinterpret_cast<char*>(malloc(strlen(filename)+1));
|
||||
SIMDJSON_PUSH_DISABLE_WARNINGS
|
||||
@@ -503,17 +503,21 @@ struct benchmarker {
|
||||
stats->blocks_with_16_structurals_flipped, percent(stats->blocks_with_16_structurals_flipped, stats->blocks));
|
||||
}
|
||||
printf("\n");
|
||||
printf("All Stages (excluding allocation)\n");
|
||||
print_aggregate("| " , all_stages_without_allocation.best);
|
||||
// frequently, allocation is a tiny fraction of the running time so we omit it
|
||||
if(allocate_stage.best.elapsed_sec() > 0.01 * all_stages_without_allocation.best.elapsed_sec()) {
|
||||
printf("|- Allocation\n");
|
||||
print_aggregate("| ", allocate_stage.best);
|
||||
if(!stage1_only) {
|
||||
printf("All Stages (excluding allocation)\n");
|
||||
print_aggregate("| " , all_stages_without_allocation.best);
|
||||
// frequently, allocation is a tiny fraction of the running time so we omit it
|
||||
if(allocate_stage.best.elapsed_sec() > 0.01 * all_stages_without_allocation.best.elapsed_sec()) {
|
||||
printf("|- Allocation\n");
|
||||
print_aggregate("| ", allocate_stage.best);
|
||||
}
|
||||
}
|
||||
printf("|- Stage 1\n");
|
||||
print_aggregate("| ", stage1.best);
|
||||
printf("|- Stage 2\n");
|
||||
print_aggregate("| ", stage2.best);
|
||||
if(!stage1_only) {
|
||||
printf("|- Stage 2\n");
|
||||
print_aggregate("| ", stage2.best);
|
||||
}
|
||||
if (collector.has_events()) {
|
||||
double freq1 = (stage1.best.cycles() / stage1.best.elapsed_sec()) / 1000000000.0;
|
||||
double freq2 = (stage2.best.cycles() / stage2.best.elapsed_sec()) / 1000000000.0;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef SIMDJSON_COMPETITION_BOOSTJSON
|
||||
|
||||
#include "distinct_user_id.h"
|
||||
|
||||
namespace distinct_user_id {
|
||||
|
||||
struct boostjson {
|
||||
bool run(simdjson::padded_string &json, std::vector<uint64_t> &result) {
|
||||
|
||||
auto root = boost::json::parse(json);
|
||||
for (const auto &tweet : root.at("statuses").as_array()) {
|
||||
result.push_back(tweet.at("user").at("id").to_number<uint64_t>());
|
||||
|
||||
if (tweet.as_object().if_contains("retweeted_status")) {
|
||||
result.push_back(tweet.at("retweeted_status").at("user").at("id").to_number<uint64_t>());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(distinct_user_id, boostjson)->UseManualTime();
|
||||
|
||||
} // namespace distinct_user_id
|
||||
|
||||
#endif // SIMDJSON_COMPETITION_BOOSTJSON
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "distinct_user_id.h"
|
||||
|
||||
namespace distinct_user_id {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<uint64_t> &result) {
|
||||
// Walk the document, parsing as we go
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object tweet : doc.find_field("statuses")) {
|
||||
// We believe that all statuses have a matching
|
||||
// user, and we are willing to throw when they do not.
|
||||
result.push_back(tweet.find_field("user").find_field("id"));
|
||||
// Not all tweets have a "retweeted_status", but when they do
|
||||
// we want to go and find the user within.
|
||||
auto retweet = tweet.find_field("retweeted_status");
|
||||
if (!retweet.error()) {
|
||||
result.push_back(retweet.find_field("user").find_field("id"));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(distinct_user_id, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace distinct_user_id
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "distinct_user_id.h"
|
||||
|
||||
namespace distinct_user_id {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage_json_pointer {
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<uint64_t> &result) {
|
||||
// Walk the document, parsing as we go
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object tweet : doc.find_field("statuses")) {
|
||||
// We believe that all statuses have a matching
|
||||
// user, and we are willing to throw when they do not.
|
||||
result.push_back(tweet.at_pointer("/user/id"));
|
||||
// Not all tweets have a "retweeted_status", but when they do
|
||||
// we want to go and find the user within.
|
||||
auto retweet_id = tweet.at_pointer("/retweeted_status/user/id");
|
||||
if (retweet_id.error() != NO_SUCH_FIELD) {
|
||||
result.push_back(retweet_id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(distinct_user_id, simdjson_singlestage_json_pointer)->UseManualTime();
|
||||
|
||||
} // namespace distinct_user_id
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -218,7 +218,7 @@ int main(int argc, char *argv[]) {
|
||||
if (!options.verbose) { progress.erase(); }
|
||||
|
||||
for (size_t i=0; i<options.files.size(); i++) {
|
||||
benchmarkers[i]->print(options.tabbed_output);
|
||||
benchmarkers[i]->print(options.tabbed_output, options.stage1_only);
|
||||
delete benchmarkers[i];
|
||||
}
|
||||
|
||||
|
||||
@@ -34,11 +34,15 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "linux-perf-events.h"
|
||||
#ifdef __linux__
|
||||
#include "linux-perf-events.h"
|
||||
#include <libgen.h>
|
||||
#endif
|
||||
|
||||
#if __APPLE__ && __aarch64__
|
||||
#include "apple/apple_arm_events.h"
|
||||
#endif
|
||||
|
||||
#include "simdjson.h"
|
||||
|
||||
using std::string;
|
||||
@@ -134,7 +138,7 @@ struct event_collector {
|
||||
|
||||
#if defined(__linux__)
|
||||
LinuxEvents<PERF_TYPE_HARDWARE> linux_events;
|
||||
event_collector(simdjson_unused bool quiet = false) : linux_events(vector<int>{
|
||||
event_collector() : linux_events(vector<int>{
|
||||
#if SIMDJSON_SIMPLE_PERFORMANCE_COUNTERS
|
||||
PERF_COUNT_HW_CPU_CYCLES,
|
||||
PERF_COUNT_HW_INSTRUCTIONS,
|
||||
@@ -149,8 +153,17 @@ struct event_collector {
|
||||
bool has_events() {
|
||||
return linux_events.is_working();
|
||||
}
|
||||
#elif __APPLE__ && __aarch64__
|
||||
AppleEvents apple_events;
|
||||
performance_counters diff;
|
||||
event_collector() : diff(0) {
|
||||
apple_events.setup_performance_counters();
|
||||
}
|
||||
bool has_events() {
|
||||
return apple_events.setup_performance_counters();
|
||||
}
|
||||
#else
|
||||
event_collector(simdjson_unused bool _quiet = false) {}
|
||||
event_collector() {}
|
||||
bool has_events() {
|
||||
return false;
|
||||
}
|
||||
@@ -159,6 +172,8 @@ struct event_collector {
|
||||
simdjson_inline void start() {
|
||||
#if defined(__linux)
|
||||
linux_events.start();
|
||||
#elif __APPLE__ && __aarch64__
|
||||
if(has_events()) { diff = apple_events.get_counters(); }
|
||||
#endif
|
||||
start_clock = steady_clock::now();
|
||||
}
|
||||
@@ -166,6 +181,16 @@ struct event_collector {
|
||||
time_point<steady_clock> end_clock = steady_clock::now();
|
||||
#if defined(__linux)
|
||||
linux_events.end(count.event_counts);
|
||||
#elif __APPLE__ && __aarch64__
|
||||
if(has_events()) {
|
||||
performance_counters end = apple_events.get_counters();
|
||||
diff = end - diff;
|
||||
}
|
||||
count.event_counts[0] = diff.cycles;
|
||||
count.event_counts[1] = diff.instructions;
|
||||
count.event_counts[2] = diff.missed_branches;
|
||||
count.event_counts[3] = 0;
|
||||
count.event_counts[4] = 0;
|
||||
#endif
|
||||
count.elapsed = end_clock - start_clock;
|
||||
return count;
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef SIMDJSON_COMPETITION_BOOSTJSON
|
||||
|
||||
#include "find_tweet.h"
|
||||
|
||||
namespace find_tweet {
|
||||
|
||||
struct boostjson {
|
||||
using StringType=std::string;
|
||||
|
||||
bool run(simdjson::padded_string &json, uint64_t find_id, std::string &result) {
|
||||
|
||||
auto root = boost::json::parse(json);
|
||||
for (const auto &tweet : root.at("statuses").as_array()) {
|
||||
if (tweet.at("id") == find_id) {
|
||||
result = tweet.at("text").as_string();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(find_tweet, boostjson)->UseManualTime();
|
||||
|
||||
} // namespace find_tweet
|
||||
|
||||
#endif // SIMDJSON_COMPETITION_BOOSTJSON
|
||||
@@ -1,33 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "find_tweet.h"
|
||||
|
||||
namespace find_tweet {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
using StringType=std::string_view;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, uint64_t find_id, std::string_view &result) {
|
||||
// Walk the document, parsing as we go
|
||||
auto doc = parser.iterate(json);
|
||||
for (auto tweet : doc.find_field("statuses")) {
|
||||
if (uint64_t(tweet.find_field("id")) == find_id) {
|
||||
result = tweet.find_field("text");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(find_tweet, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace find_tweet
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef SIMDJSON_COMPETITION_BOOSTJSON
|
||||
|
||||
#include "json2msgpack.h"
|
||||
|
||||
namespace json2msgpack {
|
||||
|
||||
struct boostjson2msgpack {
|
||||
inline std::string_view to_msgpack(const boost::json::value &root, uint8_t *buf) {
|
||||
buff = buf;
|
||||
recursive_processor(root);
|
||||
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t *buff{};
|
||||
|
||||
inline void write_double(const double d) noexcept {
|
||||
*buff++ = 0xcb;
|
||||
::memcpy(buff, &d, sizeof(d));
|
||||
buff += sizeof(d);
|
||||
}
|
||||
|
||||
inline void write_byte(const uint8_t b) noexcept {
|
||||
*buff = b;
|
||||
buff++;
|
||||
}
|
||||
|
||||
inline void write_uint32(const uint32_t w) noexcept {
|
||||
::memcpy(buff, &w, sizeof(w));
|
||||
buff += sizeof(w);
|
||||
}
|
||||
|
||||
inline void write_string(const std::string & str) {
|
||||
write_byte(0xdb);
|
||||
write_uint32(uint32_t(str.size()));
|
||||
::memcpy(buff, str.data(), str.size());
|
||||
buff += str.size();
|
||||
}
|
||||
|
||||
inline void recursive_processor(const boost::json::value &element) {
|
||||
switch(element.kind()) {
|
||||
case boost::json::kind::array: {
|
||||
write_byte(0xdd);
|
||||
const auto &array = element.as_array();
|
||||
write_uint32(static_cast<uint32_t>(array.size()));
|
||||
for (const auto &child : array) {
|
||||
recursive_processor(child);
|
||||
}
|
||||
} break;
|
||||
|
||||
case boost::json::kind::object: {
|
||||
write_byte(0xdf);
|
||||
const auto &object = element.as_object();
|
||||
write_uint32(static_cast<uint32_t>(object.size()));
|
||||
for (const auto &child : object) {
|
||||
write_string(child.key_c_str());
|
||||
recursive_processor(child.value());
|
||||
}
|
||||
} break;
|
||||
|
||||
case boost::json::kind::int64:
|
||||
case boost::json::kind::uint64:
|
||||
case boost::json::kind::double_:
|
||||
write_double(element.to_number<double>());
|
||||
break;
|
||||
|
||||
case boost::json::kind::string:
|
||||
write_string(element.as_string().c_str());
|
||||
break;
|
||||
|
||||
case boost::json::kind::bool_:
|
||||
write_byte(0xc2 + element.as_bool());
|
||||
break;
|
||||
|
||||
case boost::json::kind::null:
|
||||
write_byte(0xc0);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("unexpected\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct boostjson {
|
||||
using StringType=std::string;
|
||||
|
||||
boostjson2msgpack parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, char *buffer, std::string_view &result) {
|
||||
auto root = boost::json::parse(json);
|
||||
result = parser.to_msgpack(root, reinterpret_cast<uint8_t *>(buffer));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(json2msgpack, boostjson)->UseManualTime();
|
||||
|
||||
} // namespace json2msgpack
|
||||
|
||||
#endif // SIMDJSON_COMPETITION_BOOSTJSON
|
||||
@@ -8,7 +8,7 @@ namespace json2msgpack {
|
||||
using namespace simdjson;
|
||||
|
||||
/**
|
||||
* @brief The simdjsonondemand2msgpack struct is used to quickly convert
|
||||
* @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
|
||||
@@ -17,7 +17,7 @@ using namespace simdjson;
|
||||
*
|
||||
* Recommended usage:
|
||||
*
|
||||
* simdjsonondemand2msgpack parser{};
|
||||
* 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
|
||||
*
|
||||
@@ -26,10 +26,10 @@ using namespace simdjson;
|
||||
* 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 simdjsonondemand2msgpack instance though you should use
|
||||
* You may reuse the simdjson2msgpack instance though you should use
|
||||
* one per thread.
|
||||
*/
|
||||
struct simdjsonondemand2msgpack {
|
||||
struct simdjson2msgpack {
|
||||
/**
|
||||
* @brief Converts the provided JSON into msgpack.
|
||||
*
|
||||
@@ -58,7 +58,7 @@ private:
|
||||
};
|
||||
|
||||
std::string_view
|
||||
simdjsonondemand2msgpack::to_msgpack(const simdjson::padded_string &json,
|
||||
simdjson2msgpack::to_msgpack(const simdjson::padded_string &json,
|
||||
uint8_t *buf) {
|
||||
buff = buf;
|
||||
ondemand::document doc = parser.iterate(json);
|
||||
@@ -106,33 +106,33 @@ simdjsonondemand2msgpack::to_msgpack(const simdjson::padded_string &json,
|
||||
return std::string_view(reinterpret_cast<char *>(buf), size_t(buff - buf));
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::write_double(const double d) noexcept {
|
||||
void simdjson2msgpack::write_double(const double d) noexcept {
|
||||
*buff++ = 0xcb;
|
||||
::memcpy(buff, &d, sizeof(d));
|
||||
buff += sizeof(d);
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::write_byte(const uint8_t b) noexcept {
|
||||
void simdjson2msgpack::write_byte(const uint8_t b) noexcept {
|
||||
*buff = b;
|
||||
buff++;
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::write_uint32(const uint32_t w) noexcept {
|
||||
void simdjson2msgpack::write_uint32(const uint32_t w) noexcept {
|
||||
::memcpy(buff, &w, sizeof(w));
|
||||
buff += sizeof(w);
|
||||
}
|
||||
|
||||
uint8_t *simdjsonondemand2msgpack::skip_uint32() noexcept {
|
||||
uint8_t *simdjson2msgpack::skip_uint32() noexcept {
|
||||
uint8_t *ret = buff;
|
||||
buff += sizeof(uint32_t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
|
||||
void simdjson2msgpack::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
|
||||
::memcpy(p, &w, sizeof(w));
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::write_raw_string(
|
||||
void simdjson2msgpack::write_raw_string(
|
||||
simdjson::ondemand::raw_json_string in) {
|
||||
write_byte(0xdb);
|
||||
uint8_t *location = skip_uint32();
|
||||
@@ -140,7 +140,7 @@ void simdjsonondemand2msgpack::write_raw_string(
|
||||
write_uint32_at(uint32_t(v.size()), location);
|
||||
}
|
||||
|
||||
void simdjsonondemand2msgpack::recursive_processor(simdjson::ondemand::value element) {
|
||||
void simdjson2msgpack::recursive_processor(simdjson::ondemand::value element) {
|
||||
switch (element.type()) {
|
||||
case simdjson::ondemand::json_type::array: {
|
||||
uint32_t counter = 0;
|
||||
@@ -185,7 +185,7 @@ void simdjsonondemand2msgpack::recursive_processor(simdjson::ondemand::value ele
|
||||
}
|
||||
|
||||
|
||||
void simdjsonondemand2msgpack::recursive_processor_ref(simdjson::ondemand::value& element) {
|
||||
void simdjson2msgpack::recursive_processor_ref(simdjson::ondemand::value& element) {
|
||||
switch (element.type()) {
|
||||
case simdjson::ondemand::json_type::array: {
|
||||
uint32_t counter = 0;
|
||||
@@ -234,7 +234,7 @@ void simdjsonondemand2msgpack::recursive_processor_ref(simdjson::ondemand::value
|
||||
struct simdjson_ondemand {
|
||||
using StringType = std::string_view;
|
||||
|
||||
simdjsonondemand2msgpack parser{};
|
||||
simdjson2msgpack parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, char *buffer,
|
||||
std::string_view &result) {
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
#pragma once
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "json2msgpack.h"
|
||||
|
||||
namespace json2msgpack {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
/**
|
||||
* @brief The simdjsonsinglestage2msgpack 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:
|
||||
*
|
||||
* simdjsonsinglestage2msgpack 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 simdjsonsinglestage2msgpack instance though you should use
|
||||
* one per thread.
|
||||
*/
|
||||
struct simdjsonsinglestage2msgpack {
|
||||
/**
|
||||
* @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, writing 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::singlestage::raw_json_string rjs);
|
||||
inline void recursive_processor(simdjson::singlestage::value element);
|
||||
inline void recursive_processor_ref(simdjson::singlestage::value& element);
|
||||
|
||||
simdjson::singlestage::parser parser;
|
||||
uint8_t *buff{};
|
||||
};
|
||||
|
||||
std::string_view
|
||||
simdjsonsinglestage2msgpack::to_msgpack(const simdjson::padded_string &json,
|
||||
uint8_t *buf) {
|
||||
buff = buf;
|
||||
singlestage::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::singlestage::json_type::number:
|
||||
write_double(doc.get_double());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::string:
|
||||
write_raw_string(doc.get_raw_json_string());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::boolean:
|
||||
write_byte(0xc2 + doc.get_bool());
|
||||
break;
|
||||
case simdjson::singlestage::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::singlestage::json_type::array:
|
||||
case simdjson::singlestage::json_type::object:
|
||||
default:
|
||||
// impossible
|
||||
SIMDJSON_UNREACHABLE();
|
||||
}
|
||||
} else {
|
||||
simdjson::singlestage::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 simdjsonsinglestage2msgpack::write_double(const double d) noexcept {
|
||||
*buff++ = 0xcb;
|
||||
::memcpy(buff, &d, sizeof(d));
|
||||
buff += sizeof(d);
|
||||
}
|
||||
|
||||
void simdjsonsinglestage2msgpack::write_byte(const uint8_t b) noexcept {
|
||||
*buff = b;
|
||||
buff++;
|
||||
}
|
||||
|
||||
void simdjsonsinglestage2msgpack::write_uint32(const uint32_t w) noexcept {
|
||||
::memcpy(buff, &w, sizeof(w));
|
||||
buff += sizeof(w);
|
||||
}
|
||||
|
||||
uint8_t *simdjsonsinglestage2msgpack::skip_uint32() noexcept {
|
||||
uint8_t *ret = buff;
|
||||
buff += sizeof(uint32_t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void simdjsonsinglestage2msgpack::write_uint32_at(const uint32_t w, uint8_t *p) noexcept {
|
||||
::memcpy(p, &w, sizeof(w));
|
||||
}
|
||||
|
||||
void simdjsonsinglestage2msgpack::write_raw_string(
|
||||
simdjson::singlestage::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 simdjsonsinglestage2msgpack::recursive_processor(simdjson::singlestage::value element) {
|
||||
switch (element.type()) {
|
||||
case simdjson::singlestage::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::singlestage::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::singlestage::json_type::number:
|
||||
write_double(element.get_double());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::string:
|
||||
write_raw_string(element.get_raw_json_string());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::boolean:
|
||||
write_byte(0xc2 + element.get_bool());
|
||||
break;
|
||||
case simdjson::singlestage::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 simdjsonsinglestage2msgpack::recursive_processor_ref(simdjson::singlestage::value& element) {
|
||||
switch (element.type()) {
|
||||
case simdjson::singlestage::json_type::array: {
|
||||
uint32_t counter = 0;
|
||||
write_byte(0xdd);
|
||||
uint8_t *location = skip_uint32();
|
||||
for (auto child : element.get_array()) {
|
||||
counter++;
|
||||
simdjson::singlestage::value v = child.value();
|
||||
recursive_processor_ref(v);
|
||||
}
|
||||
write_uint32_at(counter, location);
|
||||
} break;
|
||||
case simdjson::singlestage::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::singlestage::value v = field.value();
|
||||
recursive_processor_ref(v);
|
||||
}
|
||||
write_uint32_at(counter, location);
|
||||
} break;
|
||||
case simdjson::singlestage::json_type::number:
|
||||
write_double(element.get_double());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::string:
|
||||
write_raw_string(element.get_raw_json_string());
|
||||
break;
|
||||
case simdjson::singlestage::json_type::boolean:
|
||||
write_byte(0xc2 + element.get_bool());
|
||||
break;
|
||||
case simdjson::singlestage::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_singlestage {
|
||||
using StringType = std::string_view;
|
||||
|
||||
simdjsonsinglestage2msgpack 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_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace json2msgpack
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -24,7 +24,7 @@ struct file_runner : public runner_base<I> {
|
||||
|
||||
simdjson_warn_unused bool before_run(benchmark::State &state) {
|
||||
if (!runner_base<I>::after_run(state)) { return false; };
|
||||
// Copy the original json in case we did *in situ* last time
|
||||
// Copy the original JSON in case we did *in situ* last time
|
||||
std::memcpy(json.data(), original_json.data(), original_json.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -13,15 +13,13 @@ void maybe_display_implementation() {
|
||||
std::cout << "simdjson::dom implementation: " << simdjson::get_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::singlestage implementation (stage 1): " << simdjson::get_active_implementation()->name() << std::endl;
|
||||
std::cout << "simdjson::singlestage implementation (stage 2): " << simdjson::builtin_implementation()->name() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename B, typename R> static void run_json_benchmark(benchmark::State &state) {
|
||||
maybe_display_implementation();
|
||||
|
||||
event_collector collector(true);
|
||||
event_collector collector;
|
||||
event_aggregate events;
|
||||
|
||||
// Warmup and equality check (make sure the data is right!)
|
||||
|
||||
@@ -13,7 +13,7 @@ struct string_runner : public runner_base<I> {
|
||||
|
||||
simdjson_warn_unused bool before_run(benchmark::State &state) {
|
||||
if (!runner_base<I>::after_run(state)) { return false; };
|
||||
// Copy the original json in case we did *in situ*
|
||||
// Copy the original JSON in case we did *in situ*
|
||||
std::memcpy(json.data(), original_json.data(), original_json.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef SIMDJSON_COMPETITION_BOOSTJSON
|
||||
|
||||
#include "kostya.h"
|
||||
|
||||
namespace kostya {
|
||||
|
||||
struct boostjson {
|
||||
static constexpr diff_flags DiffFlags = diff_flags::IMPRECISE_FLOATS;
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<point> &result) {
|
||||
auto root = boost::json::parse(json);
|
||||
for (const auto &point : root.at("coordinates").as_array()) {
|
||||
result.emplace_back(json_benchmark::point{
|
||||
point.at("x").to_number<double>(),
|
||||
point.at("y").to_number<double>(),
|
||||
point.at("z").to_number<double>()
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(kostya, boostjson)->UseManualTime();
|
||||
|
||||
} // namespace kostya
|
||||
|
||||
#endif // SIMDJSON_COMPETITION_BOOSTJSON
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "kostya.h"
|
||||
|
||||
namespace kostya {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
static constexpr diff_flags DiffFlags = diff_flags::NONE;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<point> &result) {
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object point : doc.find_field("coordinates")) {
|
||||
result.emplace_back(json_benchmark::point{point.find_field("x"), point.find_field("y"), point.find_field("z")});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(kostya, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace kostya
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,72 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "large_amazon_cellphones.h"
|
||||
|
||||
namespace large_amazon_cellphones {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
template<bool threaded>
|
||||
struct simdjson_singlestage {
|
||||
using StringType = std::string;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::map<StringType, brand> &result) {
|
||||
#ifdef SIMDJSON_THREADS_ENABLED
|
||||
parser.threaded = threaded;
|
||||
#endif
|
||||
singlestage::document_stream stream = parser.iterate_many(json);
|
||||
singlestage::document_stream::iterator i = stream.begin();
|
||||
++i; // Skip first line
|
||||
for (;i != stream.end(); ++i) {
|
||||
auto doc = *i;
|
||||
size_t index{0};
|
||||
StringType copy;
|
||||
double rating;
|
||||
uint64_t reviews;
|
||||
for ( auto value : doc ) {
|
||||
switch (index)
|
||||
{
|
||||
case 1:
|
||||
copy = StringType(std::string_view(value));
|
||||
break;
|
||||
case 5:
|
||||
rating = double(value);
|
||||
break;
|
||||
case 7:
|
||||
reviews = uint64_t(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
auto x = result.find(copy);
|
||||
if (x == result.end()) { // If key not found, add new key
|
||||
result.emplace(copy, large_amazon_cellphones::brand{
|
||||
rating * reviews,
|
||||
reviews
|
||||
});
|
||||
} else { // Otherwise, update key data
|
||||
x->second.cumulative_rating += rating * reviews;
|
||||
x->second.reviews_count += reviews;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_singlestage<UNTHREADED>)->UseManualTime();
|
||||
#ifdef SIMDJSON_THREADS_ENABLED
|
||||
BENCHMARK_TEMPLATE(large_amazon_cellphones, simdjson_singlestage<THREADED>)->UseManualTime();
|
||||
#endif
|
||||
|
||||
} // namespace amazon_cellphones
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef SIMDJSON_COMPETITION_BOOSTJSON
|
||||
|
||||
#include "large_random.h"
|
||||
|
||||
namespace large_random {
|
||||
|
||||
struct boostjson {
|
||||
static constexpr diff_flags DiffFlags = diff_flags::IMPRECISE_FLOATS;
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<point> &result) {
|
||||
auto root = boost::json::parse(json);
|
||||
for (const auto &point : root.as_array()) {
|
||||
result.emplace_back(json_benchmark::point{
|
||||
point.at("x").to_number<double>(),
|
||||
point.at("y").to_number<double>(),
|
||||
point.at("z").to_number<double>()
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(large_random, boostjson)->UseManualTime();
|
||||
|
||||
} // namespace large_random
|
||||
|
||||
#endif // SIMDJSON_COMPETITION_BOOSTJSON
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "large_random.h"
|
||||
|
||||
namespace large_random {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
static constexpr diff_flags DiffFlags = diff_flags::NONE;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<point> &result) {
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object coord : doc) {
|
||||
result.emplace_back(json_benchmark::point{coord.find_field("x"), coord.find_field("y"), coord.find_field("z")});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(large_random, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace large_random
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "large_random.h"
|
||||
|
||||
namespace large_random {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage_unordered {
|
||||
static constexpr diff_flags DiffFlags = diff_flags::NONE;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<point> &result) {
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object coord : doc) {
|
||||
result.emplace_back(json_benchmark::point{coord["x"], coord["y"], coord["z"]});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(large_random, simdjson_singlestage_unordered)->UseManualTime();
|
||||
|
||||
} // namespace large_random
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "largerandom.h"
|
||||
|
||||
namespace largerandom {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
class OnDemand {
|
||||
public:
|
||||
simdjson_inline bool Run(const padded_string &json);
|
||||
simdjson_inline const std::vector<my_point> &Result() { return container; }
|
||||
simdjson_inline size_t ItemCount() { return container.size(); }
|
||||
|
||||
private:
|
||||
singlestage::parser parser{};
|
||||
std::vector<my_point> container{};
|
||||
};
|
||||
|
||||
simdjson_inline bool OnDemand::Run(const padded_string &json) {
|
||||
container.clear();
|
||||
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object coord : doc) {
|
||||
container.emplace_back(my_point{coord.find_field("x"), coord.find_field("y"), coord.find_field("z")});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(LargeRandom, OnDemand);
|
||||
|
||||
} // namespace largerandom
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef SIMDJSON_COMPETITION_BOOSTJSON
|
||||
|
||||
#include "partial_tweets.h"
|
||||
|
||||
namespace partial_tweets {
|
||||
|
||||
struct boostjson {
|
||||
using StringType=std::string;
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<tweet<StringType>> &result) {
|
||||
|
||||
auto root = boost::json::parse(json);
|
||||
for (const auto &tweet : root.at("statuses").as_array()) {
|
||||
const auto &user = tweet.at("user");
|
||||
|
||||
auto in_reply_to_status_id = tweet.as_object().if_contains("in_reply_to_status_id")
|
||||
? tweet.at("in_reply_to_status_id") : boost::json::value();
|
||||
|
||||
result.emplace_back(partial_tweets::tweet<StringType>{
|
||||
tweet.at("created_at").as_string().c_str(),
|
||||
tweet.at("id").to_number<uint64_t>(),
|
||||
tweet.at("text").as_string().c_str(),
|
||||
in_reply_to_status_id.is_null() ? 0 : in_reply_to_status_id.to_number<uint64_t>(),
|
||||
{
|
||||
user.at("id").to_number<uint64_t>(),
|
||||
user.at("screen_name").as_string().c_str()
|
||||
},
|
||||
tweet.at("retweet_count").to_number<uint64_t>(),
|
||||
tweet.at("favorite_count").to_number<uint64_t>()
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(partial_tweets, boostjson)->UseManualTime();
|
||||
|
||||
} // namespace partial_tweets
|
||||
|
||||
#endif // SIMDJSON_COMPETITION_BOOSTJSON
|
||||
@@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "partial_tweets.h"
|
||||
|
||||
namespace partial_tweets {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
using StringType=std::string_view;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
simdjson_inline uint64_t nullable_int(singlestage::value value) {
|
||||
if (value.is_null()) { return 0; }
|
||||
return value;
|
||||
}
|
||||
|
||||
simdjson_inline twitter_user<std::string_view> read_user(singlestage::object user) {
|
||||
return { user.find_field("id"), user.find_field("screen_name") };
|
||||
}
|
||||
|
||||
bool run(simdjson::padded_string &json, std::vector<tweet<std::string_view>> &result) {
|
||||
// Walk the document, parsing the tweets as we go
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object tweet : doc.find_field("statuses")) {
|
||||
result.emplace_back(partial_tweets::tweet<std::string_view>{
|
||||
tweet.find_field("created_at"),
|
||||
tweet.find_field("id"),
|
||||
tweet.find_field("text"),
|
||||
nullable_int(tweet.find_field("in_reply_to_status_id")),
|
||||
read_user(tweet.find_field("user")),
|
||||
tweet.find_field("retweet_count"),
|
||||
tweet.find_field("favorite_count")
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(partial_tweets, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
} // namespace partial_tweets
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -1,63 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "partial_tweets.h"
|
||||
|
||||
namespace partial_tweets {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
|
||||
class SingleStage {
|
||||
public:
|
||||
SingleStage() {
|
||||
if(!displayed_implementation) {
|
||||
std::cout << "On Demand implementation: " << builtin_implementation()->name() << std::endl;
|
||||
displayed_implementation = true;
|
||||
}
|
||||
}
|
||||
simdjson_inline bool Run(const padded_string &json);
|
||||
simdjson_inline const std::vector<tweet> &Result() { return tweets; }
|
||||
simdjson_inline size_t ItemCount() { return tweets.size(); }
|
||||
|
||||
private:
|
||||
singlestage::parser parser{};
|
||||
std::vector<tweet> tweets{};
|
||||
|
||||
simdjson_inline uint64_t nullable_int(singlestage::value value) {
|
||||
if (value.is_null()) { return 0; }
|
||||
return value;
|
||||
}
|
||||
|
||||
simdjson_inline twitter_user read_user(singlestage::object user) {
|
||||
return { user.find_field("id"), user.find_field("screen_name") };
|
||||
}
|
||||
|
||||
static inline bool displayed_implementation = false;
|
||||
};
|
||||
|
||||
simdjson_inline bool SingleStage::Run(const padded_string &json) {
|
||||
tweets.clear();
|
||||
|
||||
// Walk the document, parsing the tweets as we go
|
||||
auto doc = parser.iterate(json);
|
||||
for (singlestage::object tweet : doc.find_field("statuses")) {
|
||||
tweets.emplace_back(partial_tweets::tweet{
|
||||
tweet.find_field("created_at"),
|
||||
tweet.find_field("id"),
|
||||
tweet.find_field("text"),
|
||||
nullable_int(tweet.find_field("in_reply_to_status_id")),
|
||||
read_user(tweet.find_field("user")),
|
||||
tweet.find_field("retweet_count"),
|
||||
tweet.find_field("favorite_count")
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(PartialTweets, SingleStage);
|
||||
|
||||
} // namespace partial_tweets
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_COMPETITION_BOOSTJSON
|
||||
|
||||
#include "top_tweet.h"
|
||||
|
||||
namespace top_tweet {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct boostjson {
|
||||
using StringType=std::string;
|
||||
|
||||
bool run(simdjson::padded_string &json, int64_t max_retweet_count, top_tweet_result<StringType> &result) {
|
||||
result.retweet_count = -1;
|
||||
boost::json::value top_tweet{};
|
||||
|
||||
auto root = boost::json::parse(json);
|
||||
for (const auto &tweet : root.at("statuses").as_array()) {
|
||||
int64_t retweet_count = tweet.at("retweet_count").as_int64();
|
||||
if (retweet_count <= max_retweet_count && retweet_count >= result.retweet_count) {
|
||||
result.retweet_count = retweet_count;
|
||||
top_tweet = tweet;
|
||||
}
|
||||
}
|
||||
|
||||
result.text = top_tweet.at("text").as_string();
|
||||
result.screen_name = top_tweet.at("user").at("screen_name").as_string();
|
||||
return result.retweet_count != -1;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(top_tweet, boostjson)->UseManualTime();
|
||||
|
||||
} // namespace top_tweet
|
||||
|
||||
#endif // SIMDJSON_COMPETITION_BOOSTJSON
|
||||
@@ -1,80 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
|
||||
#include "top_tweet.h"
|
||||
|
||||
namespace top_tweet {
|
||||
|
||||
using namespace simdjson;
|
||||
|
||||
struct simdjson_singlestage {
|
||||
using StringType=std::string_view;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, int64_t max_retweet_count, top_tweet_result<StringType> &result) {
|
||||
result.retweet_count = -1;
|
||||
// We save these DOM values for later so we don't have to parse them
|
||||
// into string_views until we're sure which ones we want to parse
|
||||
// NOTE: simdjson does not presently support reuse of objects or arrays--just scalars. This is
|
||||
// why we have to grab the text and screen_name fields instead of just saving the tweet object.
|
||||
singlestage::value screen_name, text;
|
||||
|
||||
auto doc = parser.iterate(json);
|
||||
for (auto tweet : doc["statuses"]) {
|
||||
// Since text, user.screen_name, and retweet_count generally appear in order, it's nearly free
|
||||
// for us to retrieve them here (and will cost a bit more if we do it in the if
|
||||
// statement).
|
||||
auto tweet_text = tweet["text"];
|
||||
auto tweet_screen_name = tweet["user"]["screen_name"];
|
||||
int64_t retweet_count = tweet["retweet_count"];
|
||||
if (retweet_count <= max_retweet_count && retweet_count >= result.retweet_count) {
|
||||
result.retweet_count = retweet_count;
|
||||
// TODO std::move should not be necessary
|
||||
text = std::move(tweet_text);
|
||||
screen_name = std::move(tweet_screen_name);
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we know which was the most retweeted, parse the values in it
|
||||
result.screen_name = screen_name;
|
||||
result.text = text;
|
||||
return result.retweet_count != -1;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(top_tweet, simdjson_singlestage)->UseManualTime();
|
||||
|
||||
struct simdjson_singlestage_forward_only {
|
||||
using StringType=std::string_view;
|
||||
|
||||
singlestage::parser parser{};
|
||||
|
||||
bool run(simdjson::padded_string &json, int64_t max_retweet_count, top_tweet_result<StringType> &result) {
|
||||
result.retweet_count = -1;
|
||||
|
||||
auto doc = parser.iterate(json);
|
||||
for (auto tweet : doc["statuses"]) {
|
||||
// Since text, user.screen_name, and retweet_count generally appear in order, it's nearly free
|
||||
// for us to retrieve them here (and will cost a bit more if we do it in the if
|
||||
// statement).
|
||||
auto tweet_text = tweet["text"];
|
||||
auto tweet_screen_name = tweet["user"]["screen_name"];
|
||||
int64_t retweet_count = tweet["retweet_count"];
|
||||
if (retweet_count <= max_retweet_count && retweet_count >= result.retweet_count) {
|
||||
result.retweet_count = retweet_count;
|
||||
result.text = tweet_text;
|
||||
result.screen_name = tweet_screen_name;
|
||||
}
|
||||
}
|
||||
|
||||
return result.retweet_count != -1;
|
||||
}
|
||||
};
|
||||
|
||||
BENCHMARK_TEMPLATE(top_tweet, simdjson_singlestage_forward_only)->UseManualTime();
|
||||
|
||||
} // namespace top_tweet
|
||||
|
||||
#endif // SIMDJSON_EXCEPTIONS
|
||||
@@ -114,10 +114,14 @@ set(SIMDJSON_CXX_STANDARD 17 CACHE STRING "the C++ standard to use for simdjson"
|
||||
set(CMAKE_CXX_STANDARD ${SIMDJSON_CXX_STANDARD})
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_MACOSX_RPATH OFF)
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD ON)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
set(SIMDJSON_STRUCTURAL_INDEXER_STEP CACHE STRING "the SIMDJSON_STRUCTURAL_INDEXER_STEP variable")
|
||||
|
||||
if(SIMDJSON_STRUCTURAL_INDEXER_STEP)
|
||||
message(STATUS "Setting SIMDJSON_STRUCTURAL_INDEXER_STEP to ${SIMDJSON_STRUCTURAL_INDEXER_STEP}.")
|
||||
add_compile_definitions(SIMDJSON_STRUCTURAL_INDEXER_STEP=${SIMDJSON_STRUCTURAL_INDEXER_STEP})
|
||||
endif()
|
||||
# LTO seems to create all sorts of fun problems. Let us
|
||||
# disable temporarily.
|
||||
#include(CheckIPOSupported)
|
||||
|
||||
@@ -4,3 +4,4 @@ if("@SIMDJSON_ENABLE_THREADS@")
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/simdjsonTargets.cmake")
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/simdjson_staticTargets.cmake" OPTIONAL)
|
||||
|
||||
Vendored
+9
-5
@@ -22,7 +22,7 @@ endif()
|
||||
# The bulk of our benchmarking and testing data has been moved simdjson/simdjson-data
|
||||
import_dependency(simdjson-data simdjson/simdjson-data a5b13babe65c1bba7186b41b43d4cbdc20a5c470)
|
||||
add_dependency(simdjson-data)
|
||||
|
||||
option(SIMDJSON_USE_BOOST_JSON "Try to include BOOST_JSON, this may break your binaries under some systems." OFF)
|
||||
# This prevents variables declared with set() from unnecessarily escaping and
|
||||
# should not be called more than once
|
||||
function(competition_scope_)
|
||||
@@ -36,8 +36,8 @@ function(competition_scope_)
|
||||
#endif
|
||||
|
||||
int main() {}
|
||||
]] USE_BOOST_JSON)
|
||||
if(USE_BOOST_JSON)
|
||||
]] SIMDJSON_FOUND_STRING_VIEW)
|
||||
if(SIMDJSON_FOUND_STRING_VIEW AND SIMDJSON_USE_BOOST_JSON)
|
||||
import_dependency(boostjson boostorg/json ee8d72d)
|
||||
add_library(boostjson STATIC "${boostjson_SOURCE_DIR}/src/src.cpp")
|
||||
target_compile_definitions(boostjson PUBLIC BOOST_JSON_STANDALONE)
|
||||
@@ -104,7 +104,11 @@ int main() {}
|
||||
target_compile_definitions(rapidjson INTERFACE RAPIDJSON_HAS_STDSTRING)
|
||||
target_include_directories(rapidjson SYSTEM INTERFACE
|
||||
"${rapidjson_SOURCE_DIR}/include")
|
||||
target_compile_definitions(rapidjson INTERFACE SIMDJSON_COMPETITION_RAPIDJSON)
|
||||
if (CMAKE_COMPILER_IS_GNUCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14)
|
||||
message(STATUS "Disabling rapidjson")
|
||||
else()
|
||||
target_compile_definitions(rapidjson INTERFACE SIMDJSON_COMPETITION_RAPIDJSON)
|
||||
endif()
|
||||
|
||||
import_dependency(sajson chadaustin/sajson 2dcfd35)
|
||||
add_library(sajson INTERFACE)
|
||||
@@ -130,7 +134,7 @@ int main() {}
|
||||
add_library(competition-core INTERFACE)
|
||||
target_link_libraries(competition-core INTERFACE nlohmann_json rapidjson sajson cjson jsmn yyjson)
|
||||
|
||||
if(USE_BOOST_JSON)
|
||||
if(TARGET boostjson)
|
||||
target_compile_definitions(boostjson INTERFACE HAS_BOOST_JSON)
|
||||
target_link_libraries(competition-core INTERFACE boostjson)
|
||||
endif()
|
||||
|
||||
+774
-114
File diff suppressed because it is too large
Load Diff
+11
-5
@@ -71,6 +71,12 @@ For best performance, a `parser` instance should be reused over several files: o
|
||||
If you need a lower-level interface, you may call the function `parser.parse(const char * p, size_t l)` on a pointer `p` while specifying the
|
||||
length of your input `l` in bytes. To see how to get the very best performance from a low-level approach, you way want to read our [performance notes](https://github.com/simdjson/simdjson/blob/master/doc/performance.md#padding-and-temporary-copies) on this topic (see the Padding and Temporary Copies section).
|
||||
|
||||
*Windows-specific*: Windows users who need to read files with
|
||||
non-ANSI characters in the name should set their code page to
|
||||
UTF-8 (65001). This should be the default with Windows 11 and better.
|
||||
Further, they may use the AreFileApisANSI function to determine whether
|
||||
the filename is interpreted using the ANSI or the system default OEM
|
||||
codepage, and they may call SetFileApisToOEM accordingly.
|
||||
|
||||
Using the Parsed JSON
|
||||
---------------------
|
||||
@@ -223,13 +229,13 @@ dom::element cars = parser.parse(cars_json);
|
||||
cout << cars.at_pointer("/0/tire_pressure/1") << endl; // Prints 39.9
|
||||
```
|
||||
|
||||
A JSON Path is a sequence of segments each starting with the '/' character. Within arrays, an integer
|
||||
A JSON Pointer expression is a sequence of segments each starting with the '/' character. Within arrays, an integer
|
||||
index allows you to select the indexed node. Within objects, the string value of the key allows you to
|
||||
select the value. If your keys contain the characters '/' or '~', they must be escaped as '~1' and
|
||||
'~0' respectively. An empty JSON Path refers to the whole document.
|
||||
'~0' respectively. An empty JSON Pointer expression refers to the whole document.
|
||||
|
||||
We also extend the JSON Pointer support to include *relative* paths.
|
||||
You can apply a JSON path to any node and the path gets interpreted relatively, as if the current node were a whole JSON document.
|
||||
You can apply a JSON Pointer expression to any node and the path gets interpreted relatively, as if the current node were a whole JSON document.
|
||||
|
||||
Consider the following example:
|
||||
|
||||
@@ -329,10 +335,10 @@ int main(void) {
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::element tweets; // invalid until the get() succeeds
|
||||
auto error = parser.load("twitter.json").get(tweets);
|
||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
uint64_t identifier;
|
||||
error = tweets["statuses"].at(0)["id"].get(identifier);
|
||||
if(error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
std::cout << identifier << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -11,27 +11,31 @@ CPU Architecture-Specific Implementations
|
||||
Overview
|
||||
--------
|
||||
|
||||
|
||||
|
||||
The simdjson library takes advantage of SIMD instruction sets such as NEON, SSE and AVX to achieve
|
||||
much of its speed. Because these instruction sets work differently, simdjson has to compile a
|
||||
different version of the JSON parser for different CPU architectures, often with different
|
||||
algorithms to take better advantage of a given CPU!
|
||||
|
||||
The current implementations are:
|
||||
* icelake: AVX-512F, AVX-512VBMI, etc.
|
||||
* haswell: AVX2 (2013 Intel Haswell or later)
|
||||
* icelake: AVX-512F, AVX-512_VBMI, AVX-512_VBMI2, AVX-512_DQ, AVX-512512_CD, AVX-512_BW, AVX-512_VL (2019 Intel Ice Lake, Intel Rocket Lake, Intel Sapphire Rapids, AMD Zen 4)
|
||||
* haswell: AVX2 (2013 Intel Haswell or later, all AMD Zen processors)
|
||||
* westmere: SSE4.2 (2010 Westmere or later).
|
||||
* arm64: 64-bit ARMv8-A NEON
|
||||
* ppc64: 64-bit POWER8 and POWER9 with VSX and ALTIVEC extensions. Both big endian and little endian are implemented, depends on the compiler you are using. The library is tested on recent, little-endian, POWER systems.
|
||||
* ppc64: 64-bit POWER8 and POWER9 with VSX and ALTIVEC extensions. Both big endian and little endian are implemented, depending on the compiler you are using. The library is tested on recent, little-endian, POWER systems.
|
||||
* lasx: Loongson Advanced SIMD EXtension (LASX), a 256-bit vector expansion for the LoongArch architecture.
|
||||
* lsx: Loongson SIMD EXtension (LSX), a 128-bit vector expansion for the LoongArch architecture.
|
||||
* fallback: A generic implementation that runs on any 64-bit processor.
|
||||
|
||||
In many cases, you don't know where your compiled binary is going to run, so simdjson automatically
|
||||
compiles *all* the implementations into the executable. On Intel, it will include 4 implementations
|
||||
(icelake, haswell, westmere and fallback), on ARM it will include 2 (arm64 and fallback), and on PPC
|
||||
(icelake, haswell, westmere and fallback), on 64-bit ARM it will include just one since running dispatching is unnecessary, and on PPC
|
||||
it will include 2 (ppc64 and fallback).
|
||||
|
||||
If you know more about where you're going to run and want to save the space, you can disable any of
|
||||
these implementations at compile time with `-DSIMDJSON_IMPLEMENTATION_X=0` (where X is ICELAKE, HASWELL,
|
||||
WESTMERE, ARM64, PPC64 and FALLBACK).
|
||||
WESTMERE, ARM64, PPC64, LSX, LASX and FALLBACK).
|
||||
|
||||
The simdjson library automatically sets header flags for each implementation as it compiles; there
|
||||
is no need to set architecture-specific flags yourself (e.g., `-mavx2`, `/AVX2` or
|
||||
@@ -75,8 +79,7 @@ And look them up by name:
|
||||
```c++
|
||||
cout << simdjson::get_available_implementations()["fallback"]->description() << endl;
|
||||
```
|
||||
Though the fallback implementation should always be available, others might be missing. When
|
||||
an implementation is not available, the bracket call `simdjson::get_available_implementations()[name]`
|
||||
When an implementation is not available, the bracket call `simdjson::get_available_implementations()[name]`
|
||||
will return the null pointer.
|
||||
|
||||
The available implementations have been compiled but may not necessarily be run safely on your system
|
||||
@@ -101,8 +104,8 @@ by comparing it with the null pointer.
|
||||
|
||||
```c++
|
||||
auto my_implementation = simdjson::get_available_implementations()["haswell"];
|
||||
if(! my_implementation) { exit(1); }
|
||||
if(! my_implementation->supported_by_runtime_system()) { exit(1); }
|
||||
if (! my_implementation) { exit(1); }
|
||||
if (! my_implementation->supported_by_runtime_system()) { exit(1); }
|
||||
simdjson::get_active_implementation() = my_implementation;
|
||||
```
|
||||
|
||||
@@ -113,7 +116,7 @@ You should call `supported_by_runtime_system()` to compare the processor's featu
|
||||
|
||||
```c++
|
||||
for (auto implementation : simdjson::get_available_implementations()) {
|
||||
if(implementation->supported_by_runtime_system()) {
|
||||
if (implementation->supported_by_runtime_system()) {
|
||||
cout << implementation->name() << ": " << implementation->description() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-4
@@ -17,6 +17,9 @@ Contents
|
||||
|
||||
- [Motivations](#motivations)
|
||||
- [How it works](#how-it-works)
|
||||
- [Context](#context)
|
||||
- [Design](#design)
|
||||
- [Threads](#threads)
|
||||
- [Support](#support)
|
||||
- [API](#api)
|
||||
- [Use cases](#use-cases)
|
||||
@@ -193,12 +196,12 @@ Let us illustrate the idea with code:
|
||||
simdjson::ondemand::parser parser;
|
||||
simdjson::ondemand::document_stream stream;
|
||||
auto error = parser.iterate_many(json).get(stream);
|
||||
if( error ) { /* do something */ }
|
||||
if (error) { /* do something */ }
|
||||
auto i = stream.begin();
|
||||
size_t count{0};
|
||||
for(; i != stream.end(); ++i) {
|
||||
auto doc = *i;
|
||||
if(!i.error()) {
|
||||
if (!i.error()) {
|
||||
std::cout << "got full document at " << i.current_index() << std::endl;
|
||||
std::cout << i.source() << std::endl;
|
||||
count++;
|
||||
@@ -234,7 +237,7 @@ Consider the following example where a truncated document (`{"key":"intentionall
|
||||
simdjson::ondemand::parser parser;
|
||||
simdjson::ondemand::document_stream stream;
|
||||
auto error = parser.iterate_many(json,json.size()).get(stream);
|
||||
if(error) { std::cerr << error << std::endl; return; }
|
||||
if (error) { std::cerr << error << std::endl; return; }
|
||||
for(auto i = stream.begin(); i != stream.end(); ++i) {
|
||||
std::cout << i.source() << std::endl;
|
||||
}
|
||||
@@ -266,7 +269,7 @@ Example:
|
||||
// we pass 'true' to the allow_comma parameter, the batch size will be set to at least
|
||||
// the document size.
|
||||
auto error = parser.iterate_many(json, 32, true).get(doc_stream);
|
||||
if(error) { std::cerr << error << std::endl; return; }
|
||||
if (error) { std::cerr << error << std::endl; return; }
|
||||
for (auto doc : doc_stream) {
|
||||
std::cout << doc.type() << std::endl;
|
||||
}
|
||||
|
||||
@@ -679,14 +679,14 @@ in production systems:
|
||||
ondemand::object c1 = parent["child1"];
|
||||
// c1 owns the focus
|
||||
//
|
||||
if(std::string_view(c1["name"]) != "John") { ... }
|
||||
if (std::string_view(c1["name"]) != "John") { ... }
|
||||
// c2 attempts to grab the focus from parent but fails
|
||||
ondemand::object c2 = parent["child2"];
|
||||
// c2 is now in an unsafe state and the following line would be unsafe
|
||||
// if(std::string_view(c2["name"]) != "Daniel") { return false; }
|
||||
// if (std::string_view(c2["name"]) != "Daniel") { return false; }
|
||||
```
|
||||
|
||||
A correct usage is given by the following example:
|
||||
A correct usage is given by the following example:
|
||||
|
||||
```C++
|
||||
ondemand::parser parser;
|
||||
@@ -697,7 +697,7 @@ in production systems:
|
||||
{
|
||||
ondemand::object c1 = parent["child1"];
|
||||
// c1 grabbed the focus from parent
|
||||
if(std::string_view(c1["name"]) != "John") { return false; }
|
||||
if (std::string_view(c1["name"]) != "John") { return false; }
|
||||
}
|
||||
// c1 went out of scope, so its destructor was called and the focus
|
||||
// was handed back to parent.
|
||||
@@ -705,7 +705,7 @@ in production systems:
|
||||
ondemand::object c2 = parent["child2"];
|
||||
// c2 grabbed the focus from parent
|
||||
// the following is safe:
|
||||
if(std::string_view(c2["name"]) != "Daniel") { return false; }
|
||||
if (std::string_view(c2["name"]) != "Daniel") { return false; }
|
||||
}
|
||||
```
|
||||
|
||||
@@ -752,7 +752,7 @@ On relevant systems, the On Demand API provides some support for runtime dispatc
|
||||
|
||||
Some users wish to run at the best possible speed. Under recent Intel and AMD processors, these users should take additional steps to verify that their code is well optimized.
|
||||
|
||||
Given that the On Demand API offer limited runtime dispatching, it matters that your code is compiled against a specific CPU target. You should verify that the code is compiled against the target you expect. Thankfully, the simdjson library will tell you exactly what it detects as an implementation: `icelake` (AVX512 x64 processors), `haswell` (AVX2 x64 processors), `westmere` (SSE4 x64 processors), `arm64` (64-bit ARM), `ppc64` (64-bit POWER), `fallback` (others). Under x64 processors, many programmers will want to target `haswell` whereas under ARM, most programmers will want to target `arm64` (and it should do so automatically). The `fallback` is probably only good for testing purposes, not for deployment.
|
||||
Given that the On Demand API offer limited runtime dispatching, it matters that your code is compiled against a specific CPU target. You should verify that the code is compiled against the target you expect. Thankfully, the simdjson library will tell you exactly what it detects as an implementation: `icelake` (AVX512 x64 processors), `haswell` (AVX2 x64 processors), `westmere` (SSE4 x64 processors), `arm64` (64-bit ARM), `ppc64` (64-bit POWER), `lasx` (LoongArch), `lsx` (LoongArch), `fallback` (others). Under x64 processors, many programmers will want to target `haswell` whereas under ARM, most programmers will want to target `arm64` (and it should do so automatically). The `fallback` is probably only good for testing purposes, not for deployment.
|
||||
|
||||
```C++
|
||||
std::cout << simdjson::builtin_implementation()->name() << std::endl;
|
||||
@@ -779,4 +779,4 @@ Instead of specifying a specific microarchitecture, you can let your compiler do
|
||||
|
||||
Passing `-march=native` to the compiler may make On Demand faster by allowing it to use optimizations specific to your machine. You cannot do this, however, if you are compiling code that might be run on less advanced machines. That is, be mindful that when compiling with the `-march=native` flag, the resulting binary will run on the current system but may not run on other systems (e.g., on an old processor).
|
||||
|
||||
If you are compiling on an ARM or POWER system, you do not need to be concerned with CPU selection during compilation. The `-march=native` flag useful for best performance on x64 (e.g., Intel) systems but it is generally unsupported on some platforms such as ARM (aarch64) or POWER.
|
||||
If you are compiling on an ARM or POWER system, you do not need to be concerned with CPU selection during compilation. The `-march=native` flag is useful for best performance on x64 (e.g., Intel) systems but it is generally unsupported on some platforms such as ARM (aarch64) or POWER.
|
||||
|
||||
+3
-3
@@ -184,12 +184,12 @@ Let us illustrate the idea with code:
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::document_stream stream;
|
||||
auto error = parser.parse_many(json).get(stream);
|
||||
if( error ) { /* do something */ }
|
||||
if (error) { /* do something */ }
|
||||
auto i = stream.begin();
|
||||
size_t count{0};
|
||||
for(; i != stream.end(); ++i) {
|
||||
auto doc = *i;
|
||||
if(!doc.error()) {
|
||||
if (!doc.error()) {
|
||||
std::cout << "got full document at " << i.current_index() << std::endl;
|
||||
std::cout << i.source() << std::endl;
|
||||
count++;
|
||||
@@ -225,7 +225,7 @@ Consider the following example where a truncated document (`{"key":"intentionall
|
||||
simdjson::dom::parser parser;
|
||||
simdjson::dom::document_stream stream;
|
||||
auto error = parser.parse_many(json,json.size()).get(stream);
|
||||
if(error) { std::cerr << error << std::endl; return; }
|
||||
if (error) { std::cerr << error << std::endl; return; }
|
||||
for(auto doc : stream) {
|
||||
std::cout << doc << std::endl;
|
||||
}
|
||||
|
||||
+109
-1
@@ -14,6 +14,7 @@ testing and get the best performance.
|
||||
* [Number parsing](#number-parsing)
|
||||
* [Visual Studio](#visual-studio)
|
||||
* [Power Usage and Downclocking](#power-usage-and-downclocking)
|
||||
* [Free Padding](#free-padding)
|
||||
|
||||
|
||||
NDEBUG directive
|
||||
@@ -159,7 +160,7 @@ When compiling with Visual Studio, we recommend the flags `/Ob2 /O2` or better.
|
||||
|
||||
Recent versions of Microsoft Visual Studio on Windows provides support for the LLVM Clang compiler. You only need to install the "Clang compiler" optional component (ClangCL). You may also get a copy of the 64-bit LLVM CLang compiler for [Windows directly from LLVM](https://releases.llvm.org/download.html). The simdjson library fully supports the LLVM Clang compiler under Windows. In fact, you may get better performance out of simdjson with the LLVM Clang compiler than with the regular Visual Studio compiler. Meanwhile the [LLVM CLang compiler is binary compatible with Visual Studio](https://clang.llvm.org/docs/MSVCCompatibility.html) which means that you can combine their binaries (executables and libraries).
|
||||
|
||||
Under Windows, we also support the GNU GCC compiler via MSYS2. The performance of 64-bit MSYS2 under Windows excellent (on par with Linux).
|
||||
Under Windows, we also support the GNU GCC compiler via MSYS2. The performance of 64-bit MSYS2 under Windows is excellent (on par with Linux).
|
||||
|
||||
|
||||
Power Usage and Downclocking
|
||||
@@ -179,3 +180,110 @@ The simdjson library does not generally make use of heavy 256-bit instructions.
|
||||
the macro `SIMDJSON_AVX512_ALLOWED` to `0` in C++ prior to importing the headers.
|
||||
|
||||
You may still be worried about which SIMD instruction set is used by simdjson. Thankfully, [you can always determine and change which architecture-specific implementation is used](implementation-selection.md) by simdjson. Thus even if your CPU supports AVX2, you do not need to use AVX2. You are in control.
|
||||
|
||||
|
||||
Free Padding
|
||||
-------
|
||||
|
||||
For performance reasons, the simdjson library requires that the JSON input contain at least
|
||||
`simdjson::SIMDJSON_PADDING` bytes at the end of the stream. The value `simdjson::SIMDJSON_PADDING` is
|
||||
small (e.g., 64 bytes). On modern systems, you can safely read beyond an allocated buffers,
|
||||
as long as you remain within an allocated page. Pages on modern systems span at least 4 kilobytes,
|
||||
but can be significantly larger. E.g., Apple systems favour pages spanning 16 kilobytes.
|
||||
|
||||
In effect, it means that you can almost always read a few bytes beyond your current buffer---without
|
||||
allocating extra memory. However, tools such as valgrind or memory sanitizers will flag such behavior as unsafe.
|
||||
Nevertheless, you can still make sure of this capability in your code if you are an expert
|
||||
programmer and you are willing to silence sanitizer warnings. The following code provides
|
||||
a portable example.
|
||||
|
||||
|
||||
The conditional compilation checks for the `_MSC_VER` macro (indicating Microsoft Visual Studio)
|
||||
and includes platform-specific headers accordingly.
|
||||
The `page_size()` function determines the default size of a memory page in bytes on the system.
|
||||
On Windows (when `_WIN32` is defined), it uses `GetSystemInfo()` to retrieve system information and obtain the page size.
|
||||
On other platforms (non-Windows), it uses `sysconf(_SC_PAGESIZE)` to get the page size.
|
||||
The function returns the page size.
|
||||
The `need_allocation()` function checks whether the buffer (given by `buf`) plus the specified length (`len`) is near a page boundary.
|
||||
If the buffer extends beyond the current page when padded by `simdjson::SIMDJSON_PADDING`, it returns true, indicating that reallocation is needed.
|
||||
Otherwise, it returns false.
|
||||
The `get_padded_string_view()` creates a `padded_string_view` from the input buffer.
|
||||
If reallocation is needed (unlikely case), it allocates a new padded_string and assigns it to `jsonbuffer`.
|
||||
Otherwise (very likely), it creates a `padded_string_view` directly from the buffer.
|
||||
The `simdjson::SIMDJSON_PADDING` ensures that there is additional padding for parsing efficiency.
|
||||
The calling code just needs to provide `jsonbuffer` (an instance of `simdjson::padded_string`)
|
||||
and pass `get_padded_string_view(buf, len, jsonbuffer)` to `parser.iterate`. Most of the time,
|
||||
this code will not allocate new memory.
|
||||
|
||||
|
||||
```cpp
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <sysinfoapi.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include "simdjson.h"
|
||||
#include <cstdio>
|
||||
|
||||
// Returns the default size of the page in bytes on this system.
|
||||
long page_size() {
|
||||
#ifdef _WIN32
|
||||
SYSTEM_INFO sysInfo;
|
||||
GetSystemInfo(&sysInfo);
|
||||
long pagesize = sysInfo.dwPageSize;
|
||||
#else
|
||||
long pagesize = sysconf(_SC_PAGESIZE);
|
||||
#endif
|
||||
return pagesize;
|
||||
}
|
||||
|
||||
// Returns true if the buffer + len + simdjson::SIMDJSON_PADDING crosses the
|
||||
// page boundary.
|
||||
bool need_allocation(const char *buf, size_t len) {
|
||||
return ((reinterpret_cast<uintptr_t>(buf + len - 1) % page_size()) <
|
||||
simdjson::SIMDJSON_PADDING);
|
||||
}
|
||||
|
||||
simdjson::padded_string_view
|
||||
get_padded_string_view(const char *buf, size_t len,
|
||||
simdjson::padded_string &jsonbuffer) {
|
||||
if (need_allocation(buf, len)) { // unlikely case
|
||||
jsonbuffer = simdjson::padded_string(buf, len);
|
||||
return jsonbuffer;
|
||||
} else { // no reallcation needed (very likely)
|
||||
return simdjson::padded_string_view(buf, len,
|
||||
len + simdjson::SIMDJSON_PADDING);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("page_size: %ld\n", page_size());
|
||||
const char *jsonpoiner = R"(
|
||||
{
|
||||
"key": "value"
|
||||
}
|
||||
)";
|
||||
size_t len = strlen(jsonpoiner);
|
||||
simdjson::padded_string jsonbuffer; // only allocate if needed
|
||||
simdjson::ondemand::parser parser;
|
||||
simdjson::ondemand::document doc;
|
||||
simdjson::error_code error =
|
||||
parser.iterate(get_padded_string_view(jsonpoiner, len, jsonbuffer))
|
||||
.get(doc);
|
||||
if (error) {
|
||||
printf("error: %s\n", simdjson::error_message(error));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
std::string_view value;
|
||||
error = doc["key"].get_string().get(value);
|
||||
if (error) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf("Value: \"%.*s\"\n", (int)value.size(), value.data());
|
||||
if (value != "value") {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
```
|
||||
+1
-1
@@ -29,7 +29,7 @@ It is sometimes useful to start with an example. Consider the following JSON doc
|
||||
The following is a dump of the content of the tape, with the first number of each line representing the index of a tape element.
|
||||
|
||||
### The Tape
|
||||
| index | element (64 bit word) |
|
||||
| index | element (64-bit word) |
|
||||
| ----- | ------------------------------------------------------------------- |
|
||||
| 0 | r // pointing to 39 (right after last node) |
|
||||
| 1 | { // pointing to next tape location 38 (first node after the scope) |
|
||||
|
||||
@@ -35,14 +35,4 @@ IF(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
add_quickstart_test(quickstart_ondemand_noexceptions quickstart_ondemand_noexceptions.cpp NO_EXCEPTIONS LABELS quickstart_ondemand acceptance)
|
||||
add_quickstart_test(quickstart_ondemand_noexceptions11 quickstart_ondemand_noexceptions.cpp NO_EXCEPTIONS CXX_STANDARD c++11 LABELS quickstart_ondemand)
|
||||
|
||||
# SingleStage Quick Start
|
||||
if (SIMDJSON_EXCEPTIONS)
|
||||
add_quickstart_test(quickstart_singlestage quickstart_singlestage.cpp LABELS quickstart_singlestage acceptance)
|
||||
add_quickstart_test(quickstart_singlestage11 quickstart_singlestage.cpp CXX_STANDARD c++11 LABELS quickstart_singlestage acceptance)
|
||||
add_quickstart_test(quickstart_singlestage14 quickstart_singlestage.cpp CXX_STANDARD c++14 LABELS quickstart_singlestage)
|
||||
endif()
|
||||
|
||||
add_quickstart_test(quickstart_singlestage_noexceptions quickstart_singlestage_noexceptions.cpp NO_EXCEPTIONS LABELS quickstart_singlestage acceptance)
|
||||
add_quickstart_test(quickstart_singlestage_noexceptions11 quickstart_singlestage_noexceptions.cpp NO_EXCEPTIONS CXX_STANDARD c++11 LABELS quickstart_singlestage)
|
||||
|
||||
endif()
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <iostream>
|
||||
#include "simdjson.h"
|
||||
using namespace simdjson;
|
||||
int main(void) {
|
||||
ondemand::parser parser;
|
||||
padded_string json = padded_string::load("twitter.json");
|
||||
ondemand::document tweets = parser.iterate(json);
|
||||
std::cout << uint64_t(tweets["search_metadata"]["count"]) << " results." << std::endl;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <iostream>
|
||||
#include "simdjson.h"
|
||||
using namespace simdjson;
|
||||
int main(void) {
|
||||
padded_string json;
|
||||
auto error = padded_string::load("twitter.json").get(json);
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
|
||||
ondemand::parser parser;
|
||||
ondemand::document tweets;
|
||||
error = parser.iterate(json).get(tweets);
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
|
||||
uint64_t count;
|
||||
error = tweets["search_metadata"]["count"].get(count);
|
||||
if (error) { std::cerr << error << std::endl; return EXIT_FAILURE; }
|
||||
|
||||
std::cout << count << " results." << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -63,7 +63,6 @@ if(SIMDJSON_ENABLE_FUZZING)
|
||||
implement_fuzzer(fuzz_minifyimpl) # minify *without* parsing, plus compare implementations
|
||||
implement_fuzzer(fuzz_ndjson) # the ndjson api
|
||||
implement_fuzzer(fuzz_ondemand)
|
||||
# implement_fuzzer(fuzz_singlestage) # TODO why no worky
|
||||
implement_fuzzer(fuzz_padded)
|
||||
implement_fuzzer(fuzz_parser)
|
||||
implement_fuzzer(fuzz_print_json)
|
||||
|
||||
@@ -78,7 +78,7 @@ fi
|
||||
# Different levels may uncover different types of bugs, see this interesting
|
||||
# thread: https://github.com/google/oss-fuzz/issues/2295#issuecomment-481493392
|
||||
# Oss-fuzz uses -O1 so it may be relevant to use something else than that,
|
||||
# to do something oss-fuzz doesn't.
|
||||
# to do something oss-fuzz does not do.
|
||||
variant=sanitizers-O3
|
||||
|
||||
if [ ! -d build-$variant ] ; then
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
|
||||
// Split data into two strings, json pointer and the document string.
|
||||
// Split data into two strings, JSON Pointer and the document string.
|
||||
// Might end up with none, either or both being empty, important for
|
||||
// covering edge cases such as
|
||||
// https://github.com/simdjson/simdjson/issues/1142 Inputs missing the
|
||||
// separator line will get an empty json pointer but the all the input put in
|
||||
// separator line will get an empty JSON Pointer but the all the input put in
|
||||
// the document string. This means test data from other fuzzers that take json
|
||||
// input works for this fuzzer as well.
|
||||
FuzzData fd(Data, Size);
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "FuzzUtils.h"
|
||||
#include "simdjson.h"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
FuzzData fd(Data, Size);
|
||||
const int action = fd.getInt<0, 12>();
|
||||
|
||||
// split the remainder of the document into strings
|
||||
auto strings = fd.splitIntoStrings();
|
||||
while (strings.size() < 1) {
|
||||
strings.emplace_back();
|
||||
}
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
simdjson::singlestage::parser parser;
|
||||
simdjson::padded_string padded(strings[0]);
|
||||
auto doc = parser.iterate(padded);
|
||||
if (doc.error()) {
|
||||
return 0;
|
||||
}
|
||||
for (auto item : doc) {
|
||||
switch (action) {
|
||||
case 0: {
|
||||
simdjson_unused auto x = item.get_string();
|
||||
} break;
|
||||
case 1: {
|
||||
simdjson_unused auto x = item.get_bool();
|
||||
} break;
|
||||
case 2: {
|
||||
simdjson_unused auto x = item.get_array();
|
||||
} break;
|
||||
case 3: {
|
||||
simdjson_unused auto x = item.get_int64();
|
||||
} break;
|
||||
case 4: {
|
||||
simdjson_unused auto x = item.get_double();
|
||||
} break;
|
||||
case 5: {
|
||||
simdjson_unused auto x = item.get_object();
|
||||
} break;
|
||||
case 6: {
|
||||
simdjson_unused auto x = item.get_uint64();
|
||||
} break;
|
||||
case 7: {
|
||||
simdjson_unused auto x = item.get_raw_json_string();
|
||||
} break;
|
||||
case 8: {
|
||||
simdjson_unused auto x = item.is_null();
|
||||
} break;
|
||||
case 9: {
|
||||
simdjson_unused auto x = item.begin();
|
||||
} break;
|
||||
case 10: {
|
||||
simdjson_unused auto x = item.end();
|
||||
} break;
|
||||
case 11: {
|
||||
for (auto e : item) {
|
||||
simdjson_unused auto x = e.is_null();
|
||||
}
|
||||
} break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
#if SIMDJSON_EXCEPTIONS
|
||||
} catch (...) {
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -53,6 +53,5 @@
|
||||
|
||||
#include "simdjson/dom.h"
|
||||
#include "simdjson/ondemand.h"
|
||||
#include "simdjson/singlestage.h"
|
||||
|
||||
#endif // SIMDJSON_H
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef SIMDJSON_ARM64_BASE_H
|
||||
#define SIMDJSON_ARM64_BASE_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/base.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
/**
|
||||
@@ -23,11 +23,4 @@ template <typename T> struct simd8x64;
|
||||
} // namespace arm64
|
||||
} // namespace simdjson
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
// If we're editing one of the files in this directory, begin the implementation!
|
||||
#ifndef SIMDJSON_IMPLEMENTATION
|
||||
#include "simdjson/arm64/begin.h"
|
||||
#endif
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
|
||||
#endif // SIMDJSON_ARM64_BASE_H
|
||||
|
||||
@@ -6,3 +6,5 @@
|
||||
#include "simdjson/arm64/numberparsing_defs.h"
|
||||
#include "simdjson/arm64/simd.h"
|
||||
#include "simdjson/arm64/stringparsing_defs.h"
|
||||
|
||||
#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1
|
||||
@@ -1,11 +1,13 @@
|
||||
#ifndef SIMDJSON_ARM64_BITMANIPULATION_H
|
||||
#define SIMDJSON_ARM64_BITMANIPULATION_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/arm64/base.h"
|
||||
#include "simdjson/arm64/intrinsics.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace arm64 {
|
||||
namespace {
|
||||
|
||||
// We sometimes call trailing_zero on inputs that are zero,
|
||||
@@ -98,7 +100,7 @@ simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *re
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace arm64
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_ARM64_BITMANIPULATION_H
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#ifndef SIMDJSON_ARM64_BITMASK_H
|
||||
#define SIMDJSON_ARM64_BITMASK_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/arm64/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace arm64 {
|
||||
namespace {
|
||||
|
||||
//
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/arm64/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
|
||||
#undef SIMDJSON_IMPLEMENTATION
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#ifndef SIMDJSON_ARM64_IMPLEMENTATION_H
|
||||
#define SIMDJSON_ARM64_IMPLEMENTATION_H
|
||||
|
||||
#ifndef SIMDJSON_AMALGAMATED
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/base.h"
|
||||
#include "simdjson/implementation.h"
|
||||
#include "simdjson/internal/instruction_set.h"
|
||||
#endif // SIMDJSON_AMALGAMATED
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace arm64 {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#ifndef SIMDJSON_ARM64_INTRINSICS_H
|
||||
#define SIMDJSON_ARM64_INTRINSICS_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/arm64/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
// This should be the correct header whether
|
||||
// you use visual studio or other compilers.
|
||||
#include <arm_neon.h>
|
||||
|
||||
#include "simdjson/arm64/base.h"
|
||||
|
||||
static_assert(sizeof(uint8x16_t) <= simdjson::SIMDJSON_PADDING, "insufficient padding for arm64");
|
||||
|
||||
#endif // SIMDJSON_ARM64_INTRINSICS_H
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user