From 20ada03a2619fa45ba18b59dc19d0000eca57913 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sun, 2 Jul 2017 17:34:20 +0300 Subject: [PATCH] Bug #86898: Suboptimal String::append() usage in JSON processing Amortize String::append() costs by collecting sequences of characters that don't need escaping in the input string, and appending them to the output string with a single String::append() call. --- sql/json_dom.cc | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/sql/json_dom.cc b/sql/json_dom.cc index 191c27cdc66..edabd0a3b0c 100644 --- a/sql/json_dom.cc +++ b/sql/json_dom.cc @@ -1421,10 +1421,28 @@ bool double_quote(const char *cptr, size_t length, String *buf) if (buf->append('"')) return true; /* purecov: inspected */ - for (size_t i= 0; i < length; i++) + size_t i, last_i; + + for (i= 0, last_i= 0; i < length; i++) { - char esc[2]= {'\\', cptr[i]}; + const unsigned char c= static_cast(cptr[i]); + + /* + We assume that most characters do not need quoting, so append segments of + such characters with memcpy(). + */ + if (c > 0x1f && c != '"' && c != '\\') + continue; + + /* Append previously processed characters that did not need quoting */ + DBUG_ASSERT(i >= last_i); + if (buf->append(cptr + last_i, i - last_i)) + return true; + + last_i= i + 1; + bool done= true; + char esc[2]= {'\\', cptr[i]}; switch (cptr[i]) { case '"' : @@ -1454,9 +1472,10 @@ bool double_quote(const char *cptr, size_t length, String *buf) if (buf->append(esc[0]) || buf->append(esc[1])) return true; /* purecov: inspected */ } - else if (((cptr[i] & ~0x7f) == 0) && // bit 8 not set - (cptr[i] < 0x1f)) + else { + DBUG_ASSERT(((cptr[i] & ~0x7f) == 0) && // bit 8 not set + (cptr[i] < 0x1f)); /* Unprintable control character, use hex a hexadecimal number. The meaning of such a number determined by ISO/IEC 10646. @@ -1466,11 +1485,12 @@ bool double_quote(const char *cptr, size_t length, String *buf) buf->append(_dig_vec_lower[(cptr[i] & 0x0f)])) return true; /* purecov: inspected */ } - else if (buf->append(cptr[i])) - { - return true; /* purecov: inspected */ - } } + + DBUG_ASSERT(i >= last_i); + if (buf->append(cptr + last_i, i - last_i)) + return true; + return buf->append('"'); }