rapidjsontest.cpp 13 KB

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