mirror of
https://github.com/nlohmann/json.git
synced 2026-10-22 14:08:13 +00:00
Reuse one value for the key events of the callback parser
parse() with a callback built a new string value for every key it passed to the callback (a heap allocation and release per key), and copied the key a second time into the object. The callback parser now keeps one string value for key events, which it assigns, and moves the key into the object. Callback parse, Linux Ir (GCC / Clang): twitter -13.3 % / -11.7 %, citm -9.5 % / -7.6 %. (Earlier macOS measurement: twitter -19.5 % instructions.) Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
2 files changed
+60
-12
No files matched your search
Generated
+30
-6
@@ -15933,16 +15933,13 @@ class json_sax_dom_callback_parser
|
||||
// handle_value() without touching the key stacks
|
||||
if (keep_stack.back())
|
||||
{
|
||||
BasicJsonType k = BasicJsonType(val);
|
||||
static_cast<void>(callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k));
|
||||
static_cast<void>(callback(static_cast<int>(ref_stack.size()), parse_event_t::key, key_value(val)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
BasicJsonType k = BasicJsonType(val);
|
||||
|
||||
// check callback for the key
|
||||
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
|
||||
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, key_value(val));
|
||||
key_keep_stack.push_back(keep);
|
||||
// remember the key so a rejected value can be erased without searching
|
||||
// the object for it (kept in lockstep with key_keep_stack)
|
||||
@@ -15953,7 +15950,7 @@ class json_sax_dom_callback_parser
|
||||
{
|
||||
auto& obj = *ref_stack.back()->m_data.m_value.object;
|
||||
// a single lookup: insert the placeholder, or find the existing member
|
||||
const auto inserted = obj.emplace(val, discarded);
|
||||
const auto inserted = obj.emplace(std::move(val), discarded);
|
||||
const auto it = inserted.first;
|
||||
if (!inserted.second)
|
||||
{
|
||||
@@ -16127,6 +16124,31 @@ class json_sax_dom_callback_parser
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
@brief the value of a key event for the callback
|
||||
|
||||
A string value of its own for every key would allocate it every time, so
|
||||
one is kept and set to the key. A callback that changed or moved it gets a
|
||||
new one, as it would have got a new value for every key anyway.
|
||||
*/
|
||||
BasicJsonType& key_value(const string_t& key)
|
||||
{
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
// a callback may have left positions on the value
|
||||
key_scratch = BasicJsonType(key);
|
||||
#else
|
||||
if (JSON_HEDLEY_LIKELY(key_scratch.is_string()))
|
||||
{
|
||||
*key_scratch.m_data.m_value.string = key;
|
||||
}
|
||||
else
|
||||
{
|
||||
key_scratch = BasicJsonType(key);
|
||||
}
|
||||
#endif
|
||||
return key_scratch;
|
||||
}
|
||||
|
||||
/// if there is a pending duplicate-key stash entry for this exact slot,
|
||||
/// remove it from the stash; if restore_value is true, the stashed
|
||||
/// previous value is moved back into the slot first (use this when the
|
||||
@@ -16374,6 +16396,8 @@ class json_sax_dom_callback_parser
|
||||
const bool allow_exceptions = true;
|
||||
/// a discarded value for the callback
|
||||
BasicJsonType discarded = BasicJsonType::value_t::discarded;
|
||||
/// the value of the key event for the callback (see key_value())
|
||||
BasicJsonType key_scratch {};
|
||||
/// the lexer reference to obtain the current position
|
||||
lexer_t* m_lexer_ref = nullptr;
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user