rapidjsontest.cpp 13 KB

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