1 // Tencent is pleased to support the open source community by making RapidJSON available. 2 // 3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 // 5 // Licensed under the MIT License (the "License"); you may not use this file except 6 // in compliance with the License. You may obtain a copy of the License at 7 // 8 // http://opensource.org/licenses/MIT 9 // 10 // Unless required by applicable law or agreed to in writing, software distributed 11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 // specific language governing permissions and limitations under the License. 14 15 #include "perftest.h" 16 17 #if TEST_RAPIDJSON 18 19 #include "rapidjson/rapidjson.h" 20 #include "rapidjson/document.h" 21 #include "rapidjson/prettywriter.h" 22 #include "rapidjson/stringbuffer.h" 23 #include "rapidjson/filereadstream.h" 24 #include "rapidjson/encodedstream.h" 25 #include "rapidjson/memorystream.h" 26 27 #ifdef RAPIDJSON_SSE2 28 #define SIMD_SUFFIX(name) name##_SSE2 29 #elif defined(RAPIDJSON_SSE42) 30 #define SIMD_SUFFIX(name) name##_SSE42 31 #else 32 #define SIMD_SUFFIX(name) name 33 #endif 34 35 using namespace rapidjson; 36 37 class RapidJson : public PerfTest { 38 public: 39 RapidJson() : temp_(), doc_() {} 40 41 virtual void SetUp() { 42 PerfTest::SetUp(); 43 44 // temp buffer for insitu parsing. 45 temp_ = (char *)malloc(length_ + 1); 46 47 // Parse as a document 48 EXPECT_FALSE(doc_.Parse(json_).IsNull()); 49 } 50 51 virtual void TearDown() { 52 PerfTest::TearDown(); 53 free(temp_); 54 } 55 56 private: 57 RapidJson(const RapidJson&); 58 RapidJson& operator=(const RapidJson&); 59 60 protected: 61 char *temp_; 62 Document doc_; 63 }; 64 65 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler)) { 66 for (size_t i = 0; i < kTrialCount; i++) { 67 memcpy(temp_, json_, length_ + 1); 68 InsituStringStream s(temp_); 69 BaseReaderHandler<> h; 70 Reader reader; 71 EXPECT_TRUE(reader.Parse<kParseInsituFlag>(s, h)); 72 } 73 } 74 75 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler_ValidateEncoding)) { 76 for (size_t i = 0; i < kTrialCount; i++) { 77 memcpy(temp_, json_, length_ + 1); 78 InsituStringStream s(temp_); 79 BaseReaderHandler<> h; 80 Reader reader; 81 EXPECT_TRUE(reader.Parse<kParseInsituFlag | kParseValidateEncodingFlag>(s, h)); 82 } 83 } 84 85 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler)) { 86 for (size_t i = 0; i < kTrialCount; i++) { 87 StringStream s(json_); 88 BaseReaderHandler<> h; 89 Reader reader; 90 EXPECT_TRUE(reader.Parse(s, h)); 91 } 92 } 93 94 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FullPrecision)) { 95 for (size_t i = 0; i < kTrialCount; i++) { 96 StringStream s(json_); 97 BaseReaderHandler<> h; 98 Reader reader; 99 EXPECT_TRUE(reader.Parse<kParseFullPrecisionFlag>(s, h)); 100 } 101 } 102 103 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterative_DummyHandler)) { 104 for (size_t i = 0; i < kTrialCount; i++) { 105 StringStream s(json_); 106 BaseReaderHandler<> h; 107 Reader reader; 108 EXPECT_TRUE(reader.Parse<kParseIterativeFlag>(s, h)); 109 } 110 } 111 112 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativeInsitu_DummyHandler)) { 113 for (size_t i = 0; i < kTrialCount; i++) { 114 memcpy(temp_, json_, length_ + 1); 115 InsituStringStream s(temp_); 116 BaseReaderHandler<> h; 117 Reader reader; 118 EXPECT_TRUE(reader.Parse<kParseIterativeFlag|kParseInsituFlag>(s, h)); 119 } 120 } 121 122 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_ValidateEncoding)) { 123 for (size_t i = 0; i < kTrialCount; i++) { 124 StringStream s(json_); 125 BaseReaderHandler<> h; 126 Reader reader; 127 EXPECT_TRUE(reader.Parse<kParseValidateEncodingFlag>(s, h)); 128 } 129 } 130 131 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseInsitu_MemoryPoolAllocator)) { 132 for (size_t i = 0; i < kTrialCount; i++) { 133 memcpy(temp_, json_, length_ + 1); 134 Document doc; 135 doc.ParseInsitu(temp_); 136 ASSERT_TRUE(doc.IsObject()); 137 } 138 } 139 140 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterativeInsitu_MemoryPoolAllocator)) { 141 for (size_t i = 0; i < kTrialCount; i++) { 142 memcpy(temp_, json_, length_ + 1); 143 Document doc; 144 doc.ParseInsitu<kParseIterativeFlag>(temp_); 145 ASSERT_TRUE(doc.IsObject()); 146 } 147 } 148 149 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_MemoryPoolAllocator)) { 150 for (size_t i = 0; i < kTrialCount; i++) { 151 Document doc; 152 doc.Parse(json_); 153 ASSERT_TRUE(doc.IsObject()); 154 } 155 } 156 157 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterative_MemoryPoolAllocator)) { 158 for (size_t i = 0; i < kTrialCount; i++) { 159 Document doc; 160 doc.Parse<kParseIterativeFlag>(json_); 161 ASSERT_TRUE(doc.IsObject()); 162 } 163 } 164 165 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_CrtAllocator)) { 166 for (size_t i = 0; i < kTrialCount; i++) { 167 memcpy(temp_, json_, length_ + 1); 168 GenericDocument<UTF8<>, CrtAllocator> doc; 169 doc.Parse(temp_); 170 ASSERT_TRUE(doc.IsObject()); 171 } 172 } 173 174 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseEncodedInputStream_MemoryStream)) { 175 for (size_t i = 0; i < kTrialCount; i++) { 176 MemoryStream ms(json_, length_); 177 EncodedInputStream<UTF8<>, MemoryStream> is(ms); 178 Document doc; 179 doc.ParseStream<0, UTF8<> >(is); 180 ASSERT_TRUE(doc.IsObject()); 181 } 182 } 183 184 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseAutoUTFInputStream_MemoryStream)) { 185 for (size_t i = 0; i < kTrialCount; i++) { 186 MemoryStream ms(json_, length_); 187 AutoUTFInputStream<unsigned, MemoryStream> is(ms); 188 Document doc; 189 doc.ParseStream<0, AutoUTF<unsigned> >(is); 190 ASSERT_TRUE(doc.IsObject()); 191 } 192 } 193 194 template<typename T> 195 size_t Traverse(const T& value) { 196 size_t count = 1; 197 switch(value.GetType()) { 198 case kObjectType: 199 for (typename T::ConstMemberIterator itr = value.MemberBegin(); itr != value.MemberEnd(); ++itr) { 200 count++; // name 201 count += Traverse(itr->value); 202 } 203 break; 204 205 case kArrayType: 206 for (typename T::ConstValueIterator itr = value.Begin(); itr != value.End(); ++itr) 207 count += Traverse(*itr); 208 break; 209 210 default: 211 // Do nothing. 212 break; 213 } 214 return count; 215 } 216 217 TEST_F(RapidJson, DocumentTraverse) { 218 for (size_t i = 0; i < kTrialCount; i++) { 219 size_t count = Traverse(doc_); 220 EXPECT_EQ(4339u, count); 221 //if (i == 0) 222 // std::cout << count << std::endl; 223 } 224 } 225 226 #ifdef __GNUC__ 227 RAPIDJSON_DIAG_PUSH 228 RAPIDJSON_DIAG_OFF(effc++) 229 #endif 230 231 struct ValueCounter : public BaseReaderHandler<> { 232 ValueCounter() : count_(1) {} // root 233 234 bool EndObject(SizeType memberCount) { count_ += memberCount * 2; return true; } 235 bool EndArray(SizeType elementCount) { count_ += elementCount; return true; } 236 237 SizeType count_; 238 }; 239 240 #ifdef __GNUC__ 241 RAPIDJSON_DIAG_POP 242 #endif 243 244 TEST_F(RapidJson, DocumentAccept) { 245 for (size_t i = 0; i < kTrialCount; i++) { 246 ValueCounter counter; 247 doc_.Accept(counter); 248 EXPECT_EQ(4339u, counter.count_); 249 } 250 } 251 252 struct NullStream { 253 NullStream() /*: length_(0)*/ {} 254 void Put(char) { /*++length_;*/ } 255 void Flush() {} 256 //size_t length_; 257 }; 258 259 TEST_F(RapidJson, Writer_NullStream) { 260 for (size_t i = 0; i < kTrialCount; i++) { 261 NullStream s; 262 Writer<NullStream> writer(s); 263 doc_.Accept(writer); 264 //if (i == 0) 265 // std::cout << s.length_ << std::endl; 266 } 267 } 268 269 TEST_F(RapidJson, Writer_StringBuffer) { 270 for (size_t i = 0; i < kTrialCount; i++) { 271 StringBuffer s(0, 1024 * 1024); 272 Writer<StringBuffer> writer(s); 273 doc_.Accept(writer); 274 const char* str = s.GetString(); 275 (void)str; 276 //if (i == 0) 277 // std::cout << strlen(str) << std::endl; 278 } 279 } 280 281 TEST_F(RapidJson, PrettyWriter_StringBuffer) { 282 for (size_t i = 0; i < kTrialCount; i++) { 283 StringBuffer s(0, 2048 * 1024); 284 PrettyWriter<StringBuffer> writer(s); 285 writer.SetIndent(' ', 1); 286 doc_.Accept(writer); 287 const char* str = s.GetString(); 288 (void)str; 289 //if (i == 0) 290 // std::cout << strlen(str) << std::endl; 291 } 292 } 293 294 TEST_F(RapidJson, internal_Pow10) { 295 double sum = 0; 296 for (size_t i = 0; i < kTrialCount * kTrialCount; i++) 297 sum += internal::Pow10(int(i & 255)); 298 EXPECT_GT(sum, 0.0); 299 } 300 301 TEST_F(RapidJson, SkipWhitespace_Basic) { 302 for (size_t i = 0; i < kTrialCount; i++) { 303 rapidjson::StringStream s(whitespace_); 304 while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t') 305 s.Take(); 306 ASSERT_EQ('[', s.Peek()); 307 } 308 } 309 310 TEST_F(RapidJson, SIMD_SUFFIX(SkipWhitespace)) { 311 for (size_t i = 0; i < kTrialCount; i++) { 312 rapidjson::StringStream s(whitespace_); 313 rapidjson::SkipWhitespace(s); 314 ASSERT_EQ('[', s.Peek()); 315 } 316 } 317 318 TEST_F(RapidJson, SkipWhitespace_strspn) { 319 for (size_t i = 0; i < kTrialCount; i++) { 320 const char* s = whitespace_ + std::strspn(whitespace_, " \t\r\n"); 321 ASSERT_EQ('[', *s); 322 } 323 } 324 325 TEST_F(RapidJson, UTF8_Validate) { 326 NullStream os; 327 328 for (size_t i = 0; i < kTrialCount; i++) { 329 StringStream is(json_); 330 bool result = true; 331 while (is.Peek() != '\0') 332 result &= UTF8<>::Validate(is, os); 333 EXPECT_TRUE(result); 334 } 335 } 336 337 TEST_F(RapidJson, FileReadStream) { 338 for (size_t i = 0; i < kTrialCount; i++) { 339 FILE *fp = fopen(filename_, "rb"); 340 char buffer[65536]; 341 FileReadStream s(fp, buffer, sizeof(buffer)); 342 while (s.Take() != '\0') 343 ; 344 fclose(fp); 345 } 346 } 347 348 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FileReadStream)) { 349 for (size_t i = 0; i < kTrialCount; i++) { 350 FILE *fp = fopen(filename_, "rb"); 351 char buffer[65536]; 352 FileReadStream s(fp, buffer, sizeof(buffer)); 353 BaseReaderHandler<> h; 354 Reader reader; 355 reader.Parse(s, h); 356 fclose(fp); 357 } 358 } 359 360 #endif // TEST_RAPIDJSON 361