mirror of
https://github.com/nlohmann/json.git
synced 2026-11-08 05:23:38 +00:00
Iterator: test for objects before arrays
#5835 replaced the switch on the value type in operator*, operator->, operator++, operator-- and operator== of iter_impl with an if chain that tests for an array first. Every step over an object then pays for a failed test and a taken branch: with the iterator inlined, walking twitter.json took 14% more cycles than with 3.12.0, and citm_catalog.json 3.5% more. Test for objects first. Walking every value of the three files now takes fewer cycles than with 3.12.0 (Apple M1 Max, Apple clang 21): citm_catalog.json 1.21x, twitter.json 1.04x, canada.json 1.17x as fast. canada.json, which holds only arrays, gives back part of the gain of #5835 (develop: 1.62x); the other orders tried (arrays first without hints, objects first without hints, a switch) each left one of the files slower than 3.12.0. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
2 files changed
+66
-58
No files matched your search
@@ -277,18 +277,22 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
{
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::array))
|
||||
{
|
||||
JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
|
||||
return *m_it.array_iterator;
|
||||
}
|
||||
|
||||
// objects are tested before arrays here and in the other operators:
|
||||
// with arrays first, walking a document of objects such as
|
||||
// twitter.json took 14% more cycles than with 3.12.0's switch; with
|
||||
// objects first, no document walks slower than with 3.12.0
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::object))
|
||||
{
|
||||
JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
|
||||
return m_it.object_iterator->second;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::array))
|
||||
{
|
||||
JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
|
||||
return *m_it.array_iterator;
|
||||
}
|
||||
|
||||
// neither array nor object: a primitive value (null has no value to point to)
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type != value_t::null && m_it.primitive_iterator.is_begin()))
|
||||
{
|
||||
@@ -306,18 +310,18 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
{
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::array))
|
||||
{
|
||||
JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
|
||||
return &*m_it.array_iterator;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::object))
|
||||
{
|
||||
JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
|
||||
return &(m_it.object_iterator->second);
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::array))
|
||||
{
|
||||
JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
|
||||
return &*m_it.array_iterator;
|
||||
}
|
||||
|
||||
// neither array nor object: a primitive value
|
||||
if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
|
||||
{
|
||||
@@ -346,18 +350,18 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
{
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::array))
|
||||
{
|
||||
++m_it.array_iterator;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::object))
|
||||
{
|
||||
std::advance(m_it.object_iterator, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::array))
|
||||
{
|
||||
++m_it.array_iterator;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// neither array nor object: a primitive value
|
||||
++m_it.primitive_iterator;
|
||||
return *this;
|
||||
@@ -382,18 +386,18 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
{
|
||||
JSON_ASSERT(m_object != nullptr);
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::array))
|
||||
{
|
||||
--m_it.array_iterator;
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::object))
|
||||
{
|
||||
std::advance(m_it.object_iterator, -1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::array))
|
||||
{
|
||||
--m_it.array_iterator;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// neither array nor object: a primitive value
|
||||
--m_it.primitive_iterator;
|
||||
return *this;
|
||||
@@ -415,16 +419,16 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
||||
return true;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::array))
|
||||
{
|
||||
return (m_it.array_iterator == other.m_it.array_iterator);
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::object))
|
||||
{
|
||||
return (m_it.object_iterator == other.m_it.object_iterator);
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_LIKELY(m_object->m_data.m_type == value_t::array))
|
||||
{
|
||||
return (m_it.array_iterator == other.m_it.array_iterator);
|
||||
}
|
||||
|
||||
// neither array nor object: a primitive value
|
||||
return (m_it.primitive_iterator == other.m_it.primitive_iterator);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user