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 #elif defined(RAPIDJSON_NEON)
32 #define SIMD_SUFFIX(name) name##_NEON
33 #else
34 #define SIMD_SUFFIX(name) name
35 #endif
36
37 using namespace rapidjson;
38
39 class RapidJson : public PerfTest {
40 public:
RapidJson()41 RapidJson() : temp_(), doc_() {}
42
SetUp()43 virtual void SetUp() {
44 PerfTest::SetUp();
45
46 // temp buffer for insitu parsing.
47 temp_ = (char *)malloc(length_ + 1);
48
49 // Parse as a document
50 EXPECT_FALSE(doc_.Parse(json_).HasParseError());
51
52 for (size_t i = 0; i < 7; i++)
53 EXPECT_FALSE(typesDoc_[i].Parse(types_[i]).HasParseError());
54 }
55
TearDown()56 virtual void TearDown() {
57 PerfTest::TearDown();
58 free(temp_);
59 }
60
61 private:
62 RapidJson(const RapidJson&);
63 RapidJson& operator=(const RapidJson&);
64
65 protected:
66 char *temp_;
67 Document doc_;
68 Document typesDoc_[7];
69 };
70
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParseInsitu_DummyHandler))71 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler)) {
72 for (size_t i = 0; i < kTrialCount; i++) {
73 memcpy(temp_, json_, length_ + 1);
74 InsituStringStream s(temp_);
75 BaseReaderHandler<> h;
76 Reader reader;
77 EXPECT_TRUE(reader.Parse<kParseInsituFlag>(s, h));
78 }
79 }
80
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParseInsitu_DummyHandler_ValidateEncoding))81 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler_ValidateEncoding)) {
82 for (size_t i = 0; i < kTrialCount; i++) {
83 memcpy(temp_, json_, length_ + 1);
84 InsituStringStream s(temp_);
85 BaseReaderHandler<> h;
86 Reader reader;
87 EXPECT_TRUE(reader.Parse<kParseInsituFlag | kParseValidateEncodingFlag>(s, h));
88 }
89 }
90
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParse_DummyHandler))91 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler)) {
92 for (size_t i = 0; i < kTrialCount; i++) {
93 StringStream s(json_);
94 BaseReaderHandler<> h;
95 Reader reader;
96 EXPECT_TRUE(reader.Parse(s, h));
97 }
98 }
99
100 #define TEST_TYPED(index, Name)\
101 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_##Name)) {\
102 for (size_t i = 0; i < kTrialCount * 10; i++) {\
103 StringStream s(types_[index]);\
104 BaseReaderHandler<> h;\
105 Reader reader;\
106 EXPECT_TRUE(reader.Parse(s, h));\
107 }\
108 }\
109 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler_##Name)) {\
110 for (size_t i = 0; i < kTrialCount * 10; i++) {\
111 memcpy(temp_, types_[index], typesLength_[index] + 1);\
112 InsituStringStream s(temp_);\
113 BaseReaderHandler<> h;\
114 Reader reader;\
115 EXPECT_TRUE(reader.Parse<kParseInsituFlag>(s, h));\
116 }\
117 }
118
119 TEST_TYPED(0, Booleans)
120 TEST_TYPED(1, Floats)
121 TEST_TYPED(2, Guids)
122 TEST_TYPED(3, Integers)
123 TEST_TYPED(4, Mixed)
124 TEST_TYPED(5, Nulls)
125 TEST_TYPED(6, Paragraphs)
126
127 #undef TEST_TYPED
128
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParse_DummyHandler_FullPrecision))129 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FullPrecision)) {
130 for (size_t i = 0; i < kTrialCount; i++) {
131 StringStream s(json_);
132 BaseReaderHandler<> h;
133 Reader reader;
134 EXPECT_TRUE(reader.Parse<kParseFullPrecisionFlag>(s, h));
135 }
136 }
137
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParseIterative_DummyHandler))138 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterative_DummyHandler)) {
139 for (size_t i = 0; i < kTrialCount; i++) {
140 StringStream s(json_);
141 BaseReaderHandler<> h;
142 Reader reader;
143 EXPECT_TRUE(reader.Parse<kParseIterativeFlag>(s, h));
144 }
145 }
146
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParseIterativeInsitu_DummyHandler))147 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativeInsitu_DummyHandler)) {
148 for (size_t i = 0; i < kTrialCount; i++) {
149 memcpy(temp_, json_, length_ + 1);
150 InsituStringStream s(temp_);
151 BaseReaderHandler<> h;
152 Reader reader;
153 EXPECT_TRUE(reader.Parse<kParseIterativeFlag|kParseInsituFlag>(s, h));
154 }
155 }
156
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParseIterativePull_DummyHandler))157 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativePull_DummyHandler)) {
158 for (size_t i = 0; i < kTrialCount; i++) {
159 StringStream s(json_);
160 BaseReaderHandler<> h;
161 Reader reader;
162 reader.IterativeParseInit();
163 while (!reader.IterativeParseComplete()) {
164 if (!reader.IterativeParseNext<kParseDefaultFlags>(s, h))
165 break;
166 }
167 EXPECT_FALSE(reader.HasParseError());
168 }
169 }
170
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParseIterativePullInsitu_DummyHandler))171 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativePullInsitu_DummyHandler)) {
172 for (size_t i = 0; i < kTrialCount; i++) {
173 memcpy(temp_, json_, length_ + 1);
174 InsituStringStream s(temp_);
175 BaseReaderHandler<> h;
176 Reader reader;
177 reader.IterativeParseInit();
178 while (!reader.IterativeParseComplete()) {
179 if (!reader.IterativeParseNext<kParseDefaultFlags|kParseInsituFlag>(s, h))
180 break;
181 }
182 EXPECT_FALSE(reader.HasParseError());
183 }
184 }
185
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParse_DummyHandler_ValidateEncoding))186 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_ValidateEncoding)) {
187 for (size_t i = 0; i < kTrialCount; i++) {
188 StringStream s(json_);
189 BaseReaderHandler<> h;
190 Reader reader;
191 EXPECT_TRUE(reader.Parse<kParseValidateEncodingFlag>(s, h));
192 }
193 }
194
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseInsitu_MemoryPoolAllocator))195 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseInsitu_MemoryPoolAllocator)) {
196 for (size_t i = 0; i < kTrialCount; i++) {
197 memcpy(temp_, json_, length_ + 1);
198 Document doc;
199 doc.ParseInsitu(temp_);
200 ASSERT_TRUE(doc.IsObject());
201 }
202 }
203
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseIterativeInsitu_MemoryPoolAllocator))204 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterativeInsitu_MemoryPoolAllocator)) {
205 for (size_t i = 0; i < kTrialCount; i++) {
206 memcpy(temp_, json_, length_ + 1);
207 Document doc;
208 doc.ParseInsitu<kParseIterativeFlag>(temp_);
209 ASSERT_TRUE(doc.IsObject());
210 }
211 }
212
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParse_MemoryPoolAllocator))213 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_MemoryPoolAllocator)) {
214 for (size_t i = 0; i < kTrialCount; i++) {
215 Document doc;
216 doc.Parse(json_);
217 ASSERT_TRUE(doc.IsObject());
218 }
219 }
220
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseLength_MemoryPoolAllocator))221 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseLength_MemoryPoolAllocator)) {
222 for (size_t i = 0; i < kTrialCount; i++) {
223 Document doc;
224 doc.Parse(json_, length_);
225 ASSERT_TRUE(doc.IsObject());
226 }
227 }
228
229 #if RAPIDJSON_HAS_STDSTRING
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseStdString_MemoryPoolAllocator))230 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseStdString_MemoryPoolAllocator)) {
231 const std::string s(json_, length_);
232 for (size_t i = 0; i < kTrialCount; i++) {
233 Document doc;
234 doc.Parse(s);
235 ASSERT_TRUE(doc.IsObject());
236 }
237 }
238 #endif
239
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseIterative_MemoryPoolAllocator))240 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterative_MemoryPoolAllocator)) {
241 for (size_t i = 0; i < kTrialCount; i++) {
242 Document doc;
243 doc.Parse<kParseIterativeFlag>(json_);
244 ASSERT_TRUE(doc.IsObject());
245 }
246 }
247
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParse_CrtAllocator))248 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_CrtAllocator)) {
249 for (size_t i = 0; i < kTrialCount; i++) {
250 memcpy(temp_, json_, length_ + 1);
251 GenericDocument<UTF8<>, CrtAllocator> doc;
252 doc.Parse(temp_);
253 ASSERT_TRUE(doc.IsObject());
254 }
255 }
256
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseEncodedInputStream_MemoryStream))257 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseEncodedInputStream_MemoryStream)) {
258 for (size_t i = 0; i < kTrialCount; i++) {
259 MemoryStream ms(json_, length_);
260 EncodedInputStream<UTF8<>, MemoryStream> is(ms);
261 Document doc;
262 doc.ParseStream<0, UTF8<> >(is);
263 ASSERT_TRUE(doc.IsObject());
264 }
265 }
266
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseAutoUTFInputStream_MemoryStream))267 TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseAutoUTFInputStream_MemoryStream)) {
268 for (size_t i = 0; i < kTrialCount; i++) {
269 MemoryStream ms(json_, length_);
270 AutoUTFInputStream<unsigned, MemoryStream> is(ms);
271 Document doc;
272 doc.ParseStream<0, AutoUTF<unsigned> >(is);
273 ASSERT_TRUE(doc.IsObject());
274 }
275 }
276
277 template<typename T>
Traverse(const T & value)278 size_t Traverse(const T& value) {
279 size_t count = 1;
280 switch(value.GetType()) {
281 case kObjectType:
282 for (typename T::ConstMemberIterator itr = value.MemberBegin(); itr != value.MemberEnd(); ++itr) {
283 count++; // name
284 count += Traverse(itr->value);
285 }
286 break;
287
288 case kArrayType:
289 for (typename T::ConstValueIterator itr = value.Begin(); itr != value.End(); ++itr)
290 count += Traverse(*itr);
291 break;
292
293 default:
294 // Do nothing.
295 break;
296 }
297 return count;
298 }
299
TEST_F(RapidJson,DocumentTraverse)300 TEST_F(RapidJson, DocumentTraverse) {
301 for (size_t i = 0; i < kTrialCount; i++) {
302 size_t count = Traverse(doc_);
303 EXPECT_EQ(4339u, count);
304 //if (i == 0)
305 // std::cout << count << std::endl;
306 }
307 }
308
309 #ifdef __GNUC__
310 RAPIDJSON_DIAG_PUSH
311 RAPIDJSON_DIAG_OFF(effc++)
312 #endif
313
314 struct ValueCounter : public BaseReaderHandler<> {
ValueCounterValueCounter315 ValueCounter() : count_(1) {} // root
316
EndObjectValueCounter317 bool EndObject(SizeType memberCount) { count_ += memberCount * 2; return true; }
EndArrayValueCounter318 bool EndArray(SizeType elementCount) { count_ += elementCount; return true; }
319
320 SizeType count_;
321 };
322
323 #ifdef __GNUC__
324 RAPIDJSON_DIAG_POP
325 #endif
326
TEST_F(RapidJson,DocumentAccept)327 TEST_F(RapidJson, DocumentAccept) {
328 for (size_t i = 0; i < kTrialCount; i++) {
329 ValueCounter counter;
330 doc_.Accept(counter);
331 EXPECT_EQ(4339u, counter.count_);
332 }
333 }
334
335 struct NullStream {
336 typedef char Ch;
337
NullStreamNullStream338 NullStream() /*: length_(0)*/ {}
PutNullStream339 void Put(Ch) { /*++length_;*/ }
FlushNullStream340 void Flush() {}
341 //size_t length_;
342 };
343
TEST_F(RapidJson,Writer_NullStream)344 TEST_F(RapidJson, Writer_NullStream) {
345 for (size_t i = 0; i < kTrialCount; i++) {
346 NullStream s;
347 Writer<NullStream> writer(s);
348 doc_.Accept(writer);
349 //if (i == 0)
350 // std::cout << s.length_ << std::endl;
351 }
352 }
353
TEST_F(RapidJson,SIMD_SUFFIX (Writer_StringBuffer))354 TEST_F(RapidJson, SIMD_SUFFIX(Writer_StringBuffer)) {
355 for (size_t i = 0; i < kTrialCount; i++) {
356 StringBuffer s(0, 1024 * 1024);
357 Writer<StringBuffer> writer(s);
358 doc_.Accept(writer);
359 const char* str = s.GetString();
360 (void)str;
361 //if (i == 0)
362 // std::cout << strlen(str) << std::endl;
363 }
364 }
365
366 #define TEST_TYPED(index, Name)\
367 TEST_F(RapidJson, SIMD_SUFFIX(Writer_StringBuffer_##Name)) {\
368 for (size_t i = 0; i < kTrialCount * 10; i++) {\
369 StringBuffer s(0, 1024 * 1024);\
370 Writer<StringBuffer> writer(s);\
371 typesDoc_[index].Accept(writer);\
372 const char* str = s.GetString();\
373 (void)str;\
374 }\
375 }
376
377 TEST_TYPED(0, Booleans)
378 TEST_TYPED(1, Floats)
379 TEST_TYPED(2, Guids)
380 TEST_TYPED(3, Integers)
381 TEST_TYPED(4, Mixed)
382 TEST_TYPED(5, Nulls)
383 TEST_TYPED(6, Paragraphs)
384
385 #undef TEST_TYPED
386
TEST_F(RapidJson,SIMD_SUFFIX (PrettyWriter_StringBuffer))387 TEST_F(RapidJson, SIMD_SUFFIX(PrettyWriter_StringBuffer)) {
388 for (size_t i = 0; i < kTrialCount; i++) {
389 StringBuffer s(0, 2048 * 1024);
390 PrettyWriter<StringBuffer> writer(s);
391 writer.SetIndent(' ', 1);
392 doc_.Accept(writer);
393 const char* str = s.GetString();
394 (void)str;
395 //if (i == 0)
396 // std::cout << strlen(str) << std::endl;
397 }
398 }
399
TEST_F(RapidJson,internal_Pow10)400 TEST_F(RapidJson, internal_Pow10) {
401 double sum = 0;
402 for (size_t i = 0; i < kTrialCount * kTrialCount; i++)
403 sum += internal::Pow10(int(i & 255));
404 EXPECT_GT(sum, 0.0);
405 }
406
TEST_F(RapidJson,SkipWhitespace_Basic)407 TEST_F(RapidJson, SkipWhitespace_Basic) {
408 for (size_t i = 0; i < kTrialCount; i++) {
409 rapidjson::StringStream s(whitespace_);
410 while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
411 s.Take();
412 ASSERT_EQ('[', s.Peek());
413 }
414 }
415
TEST_F(RapidJson,SIMD_SUFFIX (SkipWhitespace))416 TEST_F(RapidJson, SIMD_SUFFIX(SkipWhitespace)) {
417 for (size_t i = 0; i < kTrialCount; i++) {
418 rapidjson::StringStream s(whitespace_);
419 rapidjson::SkipWhitespace(s);
420 ASSERT_EQ('[', s.Peek());
421 }
422 }
423
TEST_F(RapidJson,SkipWhitespace_strspn)424 TEST_F(RapidJson, SkipWhitespace_strspn) {
425 for (size_t i = 0; i < kTrialCount; i++) {
426 const char* s = whitespace_ + std::strspn(whitespace_, " \t\r\n");
427 ASSERT_EQ('[', *s);
428 }
429 }
430
TEST_F(RapidJson,UTF8_Validate)431 TEST_F(RapidJson, UTF8_Validate) {
432 NullStream os;
433
434 for (size_t i = 0; i < kTrialCount; i++) {
435 StringStream is(json_);
436 bool result = true;
437 while (is.Peek() != '\0')
438 result &= UTF8<>::Validate(is, os);
439 EXPECT_TRUE(result);
440 }
441 }
442
TEST_F(RapidJson,FileReadStream)443 TEST_F(RapidJson, FileReadStream) {
444 for (size_t i = 0; i < kTrialCount; i++) {
445 FILE *fp = fopen(filename_, "rb");
446 char buffer[65536];
447 FileReadStream s(fp, buffer, sizeof(buffer));
448 while (s.Take() != '\0')
449 ;
450 fclose(fp);
451 }
452 }
453
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParse_DummyHandler_FileReadStream))454 TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FileReadStream)) {
455 for (size_t i = 0; i < kTrialCount; i++) {
456 FILE *fp = fopen(filename_, "rb");
457 char buffer[65536];
458 FileReadStream s(fp, buffer, sizeof(buffer));
459 BaseReaderHandler<> h;
460 Reader reader;
461 reader.Parse(s, h);
462 fclose(fp);
463 }
464 }
465
TEST_F(RapidJson,StringBuffer)466 TEST_F(RapidJson, StringBuffer) {
467 StringBuffer sb;
468 for (int i = 0; i < 32 * 1024 * 1024; i++)
469 sb.Put(i & 0x7f);
470 }
471
472 #endif // TEST_RAPIDJSON
473