rapidjsontest.cpp 15 KB

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