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