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