////
Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
Copyright (c) 2025 Dmitry Arkhipov (grisumbras@yandex.ru)

Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Official repository: https://github.com/boostorg/json
////

[pagelevels=1,toclevels=1]
= 基准测试 本节将 Boost.JSON 与两个广泛使用的具有类似功能的库进行性能比较：以高性能著称的 RapidJSON 和以功能丰富著称的JSON for Modern C++ 库（nlohmann/json）。bench 程序测量解析和序列化一组代表典型工作负载的 JSON 的吞吐量。评估的实现包括：

.Implementations
|===
|Name|Description

| *boost(pool)*
| Parses the input using a <<ref_monotonic_resource>>,
该资源针对解析后不进行后续修改的场景进行了优化。&lt;<ref_stream_parser>&gt; 对象在各次试验之间被复用，使得实现所分配的临时内存得以保留，从而提升性能。</ref_stream_parser>

| *boost*
| Parses the input using the <<default_memory_resource, default memory
resource&gt;&gt;, which uses the standard C++ allocator, and is designed for general use including mutation of the document after it is parsed. The &lt;<ref_stream_parser>&gt; object is reused between trials, allowing temporary memory allocated by the implementation to persist and improve performance.</ref_stream_parser>

| *rapidjson(pool)*
| Parses the input using an instance of
https://rapidjson.org/classrapidjson_1_1_memory_pool_allocator.html[`MemoryPoolAllocator`] 的实例实现的，该分配器针对“仅解析、不修改”的场景进行了优化。持有临时内存的 https://rapidjson.org/classrapidjson_1_1_generic_document.html[`Document`] 对象在多次测试之间不重复使用，否则内存消耗将无限增长，从而导致基准测试结果无效。

| *rapidjson*
| Parses the input using an instance of
使用 https://rapidjson.org/classrapidjson_1_1_crt_allocator.html[`CrtAllocator`] 的实例来实现的，该分配器使用标准 C++ 分配器，适用于通用场景，包括解析后对文档的修改。持有临时内存的 https://rapidjson.org/classrapidjson_1_1_generic_document.html[`Document`] 对象在多次测试之间不重复使用，否则内存消耗将无限增长，导致基准测试结果无效。

| *nlohmann*
| Parses the input using the static member function
https://nlohmann.github.io/json/classnlohmann_1_1basic__json_ab330c13ba254ea41fbc1c52c5c610f45.html[`json::parse`] 来实现的，该函数使用默认的 `std` 分配器，适用于通用场景，包括解析后对文档的修改。该库未提供复用解析或序列化过程中所用临时存储的接口，因此无法在后续操作中重用这些临时内存。

== 方法论
首先加载所有输入文件。随后，每种配置会运行足够多的试验次数，以确保总运行时间不少于 5 秒。每次试验会记录所用时间、调用次数（解析或序列化）以及传输的字节数，并以此生成一个样本，同时计算出以 MB/s（兆字节每秒）为单位的吞吐量。每种配置会生成多个样本（目前为五个），剔除其中非中间两个的样本后，对剩余的两个样本取平均值，作为该配置的最终基准测试结果。

输入文件位于 bench/data 目录，按如下方式布局：

.Input Files
|===
|Name|Size|Description

| <<parse_apache_builds_json,*apache_builds.json*>>
| 125KB
| Data from the Apache Jenkins installation.

| <<parse_canada_json,*canada.json*>>
| 2.2MB
| The largest file, containing a large number of 2-element arrays holding
（该二元数组是由）浮点坐标对（组成的）

| <<parse_citm_catalog_json,*citm_catalog.json*>>
| 1.69MB
| A large JSON with a variety of nesting, types, and lengths.

| <<parse_github_events_json,*github_events.json*>>
| 64KB
| An export of data from the Github Events API.

| <<parse_gsoc_2018_json,*gsoc-2018.json*>>
| 3.25MB
| Google Summer of Code 2018 data.

| <<parse_instruments_json,*instruments.json*>>
| 216KB
| An array of large objects.

| <<parse_marine_ik_json,*marine_ik.json*>>
| 2.91MB
| A three.js example model serialized to JSON.

| <<parse_mesh_json,*mesh.json*>>
| 707KB
| A JSON representing a 3D mesh. Contains many floating-point numbers.

| <<parse_mesh_pretty_json,*mesh.pretty.json*>>
| 1.54MB
| mesh.json with whitespace added.

| <<parse_numbers_json,*numbers.json*>>
| 147KB
| A array containing only floating-point numbers.

| <<parse_random_json,*random.json*>>
| 499KB
| A JSON with lots of Cyrillic characters.

| <<parse_twitter_json,*twitter.json*>>
| 617KB
| An export of data from Twitter's API.

| <<parse_twitterescaped_json,*twitterescaped.json*>>
| 550KB
| twitter.json with whitespace removed and non-ASCII characters replaced with
Unicode 转义符的。

| <<parse_update_center_json,*update-center.json*>>
| 521KB
| An export of data from Twitter's API.
|===

测试所用硬件：  **Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz**, Windows 10, 32GB RAM.

编译器及优化选项: gcc 8.1 (-O3), clang 12.0 (-O3), and msvc 19.26 (/O2).

== 解析

=== 解析 apache_builds.json
image::images/parse_apache_builds.png[width=668,align="left"]

=== 解析 canada.json
image::images/parse_canada.png[width=668,align="left"]

=== 解析 citm_catalog.json
image::images/parse_citm_catalog.png[width=668,align="left"]

=== 解析 github_events.json
image::images/parse_github_events.png[width=668,align="left"]

=== 解析 gsoc-2018.json
image::images/parse_gsoc_2018.png[width=668,align="left"]

=== 解析 instruments.json
image::images/parse_instruments.png[width=668,align="left"]

=== 解析 marine_ik.json
image::images/parse_marine_ik.png[width=668,align="left"]

=== 解析 mesh.json
image::images/parse_mesh.png[width=668,align="left"]

=== 解析 mesh.pretty.json
image::images/parse_mesh_pretty.png[width=668,align="left"]

=== 解析 numbers.json
image::images/parse_numbers.png[width=668,align="left"]

=== 解析 random.json
image::images/parse_random.png[width=668,align="left"]

=== 解析 twitter.json
image::images/parse_twitter.png[width=668,align="left"]

=== 解析 twitterescaped.json
image::images/parse_twitterescaped.png[width=668,align="left"]

=== 解析 update-center.json
image::images/parse_update_center.png[width=668,align="left"]

== 序列化

=== 序列化 canada.json
image::images/serialize_canada.png[width=668,align="left"]

=== 序列化 citm_catalog.json
image::images/serialize_citm_catalog.png[width=668,align="left"]

=== 序列化 github_events.json
image::images/serialize_github_events.png[width=668,align="left"]

=== 序列化 gsoc-2018.json
image::images/serialize_gsoc_2018.png[width=668,align="left"]

=== 序列化 instruments.json
image::images/serialize_instruments.png[width=668,align="left"]

=== 序列化 marine_ik.json
image::images/serialize_marine_ik.png[width=668,align="left"]

=== 序列化 mesh.json
image::images/serialize_mesh.png[width=668,align="left"]

=== 序列化 mesh.pretty.json
image::images/serialize_mesh_pretty.png[width=668,align="left"]

=== 序列化 numbers.json
image::images/serialize_numbers.png[width=668,align="left"]

=== 序列化 random.json
image::images/serialize_random.png[width=668,align="left"]

=== 序列化 twitter.json
image::images/serialize_twitter.png[width=668,align="left"]

=== 序列化 twitterescaped.json
image::images/serialize_twitterescaped.png[width=668,align="left"]

=== 序列化 update-center.json
image::images/serialize_update_center.png[width=668,align="left"]
