Performance profiling of JSON libraries
Latest results (October, 13, 2022):
1,000,000 read and write passes on a single core (MacBook Pro M1)
Library | Runtime (s) | Ratio |
---|---|---|
Glaze | 2.79 | 1.0 |
daw_json_link | 3.45 | 1.24 |
nlohmann json | 18.51 | 6.63 |
Test object:
{
"fixed_object": {
"int_array": [0, 1, 2, 3, 4, 5, 6],
"float_array": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
"double_array": [3288398.238, 233e22, 289e-1, 0.928759872, 0.22222848, 0.1, 0.2, 0.3, 0.4]
},
"fixed_name_object": {
"name0": "James",
"name1": "Abraham",
"name2": "Susan",
"name3": "Frank",
"name4": "Alicia"
},
"another_object": {
"string": "here is some text",
"another_string": "Hello World",
"boolean": false,
"nested_object": {
"v3s": [[0.12345, 0.23456, 0.001345],
[0.3894675, 97.39827, 297.92387],
[18.18, 87.289, 2988.298]],
"id": "298728949872"
}
},
"string_array": ["Cat", "Dog", "Elephant", "Tiger"],
"string": "Hello world",
"number": 3.14,
"boolean": true,
"another_bool": false
}
Even with Glaze being the fastest, it is also the cleanest for registration and automatic type deduction. Glaze doesn't require an additional to_json definition.
template <>
struct glz::meta<obj_t> {
using T = obj_t;
static constexpr auto value = object(
"fixed_object", &T::fixed_object,
"fixed_name_object", &T::fixed_name_object,
"another_object", &T::another_object,
"string_array", &T::string_array,
"string", &T::string,
"number", &T::number,
"boolean", &T::boolean,
"another_bool", &T::another_bool
);
};
template<>
struct daw::json::json_data_contract<obj_t> {
using type = json_member_list<
json_class<"fixed_object", fixed_object_t>,
json_class<"fixed_name_object", fixed_name_object_t>,
json_class<"another_object", another_object_t>,
json_array<"string_array", std::string>,
json_string<"string", std::string>,
json_number<"number", double>,
json_bool<"boolean", bool>,
json_bool<"another_bool", bool>>;
static constexpr auto to_json_data(const obj_t& v ) {
return std::forward_as_tuple(v.fixed_object,
v.fixed_name_object,
v.another_object,
v.string_array,
v.string,
v.number,
v.boolean,
v.another_bool);
}
};
void to_json(json& j, const obj_t& v) {
j = json{{"fixed_object", v.fixed_object},
{"fixed_name_object", v.fixed_name_object},
{"another_object", v.another_object},
{"string_array", v.string_array},
{"string", v.string},
{"number", v.number},
{"boolean", v.boolean},
{"another_bool", v.another_bool}};
}
void from_json(const json& j, obj_t& v) {
j.at("fixed_object").get_to(v.fixed_object);
j.at("fixed_name_object").get_to(v.fixed_name_object);
j.at("another_object").get_to(v.another_object);
j.at("string_array").get_to(v.string_array);
j.at("string").get_to(v.string);
j.at("number").get_to(v.number);
j.at("boolean").get_to(v.boolean);
j.at("another_bool").get_to(v.another_bool);
}