Reserve room for two elements in the arrays unflatten() creates

An array that unflatten() creates grows by one element at a time, so an
array of two elements (a coordinate pair, a range) was allocated, grown and
freed once more than needed. New arrays get room for two elements first,
for array types that have reserve(). Arrays of two or more elements need no
more memory than before; an array of one element has room for one more.

unflatten() (instructions on macOS, Linux Ir GCC 13 / Clang 18): canada 161.9M ->
141.2M, 128.3M -> 117.9M / 138.0M -> 128.6M; citm_catalog 43.5M -> 42.8M, 37.0M
-> 36.8M / 37.5M -> 37.3M; twitter unchanged.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-22 09:30:01 +02:00
1 parent a89d3d2738
commit 42bd27824e
2 files changed
+28

No files matched your search

+14
View File
@@ -481,6 +481,18 @@ class json_pointer
return pos == size;
}
/// reserve room for @a n elements of an array type that has reserve()
template<typename ArrayType>
static auto reserve_elements(ArrayType& array, const std::size_t n, detail::priority_tag<1> /*unused*/)
-> decltype(array.reserve(n), void())
{
array.reserve(n);
}
template<typename ArrayType>
static void reserve_elements(ArrayType& /*array*/, const std::size_t /*n*/, detail::priority_tag<0> /*unused*/)
{}
/// @brief object member access with a key that is only copied if it is inserted
///
/// Objects that can find the position of a key and insert there
@@ -1717,6 +1729,8 @@ class json_pointer
{
// some reference token below this position is 0, so the
// value is an array
*current = BasicJsonType(detail::value_t::array);
reserve_elements(*current->m_data.m_value.array, 2, detail::priority_tag<1> {});
current = &current->operator[](array_index<BasicJsonType>(token));
}
else
+14
View File
@@ -22831,6 +22831,18 @@ class json_pointer
return pos == size;
}
/// reserve room for @a n elements of an array type that has reserve()
template<typename ArrayType>
static auto reserve_elements(ArrayType& array, const std::size_t n, detail::priority_tag<1> /*unused*/)
-> decltype(array.reserve(n), void())
{
array.reserve(n);
}
template<typename ArrayType>
static void reserve_elements(ArrayType& /*array*/, const std::size_t /*n*/, detail::priority_tag<0> /*unused*/)
{}
/// @brief object member access with a key that is only copied if it is inserted
///
/// Objects that can find the position of a key and insert there
@@ -24067,6 +24079,8 @@ class json_pointer
{
// some reference token below this position is 0, so the
// value is an array
*current = BasicJsonType(detail::value_t::array);
reserve_elements(*current->m_data.m_value.array, 2, detail::priority_tag<1> {});
current = &current->operator[](array_index<BasicJsonType>(token));
}
else