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:
RapidJson()39     RapidJson() : temp_(), doc_() {}
40 
SetUp()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 
TearDown()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 
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParseInsitu_DummyHandler))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 
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParseInsitu_DummyHandler_ValidateEncoding))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 
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParse_DummyHandler))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 
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParse_DummyHandler_FullPrecision))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 
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParseIterative_DummyHandler))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 
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParseIterativeInsitu_DummyHandler))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 
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParse_DummyHandler_ValidateEncoding))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 
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseInsitu_MemoryPoolAllocator))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 
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseIterativeInsitu_MemoryPoolAllocator))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 
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParse_MemoryPoolAllocator))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 
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseIterative_MemoryPoolAllocator))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 
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParse_CrtAllocator))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 
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseEncodedInputStream_MemoryStream))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 
TEST_F(RapidJson,SIMD_SUFFIX (DocumentParseAutoUTFInputStream_MemoryStream))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>
Traverse(const T & value)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 
TEST_F(RapidJson,DocumentTraverse)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<> {
ValueCounterValueCounter232     ValueCounter() : count_(1) {}   // root
233 
EndObjectValueCounter234     bool EndObject(SizeType memberCount) { count_ += memberCount * 2; return true; }
EndArrayValueCounter235     bool EndArray(SizeType elementCount) { count_ += elementCount; return true; }
236 
237     SizeType count_;
238 };
239 
240 #ifdef __GNUC__
241 RAPIDJSON_DIAG_POP
242 #endif
243 
TEST_F(RapidJson,DocumentAccept)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 {
NullStreamNullStream253     NullStream() /*: length_(0)*/ {}
PutNullStream254     void Put(char) { /*++length_;*/ }
FlushNullStream255     void Flush() {}
256     //size_t length_;
257 };
258 
TEST_F(RapidJson,Writer_NullStream)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 
TEST_F(RapidJson,Writer_StringBuffer)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 
TEST_F(RapidJson,PrettyWriter_StringBuffer)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 
TEST_F(RapidJson,internal_Pow10)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 
TEST_F(RapidJson,SkipWhitespace_Basic)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 
TEST_F(RapidJson,SIMD_SUFFIX (SkipWhitespace))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 
TEST_F(RapidJson,SkipWhitespace_strspn)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 
TEST_F(RapidJson,UTF8_Validate)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 
TEST_F(RapidJson,FileReadStream)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 
TEST_F(RapidJson,SIMD_SUFFIX (ReaderParse_DummyHandler_FileReadStream))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