From b1441f3485355e774f178cce7e2b645fd3f20943 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 26 Feb 2017 20:58:00 +0100 Subject: [PATCH] :zap: micro-optimizations for dump() Indentation string is recycled to avoid allocations. Comma-separation in objects does not need an if any more. Cachegrind measures 1% performance improvement. --- src/json.hpp | 31 +++++++++++++++++-------------- src/json.hpp.re2c | 31 +++++++++++++++++-------------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 3c41b41aa..3a638d76a 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -8430,34 +8430,36 @@ class basic_json // variable to hold indentation for recursive calls const auto new_indent = current_indent + indent_step; - const std::string indent_string = string_t(new_indent, ' '); + string_t indent_string = string_t(new_indent, ' '); - for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i) + auto i = m_value.object->cbegin(); + for (size_t cnt = 0; cnt < m_value.object->size() - 1; ++cnt, ++i) { - if (i != m_value.object->cbegin()) - { - o << ",\n"; - } o << indent_string << '\"' << escape_string(i->first) << "\": "; i->second.dump(o, true, indent_step, new_indent); + o << ",\n"; } - o << '\n' << string_t(current_indent, ' ') + '}'; + o << indent_string << '\"' << escape_string(i->first) << "\": "; + i->second.dump(o, true, indent_step, new_indent); + + indent_string.resize(current_indent); + o << '\n' << indent_string << '}'; } else { o << '{'; - for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i) + auto i = m_value.object->cbegin(); + for (size_t cnt = 0; cnt < m_value.object->size() - 1; ++cnt, ++i) { - if (i != m_value.object->cbegin()) - { - o << ','; - } o << '\"' << escape_string(i->first) << "\":"; i->second.dump(o, false, indent_step, current_indent); + o << ','; } + o << '\"' << escape_string(i->first) << "\":"; + i->second.dump(o, false, indent_step, current_indent); o << '}'; } @@ -8478,7 +8480,7 @@ class basic_json // variable to hold indentation for recursive calls const auto new_indent = current_indent + indent_step; - const std::string indent_string = string_t(new_indent, ' '); + string_t indent_string = string_t(new_indent, ' '); for (auto i = m_value.array->cbegin(); i != m_value.array->cend() - 1; ++i) { @@ -8491,7 +8493,8 @@ class basic_json assert(not m_value.array->empty()); m_value.array->back().dump(o, true, indent_step, new_indent); - o << '\n' << string_t(current_indent, ' ') << ']'; + indent_string.resize(current_indent); + o << '\n' << indent_string << ']'; } else { diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 6412fe8be..796f8c568 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -8430,34 +8430,36 @@ class basic_json // variable to hold indentation for recursive calls const auto new_indent = current_indent + indent_step; - const std::string indent_string = string_t(new_indent, ' '); + string_t indent_string = string_t(new_indent, ' '); - for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i) + auto i = m_value.object->cbegin(); + for (size_t cnt = 0; cnt < m_value.object->size() - 1; ++cnt, ++i) { - if (i != m_value.object->cbegin()) - { - o << ",\n"; - } o << indent_string << '\"' << escape_string(i->first) << "\": "; i->second.dump(o, true, indent_step, new_indent); + o << ",\n"; } - o << '\n' << string_t(current_indent, ' ') + '}'; + o << indent_string << '\"' << escape_string(i->first) << "\": "; + i->second.dump(o, true, indent_step, new_indent); + + indent_string.resize(current_indent); + o << '\n' << indent_string << '}'; } else { o << '{'; - for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i) + auto i = m_value.object->cbegin(); + for (size_t cnt = 0; cnt < m_value.object->size() - 1; ++cnt, ++i) { - if (i != m_value.object->cbegin()) - { - o << ','; - } o << '\"' << escape_string(i->first) << "\":"; i->second.dump(o, false, indent_step, current_indent); + o << ','; } + o << '\"' << escape_string(i->first) << "\":"; + i->second.dump(o, false, indent_step, current_indent); o << '}'; } @@ -8478,7 +8480,7 @@ class basic_json // variable to hold indentation for recursive calls const auto new_indent = current_indent + indent_step; - const std::string indent_string = string_t(new_indent, ' '); + string_t indent_string = string_t(new_indent, ' '); for (auto i = m_value.array->cbegin(); i != m_value.array->cend() - 1; ++i) { @@ -8491,7 +8493,8 @@ class basic_json assert(not m_value.array->empty()); m_value.array->back().dump(o, true, indent_step, new_indent); - o << '\n' << string_t(current_indent, ' ') << ']'; + indent_string.resize(current_indent); + o << '\n' << indent_string << ']'; } else {