diff --git a/include/rapidjson/document.h b/include/rapidjson/document.h index d94cd623..4448600b 100644 --- a/include/rapidjson/document.h +++ b/include/rapidjson/document.h @@ -1221,13 +1221,12 @@ public: \tparam SourceEncoding Encoding of input stream \tparam InputStream Type of input stream, implementing Stream concept \param is Input stream to be parsed. - \param limit Parsing stack size limit(in bytes). Pass 0 means no limit. \return The document itself for fluent API. */ template - GenericDocument& ParseStream(InputStream& is, size_t limit = 0) { + GenericDocument& ParseStream(InputStream& is) { ValueType::SetNull(); // Remove existing root if exist - GenericReader reader(limit, &GetAllocator()); + GenericReader reader(&GetAllocator()); ClearStackOnExit scope(*this); parseResult_ = reader.template Parse(is, *this); if (parseResult_) { @@ -1241,23 +1240,21 @@ public: /*! \tparam parseFlags Combination of \ref ParseFlag. \tparam InputStream Type of input stream, implementing Stream concept \param is Input stream to be parsed. - \param limit Parsing stack size limit(in bytes). Pass 0 means no limit. \return The document itself for fluent API. */ template - GenericDocument& ParseStream(InputStream& is, size_t limit = 0) { - return ParseStream(is, limit); + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); } //! Parse JSON text from an input stream (with \ref kParseDefaultFlags) /*! \tparam InputStream Type of input stream, implementing Stream concept \param is Input stream to be parsed. - \param limit Parsing stack size limit(in bytes). Pass 0 means no limit. \return The document itself for fluent API. */ template - GenericDocument& ParseStream(InputStream& is, size_t limit = 0) { - return ParseStream(is, limit); + GenericDocument& ParseStream(InputStream& is) { + return ParseStream(is); } //!@} @@ -1268,33 +1265,30 @@ public: /*! \tparam parseFlags Combination of \ref ParseFlag. \tparam SourceEncoding Transcoding from input Encoding \param str Mutable zero-terminated string to be parsed. - \param limit Parsing stack size limit(in bytes). Pass 0 means no limit. \return The document itself for fluent API. */ template - GenericDocument& ParseInsitu(Ch* str, size_t limit = 0) { + GenericDocument& ParseInsitu(Ch* str) { GenericInsituStringStream s(str); - return ParseStream(s, limit); + return ParseStream(s); } //! Parse JSON text from a mutable string /*! \tparam parseFlags Combination of \ref ParseFlag. \param str Mutable zero-terminated string to be parsed. - \param limit Parsing stack size limit(in bytes). Pass 0 means no limit. \return The document itself for fluent API. */ template - GenericDocument& ParseInsitu(Ch* str, size_t limit = 0) { - return ParseInsitu(str, limit); + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu(str); } //! Parse JSON text from a mutable string (with \ref kParseDefaultFlags) /*! \param str Mutable zero-terminated string to be parsed. - \param limit Parsing stack size limit(in bytes). Pass 0 means no limit. \return The document itself for fluent API. */ - GenericDocument& ParseInsitu(Ch* str, size_t limit = 0) { - return ParseInsitu(str, limit); + GenericDocument& ParseInsitu(Ch* str) { + return ParseInsitu(str); } //!@} @@ -1305,31 +1299,28 @@ public: /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). \tparam SourceEncoding Transcoding from input Encoding \param str Read-only zero-terminated string to be parsed. - \param limit Parsing stack size limit(in bytes). Pass 0 means no limit. */ template - GenericDocument& Parse(const Ch* str, size_t limit = 0) { + GenericDocument& Parse(const Ch* str) { RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag)); GenericStringStream s(str); - return ParseStream(s, limit); + return ParseStream(s); } //! Parse JSON text from a read-only string /*! \tparam parseFlags Combination of \ref ParseFlag (must not contain \ref kParseInsituFlag). \param str Read-only zero-terminated string to be parsed. - \param limit Parsing stack size limit(in bytes). Pass 0 means no limit. */ template - GenericDocument& Parse(const Ch* str, size_t limit = 0) { - return Parse(str, limit); + GenericDocument& Parse(const Ch* str) { + return Parse(str); } //! Parse JSON text from a read-only string (with \ref kParseDefaultFlags) /*! \param str Read-only zero-terminated string to be parsed. - \param limit Parsing stack size limit(in bytes). Pass 0 means no limit. */ - GenericDocument& Parse(const Ch* str, size_t limit = 0) { - return Parse(str, limit); + GenericDocument& Parse(const Ch* str) { + return Parse(str); } //!@} diff --git a/include/rapidjson/error/en.h b/include/rapidjson/error/en.h index e9a5d1d3..e9120c5b 100644 --- a/include/rapidjson/error/en.h +++ b/include/rapidjson/error/en.h @@ -40,7 +40,6 @@ inline const RAPIDJSON_ERROR_CHARTYPE* GetParseError_En(ParseErrorCode parseErro case kParseErrorTermination: return RAPIDJSON_ERROR_STRING("Terminate parsing due to Handler error."); case kParseErrorUnspecificSyntaxError: return RAPIDJSON_ERROR_STRING("Unspecific syntax error."); - case kParseErrorStackSizeLimitExceeded: return RAPIDJSON_ERROR_STRING("Parsing stack size limit is exceeded."); default: return RAPIDJSON_ERROR_STRING("Unknown error."); diff --git a/include/rapidjson/error/error.h b/include/rapidjson/error/error.h index a47dfaaf..981cbd92 100644 --- a/include/rapidjson/error/error.h +++ b/include/rapidjson/error/error.h @@ -60,7 +60,6 @@ enum ParseErrorCode { kParseErrorTermination, //!< Parsing was terminated. kParseErrorUnspecificSyntaxError, //!< Unspecific syntax error. - kParseErrorStackSizeLimitExceeded //!< Parsing stack size limit is exceeded. }; //! Result of parsing (wraps ParseErrorCode) diff --git a/include/rapidjson/internal/stack.h b/include/rapidjson/internal/stack.h index ff5ff82a..85484655 100644 --- a/include/rapidjson/internal/stack.h +++ b/include/rapidjson/internal/stack.h @@ -28,20 +28,14 @@ public: void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; } + // Optimization note: try to minimize the size of this function for force inline. + // Expansion is run very infrequently, so it is moved to another (probably non-inline) function. template - T* Push(size_t count = 1) { + RAPIDJSON_FORCEINLINE T* Push(size_t count = 1) { // Expand the stack if needed - if (stack_top_ + sizeof(T) * count >= stack_end_) { - size_t new_capacity = stack_capacity_ * 2; - size_t size = GetSize(); - size_t new_size = GetSize() + sizeof(T) * count; - if (new_capacity < new_size) - new_capacity = new_size; - stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity); - stack_capacity_ = new_capacity; - stack_top_ = stack_ + size; - stack_end_ = stack_ + stack_capacity_; - } + if (stack_top_ + sizeof(T) * count >= stack_end_) + Expand(count); + T* ret = reinterpret_cast(stack_top_); stack_top_ += sizeof(T) * count; return ret; @@ -69,6 +63,19 @@ public: size_t GetCapacity() const { return stack_capacity_; } private: + template + void Expand(size_t count) { + size_t new_capacity = stack_capacity_ * 2; + size_t size = GetSize(); + size_t new_size = GetSize() + sizeof(T) * count; + if (new_capacity < new_size) + new_capacity = new_size; + stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity); + stack_capacity_ = new_capacity; + stack_top_ = stack_ + size; + stack_end_ = stack_ + stack_capacity_; + } + // Prohibit copy constructor & assignment operator. Stack(const Stack&); Stack& operator=(const Stack&); diff --git a/include/rapidjson/rapidjson.h b/include/rapidjson/rapidjson.h index 903dee15..562b4947 100644 --- a/include/rapidjson/rapidjson.h +++ b/include/rapidjson/rapidjson.h @@ -41,6 +41,8 @@ #ifndef RAPIDJSON_FORCEINLINE #ifdef _MSC_VER #define RAPIDJSON_FORCEINLINE __forceinline +#elif defined(__GNUC__) && __GNUC__ >= 4 +#define RAPIDJSON_FORCEINLINE __attribute__((always_inline)) #else #define RAPIDJSON_FORCEINLINE #endif diff --git a/test/perftest/rapidjsontest.cpp b/test/perftest/rapidjsontest.cpp index 0b52e8a8..b2427175 100644 --- a/test/perftest/rapidjsontest.cpp +++ b/test/perftest/rapidjsontest.cpp @@ -104,48 +104,37 @@ TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_ValidateEncoding)) { } TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseInsitu_MemoryPoolAllocator)) { - //const size_t userBufferSize = 128 * 1024; - //char* userBuffer = (char*)malloc(userBufferSize); - for (size_t i = 0; i < kTrialCount; i++) { memcpy(temp_, json_, length_ + 1); - //MemoryPoolAllocator<> allocator(userBuffer, userBufferSize); - //Document doc(&allocator); Document doc; doc.ParseInsitu(temp_); ASSERT_TRUE(doc.IsObject()); - //if (i == 0) { - // size_t size = doc.GetAllocator().Size(); - // size_t capacity = doc.GetAllocator().Capacity(); - // size_t stack_capacity = doc.GetStackCapacity(); - // size_t actual = size - stack_capacity; - // std::cout << "Size:" << size << " Capacity:" << capacity << " Stack:" << stack_capacity << " Actual:" << actual << std::endl; - //} } +} - //free(userBuffer); +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterativeInsitu_MemoryPoolAllocator)) { + for (size_t i = 0; i < kTrialCount; i++) { + memcpy(temp_, json_, length_ + 1); + Document doc; + doc.ParseInsitu(temp_); + ASSERT_TRUE(doc.IsObject()); + } } TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_MemoryPoolAllocator)) { - //const size_t userBufferSize = 128 * 1024; - //char* userBuffer = (char*)malloc(userBufferSize); - for (size_t i = 0; i < kTrialCount; i++) { - //MemoryPoolAllocator<> allocator(userBuffer, userBufferSize); - //Document doc(&allocator); Document doc; doc.Parse(json_); ASSERT_TRUE(doc.IsObject()); - //if (i == 0) { - // size_t size = doc.GetAllocator().Size(); - // size_t capacity = doc.GetAllocator().Capacity(); - // size_t stack_capacity = doc.GetStackCapacity(); - // size_t actual = size - stack_capacity; - // std::cout << "Size:" << size << " Capacity:" << capacity << " Stack:" << stack_capacity << " Actual:" << actual << std::endl; - //} } +} - //free(userBuffer); +TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterative_MemoryPoolAllocator)) { + for (size_t i = 0; i < kTrialCount; i++) { + Document doc; + doc.Parse(json_); + ASSERT_TRUE(doc.IsObject()); + } } TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_CrtAllocator)) {