get<T>() and get_to() of a view call T's from_json() with the view itself
when that from_json() accepts views but not an unrelated probe type, and
fall back to materialize() otherwise. The from_json() functions of the
NLOHMANN_DEFINE_TYPE_*, NLOHMANN_DEFINE_DERIVED_TYPE_* and
NLOHMANN_JSON_SERIALIZE_ENUM(_STRICT) macros accept basic_json values and
views; a derived type whose base reads only json reads the base part
through materialize(). The library's own from_json() overloads are not
called with views: from_json() of a view (and of the probe) only looks up
functions by ADL.
New public trait nlohmann::is_json_view<T>, and the member type
basic_json_type of basic_json_view. With duplicate keys, the members of
such a T are those the view's lookups find (the first ones).
bench_decode.cpp measures decoding into structs (4-6x faster than
materialize().get<T>() on twitter, citm_catalog, and synthetic records).
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
- bench_view: add "(editable)" rows for json_editable_document and a
parse+dump workload, so the cost of lazy float conversion shows next to the
parse row (the traverse workload already includes the parse). Check that
all engines' dumps agree where outputs are comparable.
- compare.py: add --aligned, which also builds and runs with aligned code and
reports both tables, so code-layout artifacts become visible. Off by
default; the default output is unchanged. Not run end to end yet.
- README: say which engines are like-for-like peers (yyjson, simdjson DOM) and
which are mutable reference points (Boost.JSON, json::parse, the editable
json_view); explain the lazy float conversion and the eager prototype that
was measured and dropped.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Compare json_view with yyjson, simdjson, and Boost.JSON
tests/benchmarks/json_view/ holds a comparison with other
libraries, answering the question users ask when they pick one.
It is not built by CMake and not run by CI.
- bench_view.cpp: parse, traverse, select and dump of twitter,
citm_catalog, canada, jeopardy, a tweet and an RPC request,
against json_view, yyjson, simdjson, Boost.JSON and json::parse,
all agreeing and run interleaved.
- bench_corpus.cpp: parse, traverse and dump of any file list.
- bench_edit.cpp: parses, edits through each library's own API,
and serializes; all outputs must describe the same value.
- compare.py: builds both programs with system or pinned,
SHA-256-checked downloads, and writes results with the commit,
CPU, OS, compiler and library versions.
- README.md and a workflow that runs on demand or via a PR label.
Fairness fixes folded in: each engine runs once untimed before
each timed round, so the next one no longer pays for the
previous one's cleanup; dump is also compared with source numbers
against yyjson's raw-number mode; a "simdjson DOM (fresh)" column
and a reused-document column for json_view were added;
compare.py's paths are absolute; downloads use a .part file and a
failed checksum removes the archive.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Make the downloads of json_view's compare.py robust
Hash the archives in chunks instead of reading them into memory, download
with a timeout, extract into a temporary directory that is renamed into
place only after success (a half-extracted directory was trusted forever),
and split CXX and CC into arguments so that values like 'ccache g++' work.
Note at the pins that a SHA-256 mismatch of a GitHub tag archive means
that GitHub regenerated it.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Add a timeout and a concurrency group to the json_view benchmarks
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
* Check the CSV file and the round count in the json_view benchmarks
fopen() of the CSV output was not checked, so an unwritable directory made
fprintf() write to a null FILE*; the round count is parsed with strtol and
clamped instead of atoi.
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
---------
Signed-off-by: Niels Lohmann <mail@nlohmann.me>