// Tencent is pleased to support the open source community by making RapidJSON available. // // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // // Licensed under the MIT License (the "License"); you may not use this file except // in compliance with the License. You may obtain a copy of the License at // // http://opensource.org/licenses/MIT // // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. #include "perftest.h" #if TEST_RAPIDJSON #include "rapidjson/rapidjson.h" #include "rapidjson/document.h" #include "rapidjson/prettywriter.h" #include "rapidjson/stringbuffer.h" #include "rapidjson/filereadstream.h" #include "rapidjson/encodedstream.h" #include "rapidjson/memorystream.h" #ifdef RAPIDJSON_SSE2 #define SIMD_SUFFIX(name) name##_SSE2 #elif defined(RAPIDJSON_SSE42) #define SIMD_SUFFIX(name) name##_SSE42 #elif defined(RAPIDJSON_NEON) #define SIMD_SUFFIX(name) name##_NEON #else #define SIMD_SUFFIX(name) name #endif using namespace rapidjson; class RapidJson : public PerfTest { public: RapidJson() : temp_(), doc_() {} virtual void SetUp() { PerfTest::SetUp(); // temp buffer for insitu parsing. temp_ = (char *)malloc(length_ + 1); // Parse as a document EXPECT_FALSE(doc_.Parse(json_).HasParseError()); for (size_t i = 0; i < 7; i++) EXPECT_FALSE(typesDoc_[i].Parse(types_[i]).HasParseError()); } virtual void TearDown() { PerfTest::TearDown(); free(temp_); } private: RapidJson(const RapidJson&); RapidJson& operator=(const RapidJson&); protected: char *temp_; Document doc_; Document typesDoc_[7]; }; TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler)) { for (size_t i = 0; i < kTrialCount; i++) { memcpy(temp_, json_, length_ + 1); InsituStringStream s(temp_); BaseReaderHandler<> h; Reader reader; EXPECT_TRUE(reader.Parse(s, h)); } } TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler_ValidateEncoding)) { for (size_t i = 0; i < kTrialCount; i++) { memcpy(temp_, json_, length_ + 1); InsituStringStream s(temp_); BaseReaderHandler<> h; Reader reader; EXPECT_TRUE(reader.Parse(s, h)); } } TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler)) { for (size_t i = 0; i < kTrialCount; i++) { StringStream s(json_); BaseReaderHandler<> h; Reader reader; EXPECT_TRUE(reader.Parse(s, h)); } } #define TEST_TYPED(index, Name)\ TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_##Name)) {\ for (size_t i = 0; i < kTrialCount * 10; i++) {\ StringStream s(types_[index]);\ BaseReaderHandler<> h;\ Reader reader;\ EXPECT_TRUE(reader.Parse(s, h));\ }\ }\ TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler_##Name)) {\ for (size_t i = 0; i < kTrialCount * 10; i++) {\ memcpy(temp_, types_[index], typesLength_[index] + 1);\ InsituStringStream s(temp_);\ BaseReaderHandler<> h;\ Reader reader;\ EXPECT_TRUE(reader.Parse(s, h));\ }\ } TEST_TYPED(0, Booleans) TEST_TYPED(1, Floats) TEST_TYPED(2, Guids) TEST_TYPED(3, Integers) TEST_TYPED(4, Mixed) TEST_TYPED(5, Nulls) TEST_TYPED(6, Paragraphs) #undef TEST_TYPED TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FullPrecision)) { for (size_t i = 0; i < kTrialCount; i++) { StringStream s(json_); BaseReaderHandler<> h; Reader reader; EXPECT_TRUE(reader.Parse(s, h)); } } TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterative_DummyHandler)) { for (size_t i = 0; i < kTrialCount; i++) { StringStream s(json_); BaseReaderHandler<> h; Reader reader; EXPECT_TRUE(reader.Parse(s, h)); } } TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativeInsitu_DummyHandler)) { for (size_t i = 0; i < kTrialCount; i++) { memcpy(temp_, json_, length_ + 1); InsituStringStream s(temp_); BaseReaderHandler<> h; Reader reader; EXPECT_TRUE(reader.Parse(s, h)); } } TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativePull_DummyHandler)) { for (size_t i = 0; i < kTrialCount; i++) { StringStream s(json_); BaseReaderHandler<> h; Reader reader; reader.IterativeParseInit(); while (!reader.IterativeParseComplete()) { if (!reader.IterativeParseNext(s, h)) break; } EXPECT_FALSE(reader.HasParseError()); } } TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativePullInsitu_DummyHandler)) { for (size_t i = 0; i < kTrialCount; i++) { memcpy(temp_, json_, length_ + 1); InsituStringStream s(temp_); BaseReaderHandler<> h; Reader reader; reader.IterativeParseInit(); while (!reader.IterativeParseComplete()) { if (!reader.IterativeParseNext(s, h)) break; } EXPECT_FALSE(reader.HasParseError()); } } TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_ValidateEncoding)) { for (size_t i = 0; i < kTrialCount; i++) { StringStream s(json_); BaseReaderHandler<> h; Reader reader; EXPECT_TRUE(reader.Parse(s, h)); } } TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseInsitu_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(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)) { for (size_t i = 0; i < kTrialCount; i++) { Document doc; doc.Parse(json_); ASSERT_TRUE(doc.IsObject()); } } TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseLength_MemoryPoolAllocator)) { for (size_t i = 0; i < kTrialCount; i++) { Document doc; doc.Parse(json_, length_); ASSERT_TRUE(doc.IsObject()); } } #if RAPIDJSON_HAS_STDSTRING TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseStdString_MemoryPoolAllocator)) { const std::string s(json_, length_); for (size_t i = 0; i < kTrialCount; i++) { Document doc; doc.Parse(s); ASSERT_TRUE(doc.IsObject()); } } #endif 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)) { for (size_t i = 0; i < kTrialCount; i++) { memcpy(temp_, json_, length_ + 1); GenericDocument, CrtAllocator> doc; doc.Parse(temp_); ASSERT_TRUE(doc.IsObject()); } } TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseEncodedInputStream_MemoryStream)) { for (size_t i = 0; i < kTrialCount; i++) { MemoryStream ms(json_, length_); EncodedInputStream, MemoryStream> is(ms); Document doc; doc.ParseStream<0, UTF8<> >(is); ASSERT_TRUE(doc.IsObject()); } } TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseAutoUTFInputStream_MemoryStream)) { for (size_t i = 0; i < kTrialCount; i++) { MemoryStream ms(json_, length_); AutoUTFInputStream is(ms); Document doc; doc.ParseStream<0, AutoUTF >(is); ASSERT_TRUE(doc.IsObject()); } } template size_t Traverse(const T& value) { size_t count = 1; switch(value.GetType()) { case kObjectType: for (typename T::ConstMemberIterator itr = value.MemberBegin(); itr != value.MemberEnd(); ++itr) { count++; // name count += Traverse(itr->value); } break; case kArrayType: for (typename T::ConstValueIterator itr = value.Begin(); itr != value.End(); ++itr) count += Traverse(*itr); break; default: // Do nothing. break; } return count; } TEST_F(RapidJson, DocumentTraverse) { for (size_t i = 0; i < kTrialCount; i++) { size_t count = Traverse(doc_); EXPECT_EQ(4339u, count); //if (i == 0) // std::cout << count << std::endl; } } #ifdef __GNUC__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) #endif struct ValueCounter : public BaseReaderHandler<> { ValueCounter() : count_(1) {} // root bool EndObject(SizeType memberCount) { count_ += memberCount * 2; return true; } bool EndArray(SizeType elementCount) { count_ += elementCount; return true; } SizeType count_; }; #ifdef __GNUC__ RAPIDJSON_DIAG_POP #endif TEST_F(RapidJson, DocumentAccept) { for (size_t i = 0; i < kTrialCount; i++) { ValueCounter counter; doc_.Accept(counter); EXPECT_EQ(4339u, counter.count_); } } struct NullStream { typedef char Ch; NullStream() /*: length_(0)*/ {} void Put(Ch) { /*++length_;*/ } void Flush() {} //size_t length_; }; TEST_F(RapidJson, Writer_NullStream) { for (size_t i = 0; i < kTrialCount; i++) { NullStream s; Writer writer(s); doc_.Accept(writer); //if (i == 0) // std::cout << s.length_ << std::endl; } } TEST_F(RapidJson, SIMD_SUFFIX(Writer_StringBuffer)) { for (size_t i = 0; i < kTrialCount; i++) { StringBuffer s(0, 1024 * 1024); Writer writer(s); doc_.Accept(writer); const char* str = s.GetString(); (void)str; //if (i == 0) // std::cout << strlen(str) << std::endl; } } #define TEST_TYPED(index, Name)\ TEST_F(RapidJson, SIMD_SUFFIX(Writer_StringBuffer_##Name)) {\ for (size_t i = 0; i < kTrialCount * 10; i++) {\ StringBuffer s(0, 1024 * 1024);\ Writer writer(s);\ typesDoc_[index].Accept(writer);\ const char* str = s.GetString();\ (void)str;\ }\ } TEST_TYPED(0, Booleans) TEST_TYPED(1, Floats) TEST_TYPED(2, Guids) TEST_TYPED(3, Integers) TEST_TYPED(4, Mixed) TEST_TYPED(5, Nulls) TEST_TYPED(6, Paragraphs) #undef TEST_TYPED TEST_F(RapidJson, SIMD_SUFFIX(PrettyWriter_StringBuffer)) { for (size_t i = 0; i < kTrialCount; i++) { StringBuffer s(0, 2048 * 1024); PrettyWriter writer(s); writer.SetIndent(' ', 1); doc_.Accept(writer); const char* str = s.GetString(); (void)str; //if (i == 0) // std::cout << strlen(str) << std::endl; } } TEST_F(RapidJson, internal_Pow10) { double sum = 0; for (size_t i = 0; i < kTrialCount * kTrialCount; i++) sum += internal::Pow10(int(i & 255)); EXPECT_GT(sum, 0.0); } TEST_F(RapidJson, SkipWhitespace_Basic) { for (size_t i = 0; i < kTrialCount; i++) { rapidjson::StringStream s(whitespace_); while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') s.Take(); ASSERT_EQ('[', s.Peek()); } } TEST_F(RapidJson, SIMD_SUFFIX(SkipWhitespace)) { for (size_t i = 0; i < kTrialCount; i++) { rapidjson::StringStream s(whitespace_); rapidjson::SkipWhitespace(s); ASSERT_EQ('[', s.Peek()); } } TEST_F(RapidJson, SkipWhitespace_strspn) { for (size_t i = 0; i < kTrialCount; i++) { const char* s = whitespace_ + std::strspn(whitespace_, " \t\r\n"); ASSERT_EQ('[', *s); } } TEST_F(RapidJson, UTF8_Validate) { NullStream os; for (size_t i = 0; i < kTrialCount; i++) { StringStream is(json_); bool result = true; while (is.Peek() != '\0') result &= UTF8<>::Validate(is, os); EXPECT_TRUE(result); } } TEST_F(RapidJson, FileReadStream) { for (size_t i = 0; i < kTrialCount; i++) { FILE *fp = fopen(filename_, "rb"); char buffer[65536]; FileReadStream s(fp, buffer, sizeof(buffer)); while (s.Take() != '\0') ; fclose(fp); } } TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FileReadStream)) { for (size_t i = 0; i < kTrialCount; i++) { FILE *fp = fopen(filename_, "rb"); char buffer[65536]; FileReadStream s(fp, buffer, sizeof(buffer)); BaseReaderHandler<> h; Reader reader; reader.Parse(s, h); fclose(fp); } } TEST_F(RapidJson, StringBuffer) { StringBuffer sb; for (int i = 0; i < 32 * 1024 * 1024; i++) sb.Put(i & 0x7f); } #endif // TEST_RAPIDJSON