Convert DITLs to JSON

This commit is contained in:
elasota
2020-02-07 02:45:45 -05:00
parent 507019abda
commit 7c3dc7d1a3
238 changed files with 53935 additions and 39 deletions

View File

@@ -0,0 +1,28 @@
set(PERFTEST_SOURCES
misctest.cpp
perftest.cpp
platformtest.cpp
rapidjsontest.cpp
schematest.cpp)
add_executable(perftest ${PERFTEST_SOURCES})
target_link_libraries(perftest ${TEST_LIBRARIES})
add_dependencies(tests perftest)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments -fcolor-diagnostics")
endif()
endif(CCACHE_FOUND)
set_property(DIRECTORY PROPERTY COMPILE_OPTIONS ${EXTRA_CXX_FLAGS})
IF(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug"))
add_test(NAME perftest
COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/perftest
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
ENDIF()

View File

@@ -0,0 +1,974 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "perftest.h"
#if TEST_MISC
#define __STDC_FORMAT_MACROS
#include "rapidjson/stringbuffer.h"
#define protected public
#include "rapidjson/writer.h"
#undef private
class Misc : public PerfTest {
};
// Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>
// See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details.
#define UTF8_ACCEPT 0
#define UTF8_REJECT 12
static const unsigned char utf8d[] = {
// The first part of the table maps bytes to character classes that
// to reduce the size of the transition table and create bitmasks.
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
// The second part is a transition table that maps a combination
// of a state of the automaton and a character class to a state.
0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
12,36,12,12,12,12,12,12,12,12,12,12,
};
static unsigned inline decode(unsigned* state, unsigned* codep, unsigned byte) {
unsigned type = utf8d[byte];
*codep = (*state != UTF8_ACCEPT) ?
(byte & 0x3fu) | (*codep << 6) :
(0xff >> type) & (byte);
*state = utf8d[256 + *state + type];
return *state;
}
static bool IsUTF8(unsigned char* s) {
unsigned codepoint, state = 0;
while (*s)
decode(&state, &codepoint, *s++);
return state == UTF8_ACCEPT;
}
TEST_F(Misc, Hoehrmann_IsUTF8) {
for (size_t i = 0; i < kTrialCount; i++) {
EXPECT_TRUE(IsUTF8((unsigned char*)json_));
}
}
////////////////////////////////////////////////////////////////////////////////
// CountDecimalDigit: Count number of decimal places
inline unsigned CountDecimalDigit_naive(unsigned n) {
unsigned count = 1;
while (n >= 10) {
n /= 10;
count++;
}
return count;
}
inline unsigned CountDecimalDigit_enroll4(unsigned n) {
unsigned count = 1;
while (n >= 10000) {
n /= 10000u;
count += 4;
}
if (n < 10) return count;
if (n < 100) return count + 1;
if (n < 1000) return count + 2;
return count + 3;
}
inline unsigned CountDecimalDigit64_enroll4(uint64_t n) {
unsigned count = 1;
while (n >= 10000) {
n /= 10000u;
count += 4;
}
if (n < 10) return count;
if (n < 100) return count + 1;
if (n < 1000) return count + 2;
return count + 3;
}
inline unsigned CountDecimalDigit_fast(unsigned n) {
static const uint32_t powers_of_10[] = {
0,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000
};
#if defined(_M_IX86) || defined(_M_X64)
unsigned long i = 0;
_BitScanReverse(&i, n | 1);
uint32_t t = (i + 1) * 1233 >> 12;
#elif defined(__GNUC__)
uint32_t t = (32 - __builtin_clz(n | 1)) * 1233 >> 12;
#else
#error
#endif
return t - (n < powers_of_10[t]) + 1;
}
inline unsigned CountDecimalDigit64_fast(uint64_t n) {
static const uint64_t powers_of_10[] = {
0,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
10000000000,
100000000000,
1000000000000,
10000000000000,
100000000000000,
1000000000000000,
10000000000000000,
100000000000000000,
1000000000000000000,
10000000000000000000U
};
#if defined(_M_IX86)
uint64_t m = n | 1;
unsigned long i = 0;
if (_BitScanReverse(&i, m >> 32))
i += 32;
else
_BitScanReverse(&i, m & 0xFFFFFFFF);
uint32_t t = (i + 1) * 1233 >> 12;
#elif defined(_M_X64)
unsigned long i = 0;
_BitScanReverse64(&i, n | 1);
uint32_t t = (i + 1) * 1233 >> 12;
#elif defined(__GNUC__)
uint32_t t = (64 - __builtin_clzll(n | 1)) * 1233 >> 12;
#else
#error
#endif
return t - (n < powers_of_10[t]) + 1;
}
#if 0
// Exhaustive, very slow
TEST_F(Misc, CountDecimalDigit_Verify) {
unsigned i = 0;
do {
if (i % (65536 * 256) == 0)
printf("%u\n", i);
ASSERT_EQ(CountDecimalDigit_enroll4(i), CountDecimalDigit_fast(i));
i++;
} while (i != 0);
}
static const unsigned kDigits10Trial = 1000000000u;
TEST_F(Misc, CountDecimalDigit_naive) {
unsigned sum = 0;
for (unsigned i = 0; i < kDigits10Trial; i++)
sum += CountDecimalDigit_naive(i);
printf("%u\n", sum);
}
TEST_F(Misc, CountDecimalDigit_enroll4) {
unsigned sum = 0;
for (unsigned i = 0; i < kDigits10Trial; i++)
sum += CountDecimalDigit_enroll4(i);
printf("%u\n", sum);
}
TEST_F(Misc, CountDecimalDigit_fast) {
unsigned sum = 0;
for (unsigned i = 0; i < kDigits10Trial; i++)
sum += CountDecimalDigit_fast(i);
printf("%u\n", sum);
}
#endif
TEST_F(Misc, CountDecimalDigit64_VerifyFast) {
uint64_t i = 1, j;
do {
//printf("%" PRIu64 "\n", i);
ASSERT_EQ(CountDecimalDigit64_enroll4(i), CountDecimalDigit64_fast(i));
j = i;
i *= 3;
} while (j < i);
}
////////////////////////////////////////////////////////////////////////////////
// integer-to-string conversion
// https://gist.github.com/anonymous/7179097
static const int randval[] ={
936116, 369532, 453755, -72860, 209713, 268347, 435278, -360266, -416287, -182064,
-644712, 944969, 640463, -366588, 471577, -69401, -744294, -505829, 923883, 831785,
-601136, -636767, -437054, 591718, 100758, 231907, -719038, 973540, -605220, 506659,
-871653, 462533, 764843, -919138, 404305, -630931, -288711, -751454, -173726, -718208,
432689, -281157, 360737, 659827, 19174, -376450, 769984, -858198, 439127, 734703,
-683426, 7, 386135, 186997, -643900, -744422, -604708, -629545, 42313, -933592,
-635566, 182308, 439024, -367219, -73924, -516649, 421935, -470515, 413507, -78952,
-427917, -561158, 737176, 94538, 572322, 405217, 709266, -357278, -908099, -425447,
601119, 750712, -862285, -177869, 900102, 384877, 157859, -641680, 503738, -702558,
278225, 463290, 268378, -212840, 580090, 347346, -473985, -950968, -114547, -839893,
-738032, -789424, 409540, 493495, 432099, 119755, 905004, -174834, 338266, 234298,
74641, -965136, -754593, 685273, 466924, 920560, 385062, 796402, -67229, 994864,
376974, 299869, -647540, -128724, 469890, -163167, -547803, -743363, 486463, -621028,
612288, 27459, -514224, 126342, -66612, 803409, -777155, -336453, -284002, 472451,
342390, -163630, 908356, -456147, -825607, 268092, -974715, 287227, 227890, -524101,
616370, -782456, 922098, -624001, -813690, 171605, -192962, 796151, 707183, -95696,
-23163, -721260, 508892, 430715, 791331, 482048, -996102, 863274, 275406, -8279,
-556239, -902076, 268647, -818565, 260069, -798232, -172924, -566311, -806503, -885992,
813969, -78468, 956632, 304288, 494867, -508784, 381751, 151264, 762953, 76352,
594902, 375424, 271700, -743062, 390176, 924237, 772574, 676610, 435752, -153847,
3959, -971937, -294181, -538049, -344620, -170136, 19120, -703157, 868152, -657961,
-818631, 219015, -872729, -940001, -956570, 880727, -345910, 942913, -942271, -788115,
225294, 701108, -517736, -416071, 281940, 488730, 942698, 711494, 838382, -892302,
-533028, 103052, 528823, 901515, 949577, 159364, 718227, -241814, -733661, -462928,
-495829, 165170, 513580, -629188, -509571, -459083, 198437, 77198, -644612, 811276,
-422298, -860842, -52584, 920369, 686424, -530667, -243476, 49763, 345866, -411960,
-114863, 470810, -302860, 683007, -509080, 2, -174981, -772163, -48697, 447770,
-268246, 213268, 269215, 78810, -236340, -639140, -864323, 505113, -986569, -325215,
541859, 163070, -819998, -645161, -583336, 573414, 696417, -132375, 3, -294501,
320435, 682591, 840008, 351740, 426951, 609354, 898154, -943254, 227321, -859793,
-727993, 44137, -497965, -782239, 14955, -746080, -243366, 9837, -233083, 606507,
-995864, -615287, -994307, 602715, 770771, -315040, 610860, 446102, -307120, 710728,
-590392, -230474, -762625, -637525, 134963, -202700, -766902, -985541, 218163, 682009,
926051, 525156, -61195, 403211, -810098, 245539, -431733, 179998, -806533, 745943,
447597, 131973, -187130, 826019, 286107, -937230, -577419, 20254, 681802, -340500,
323080, 266283, -667617, 309656, 416386, 611863, 759991, -534257, 523112, -634892,
-169913, -204905, -909867, -882185, -944908, 741811, -717675, 967007, -317396, 407230,
-412805, 792905, 994873, 744793, -456797, 713493, 355232, 116900, -945199, 880539,
342505, -580824, -262273, 982968, -349497, -735488, 311767, -455191, 570918, 389734,
-958386, 10262, -99267, 155481, 304210, 204724, 704367, -144893, -233664, -671441,
896849, 408613, 762236, 322697, 981321, 688476, 13663, -970704, -379507, 896412,
977084, 348869, 875948, 341348, 318710, 512081, 6163, 669044, 833295, 811883,
708756, -802534, -536057, 608413, -389625, -694603, 541106, -110037, 720322, -540581,
645420, 32980, 62442, 510157, -981870, -87093, -325960, -500494, -718291, -67889,
991501, 374804, 769026, -978869, 294747, 714623, 413327, -199164, 671368, 804789,
-362507, 798196, -170790, -568895, -869379, 62020, -316693, -837793, 644994, -39341,
-417504, -243068, -957756, 99072, 622234, -739992, 225668, 8863, -505910, 82483,
-559244, 241572, 1315, -36175, -54990, 376813, -11, 162647, -688204, -486163,
-54934, -197470, 744223, -762707, 732540, 996618, 351561, -445933, -898491, 486531,
456151, 15276, 290186, -817110, -52995, 313046, -452533, -96267, 94470, -500176,
-818026, -398071, -810548, -143325, -819741, 1338, -897676, -101577, -855445, 37309,
285742, 953804, -777927, -926962, -811217, -936744, -952245, -802300, -490188, -964953,
-552279, 329142, -570048, -505756, 682898, -381089, -14352, 175138, 152390, -582268,
-485137, 717035, 805329, 239572, -730409, 209643, -184403, -385864, 675086, 819648,
629058, -527109, -488666, -171981, 532788, 552441, 174666, 984921, 766514, 758787,
716309, 338801, -978004, -412163, 876079, -734212, 789557, -160491, -522719, 56644,
-991, -286038, -53983, 663740, 809812, 919889, -717502, -137704, 220511, 184396,
-825740, -588447, 430870, 124309, 135956, 558662, -307087, -788055, -451328, 812260,
931601, 324347, -482989, -117858, -278861, 189068, -172774, 929057, 293787, 198161,
-342386, -47173, 906555, -759955, -12779, 777604, -97869, 899320, 927486, -25284,
-848550, 259450, -485856, -17820, 88, 171400, 235492, -326783, -340793, 886886,
112428, -246280, 5979, 648444, -114982, 991013, -56489, -9497, 419706, 632820,
-341664, 393926, -848977, -22538, 257307, 773731, -905319, 491153, 734883, -868212,
-951053, 644458, -580758, 764735, 584316, 297077, 28852, -397710, -953669, 201772,
879050, -198237, -588468, 448102, -116837, 770007, -231812, 642906, -582166, -885828,
9, 305082, -996577, 303559, 75008, -772956, -447960, 599825, -295552, 870739,
-386278, -950300, 485359, -457081, 629461, -850276, 550496, -451755, -620841, -11766,
-950137, 832337, 28711, -273398, -507197, 91921, -271360, -705991, -753220, -388968,
967945, 340434, -320883, -662793, -554617, -574568, 477946, -6148, -129519, 689217,
920020, -656315, -974523, -212525, 80921, -612532, 645096, 545655, 655713, -591631,
-307385, -816688, -618823, -113713, 526430, 673063, 735916, -809095, -850417, 639004,
432281, -388185, 270708, 860146, -39902, -786157, -258180, -246169, -966720, -264957,
548072, -306010, -57367, -635665, 933824, 70553, -989936, -488741, 72411, -452509,
529831, 956277, 449019, -577850, -360986, -803418, 48833, 296073, 203430, 609591,
715483, 470964, 658106, -718254, -96424, 790163, 334739, 181070, -373578, 5,
-435088, 329841, 330939, -256602, 394355, 912412, 231910, 927278, -661933, 788539,
-769664, -893274, -96856, 298205, 901043, -608122, -527430, 183618, -553963, -35246,
-393924, 948832, -483198, 594501, 35460, -407007, 93494, -336881, -634072, 984205,
-812161, 944664, -31062, 753872, 823933, -69566, 50445, 290147, 85134, 34706,
551902, 405202, -991246, -84642, 154341, 316432, -695101, -651588, -5030, 137564,
-294665, 332541, 528307, -90572, -344923, 523766, -758498, -968047, 339028, 494578,
593129, -725773, 31834, -718406, -208638, 159665, -2043, 673344, -442767, 75816,
755442, 769257, -158730, -410272, 691688, 589550, -878398, -184121, 460679, 346312,
294163, -544602, 653308, 254167, -276979, 52073, -892684, 887653, -41222, 983065,
-68258, -408799, -99069, -674069, -863635, -32890, 622757, -743862, 40872, -4837,
-967228, 522370, -903951, -818669, 524459, 514702, 925801, 20007, -299229, 579348,
626021, 430089, 348139, -562692, -607728, -130606, -928451, -424793, -458647, -448892,
-312230, 143337, 109746, 880042, -339658, -785614, 938995, 540916, 118429, 661351,
-402967, 404729, -40918, -976535, 743230, 713110, 440182, -381314, -499252, 74613,
193652, 912717, 491323, 583633, 324691, 459397, 281253, 195540, -2764, -888651,
892449, 132663, -478373, -430002, -314551, 527826, 247165, 557966, 554778, 481531,
-946634, 431685, -769059, -348371, 174046, 184597, -354867, 584422, 227390, -850397,
-542924, -849093, -737769, 325359, 736314, 269101, 767940, 674809, 81413, -447458,
445076, 189072, 906218, 502688, -718476, -863827, -731381, 100660, 623249, 710008,
572060, 922203, 685740, 55096, 263394, -243695, -353910, -516788, 388471, 455165,
844103, -643772, 363976, 268875, -899450, 104470, 104029, -238874, -274659, 732969,
-676443, 953291, -916289, -861849, -242344, 958083, -479593, -970395, 799831, 277841,
-243236, -283462, -201510, 166263, -259105, -575706, 878926, 891064, 895297, 655262,
-34807, -809833, -89281, 342585, 554920, 1, 902141, -333425, 139703, 852318,
-618438, 329498, -932596, -692836, -513372, 733656, -523411, 85779, 500478, -682697,
-502836, 138776, 156341, -420037, -557964, -556378, 710993, -50383, -877159, 916334,
132996, 583516, -603392, -111615, -12288, -780214, 476780, 123327, 137607, 519956,
745837, 17358, -158581, -53490
};
static const size_t randvalCount = sizeof(randval) / sizeof(randval[0]);
static const size_t kItoaTrialCount = 10000;
static const char digits[201] =
"0001020304050607080910111213141516171819"
"2021222324252627282930313233343536373839"
"4041424344454647484950515253545556575859"
"6061626364656667686970717273747576777879"
"8081828384858687888990919293949596979899";
// Prevent code being optimized out
//#define OUTPUT_LENGTH(length) printf("", length)
#define OUTPUT_LENGTH(length) printf("%u\n", (unsigned)length)
template<typename OutputStream>
class Writer1 {
public:
Writer1() : os_() {}
Writer1(OutputStream& os) : os_(&os) {}
void Reset(OutputStream& os) {
os_ = &os;
}
bool WriteInt(int i) {
if (i < 0) {
os_->Put('-');
i = -i;
}
return WriteUint((unsigned)i);
}
bool WriteUint(unsigned u) {
char buffer[10];
char *p = buffer;
do {
*p++ = char(u % 10) + '0';
u /= 10;
} while (u > 0);
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
bool WriteInt64(int64_t i64) {
if (i64 < 0) {
os_->Put('-');
i64 = -i64;
}
WriteUint64((uint64_t)i64);
return true;
}
bool WriteUint64(uint64_t u64) {
char buffer[20];
char *p = buffer;
do {
*p++ = char(u64 % 10) + '0';
u64 /= 10;
} while (u64 > 0);
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
private:
OutputStream* os_;
};
template<>
bool Writer1<rapidjson::StringBuffer>::WriteUint(unsigned u) {
char buffer[10];
char* p = buffer;
do {
*p++ = char(u % 10) + '0';
u /= 10;
} while (u > 0);
char* d = os_->Push(p - buffer);
do {
--p;
*d++ = *p;
} while (p != buffer);
return true;
}
// Using digits LUT to reduce division/modulo
template<typename OutputStream>
class Writer2 {
public:
Writer2() : os_() {}
Writer2(OutputStream& os) : os_(&os) {}
void Reset(OutputStream& os) {
os_ = &os;
}
bool WriteInt(int i) {
if (i < 0) {
os_->Put('-');
i = -i;
}
return WriteUint((unsigned)i);
}
bool WriteUint(unsigned u) {
char buffer[10];
char* p = buffer;
while (u >= 100) {
const unsigned i = (u % 100) << 1;
u /= 100;
*p++ = digits[i + 1];
*p++ = digits[i];
}
if (u < 10)
*p++ = char(u) + '0';
else {
const unsigned i = u << 1;
*p++ = digits[i + 1];
*p++ = digits[i];
}
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
bool WriteInt64(int64_t i64) {
if (i64 < 0) {
os_->Put('-');
i64 = -i64;
}
WriteUint64((uint64_t)i64);
return true;
}
bool WriteUint64(uint64_t u64) {
char buffer[20];
char* p = buffer;
while (u64 >= 100) {
const unsigned i = static_cast<unsigned>(u64 % 100) << 1;
u64 /= 100;
*p++ = digits[i + 1];
*p++ = digits[i];
}
if (u64 < 10)
*p++ = char(u64) + '0';
else {
const unsigned i = static_cast<unsigned>(u64) << 1;
*p++ = digits[i + 1];
*p++ = digits[i];
}
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
private:
OutputStream* os_;
};
// First pass to count digits
template<typename OutputStream>
class Writer3 {
public:
Writer3() : os_() {}
Writer3(OutputStream& os) : os_(&os) {}
void Reset(OutputStream& os) {
os_ = &os;
}
bool WriteInt(int i) {
if (i < 0) {
os_->Put('-');
i = -i;
}
return WriteUint((unsigned)i);
}
bool WriteUint(unsigned u) {
char buffer[10];
char *p = buffer;
do {
*p++ = char(u % 10) + '0';
u /= 10;
} while (u > 0);
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
bool WriteInt64(int64_t i64) {
if (i64 < 0) {
os_->Put('-');
i64 = -i64;
}
WriteUint64((uint64_t)i64);
return true;
}
bool WriteUint64(uint64_t u64) {
char buffer[20];
char *p = buffer;
do {
*p++ = char(u64 % 10) + '0';
u64 /= 10;
} while (u64 > 0);
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
private:
void WriteUintReverse(char* d, unsigned u) {
do {
*--d = char(u % 10) + '0';
u /= 10;
} while (u > 0);
}
void WriteUint64Reverse(char* d, uint64_t u) {
do {
*--d = char(u % 10) + '0';
u /= 10;
} while (u > 0);
}
OutputStream* os_;
};
template<>
inline bool Writer3<rapidjson::StringBuffer>::WriteUint(unsigned u) {
unsigned digit = CountDecimalDigit_fast(u);
WriteUintReverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer3<rapidjson::InsituStringStream>::WriteUint(unsigned u) {
unsigned digit = CountDecimalDigit_fast(u);
WriteUintReverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer3<rapidjson::StringBuffer>::WriteUint64(uint64_t u) {
unsigned digit = CountDecimalDigit64_fast(u);
WriteUint64Reverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer3<rapidjson::InsituStringStream>::WriteUint64(uint64_t u) {
unsigned digit = CountDecimalDigit64_fast(u);
WriteUint64Reverse(os_->Push(digit) + digit, u);
return true;
}
// Using digits LUT to reduce division/modulo, two passes
template<typename OutputStream>
class Writer4 {
public:
Writer4() : os_() {}
Writer4(OutputStream& os) : os_(&os) {}
void Reset(OutputStream& os) {
os_ = &os;
}
bool WriteInt(int i) {
if (i < 0) {
os_->Put('-');
i = -i;
}
return WriteUint((unsigned)i);
}
bool WriteUint(unsigned u) {
char buffer[10];
char* p = buffer;
while (u >= 100) {
const unsigned i = (u % 100) << 1;
u /= 100;
*p++ = digits[i + 1];
*p++ = digits[i];
}
if (u < 10)
*p++ = char(u) + '0';
else {
const unsigned i = u << 1;
*p++ = digits[i + 1];
*p++ = digits[i];
}
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
bool WriteInt64(int64_t i64) {
if (i64 < 0) {
os_->Put('-');
i64 = -i64;
}
WriteUint64((uint64_t)i64);
return true;
}
bool WriteUint64(uint64_t u64) {
char buffer[20];
char* p = buffer;
while (u64 >= 100) {
const unsigned i = static_cast<unsigned>(u64 % 100) << 1;
u64 /= 100;
*p++ = digits[i + 1];
*p++ = digits[i];
}
if (u64 < 10)
*p++ = char(u64) + '0';
else {
const unsigned i = static_cast<unsigned>(u64) << 1;
*p++ = digits[i + 1];
*p++ = digits[i];
}
do {
--p;
os_->Put(*p);
} while (p != buffer);
return true;
}
private:
void WriteUintReverse(char* d, unsigned u) {
while (u >= 100) {
const unsigned i = (u % 100) << 1;
u /= 100;
*--d = digits[i + 1];
*--d = digits[i];
}
if (u < 10) {
*--d = char(u) + '0';
}
else {
const unsigned i = u << 1;
*--d = digits[i + 1];
*--d = digits[i];
}
}
void WriteUint64Reverse(char* d, uint64_t u) {
while (u >= 100) {
const unsigned i = (u % 100) << 1;
u /= 100;
*--d = digits[i + 1];
*--d = digits[i];
}
if (u < 10) {
*--d = char(u) + '0';
}
else {
const unsigned i = u << 1;
*--d = digits[i + 1];
*--d = digits[i];
}
}
OutputStream* os_;
};
template<>
inline bool Writer4<rapidjson::StringBuffer>::WriteUint(unsigned u) {
unsigned digit = CountDecimalDigit_fast(u);
WriteUintReverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer4<rapidjson::InsituStringStream>::WriteUint(unsigned u) {
unsigned digit = CountDecimalDigit_fast(u);
WriteUintReverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer4<rapidjson::StringBuffer>::WriteUint64(uint64_t u) {
unsigned digit = CountDecimalDigit64_fast(u);
WriteUint64Reverse(os_->Push(digit) + digit, u);
return true;
}
template<>
inline bool Writer4<rapidjson::InsituStringStream>::WriteUint64(uint64_t u) {
unsigned digit = CountDecimalDigit64_fast(u);
WriteUint64Reverse(os_->Push(digit) + digit, u);
return true;
}
template <typename Writer>
void itoa_Writer_StringBufferVerify() {
rapidjson::StringBuffer sb;
Writer writer(sb);
for (size_t j = 0; j < randvalCount; j++) {
char buffer[32];
sprintf(buffer, "%d", randval[j]);
writer.WriteInt(randval[j]);
ASSERT_STREQ(buffer, sb.GetString());
sb.Clear();
}
}
template <typename Writer>
void itoa_Writer_InsituStringStreamVerify() {
Writer writer;
for (size_t j = 0; j < randvalCount; j++) {
char buffer[32];
sprintf(buffer, "%d", randval[j]);
char buffer2[32];
rapidjson::InsituStringStream ss(buffer2);
writer.Reset(ss);
char* begin = ss.PutBegin();
writer.WriteInt(randval[j]);
ss.Put('\0');
ss.PutEnd(begin);
ASSERT_STREQ(buffer, buffer2);
}
}
template <typename Writer>
void itoa_Writer_StringBuffer() {
size_t length = 0;
rapidjson::StringBuffer sb;
Writer writer(sb);
for (size_t i = 0; i < kItoaTrialCount; i++) {
for (size_t j = 0; j < randvalCount; j++) {
writer.WriteInt(randval[j]);
length += sb.GetSize();
sb.Clear();
}
}
OUTPUT_LENGTH(length);
}
template <typename Writer>
void itoa_Writer_InsituStringStream() {
size_t length = 0;
char buffer[32];
Writer writer;
for (size_t i = 0; i < kItoaTrialCount; i++) {
for (size_t j = 0; j < randvalCount; j++) {
rapidjson::InsituStringStream ss(buffer);
writer.Reset(ss);
char* begin = ss.PutBegin();
writer.WriteInt(randval[j]);
length += ss.PutEnd(begin);
}
}
OUTPUT_LENGTH(length);
};
template <typename Writer>
void itoa64_Writer_StringBufferVerify() {
rapidjson::StringBuffer sb;
Writer writer(sb);
for (size_t j = 0; j < randvalCount; j++) {
char buffer[32];
int64_t x = randval[j] * randval[j];
sprintf(buffer, "%" PRIi64, x);
writer.WriteInt64(x);
ASSERT_STREQ(buffer, sb.GetString());
sb.Clear();
}
}
template <typename Writer>
void itoa64_Writer_InsituStringStreamVerify() {
Writer writer;
for (size_t j = 0; j < randvalCount; j++) {
char buffer[32];
int64_t x = randval[j] * randval[j];
sprintf(buffer, "%" PRIi64, x);
char buffer2[32];
rapidjson::InsituStringStream ss(buffer2);
writer.Reset(ss);
char* begin = ss.PutBegin();
writer.WriteInt64(x);
ss.Put('\0');
ss.PutEnd(begin);
ASSERT_STREQ(buffer, buffer2);
}
}
template <typename Writer>
void itoa64_Writer_StringBuffer() {
size_t length = 0;
rapidjson::StringBuffer sb;
Writer writer(sb);
for (size_t i = 0; i < kItoaTrialCount; i++) {
for (size_t j = 0; j < randvalCount; j++) {
writer.WriteInt64(randval[j] * randval[j]);
length += sb.GetSize();
sb.Clear();
}
}
OUTPUT_LENGTH(length);
}
template <typename Writer>
void itoa64_Writer_InsituStringStream() {
size_t length = 0;
char buffer[32];
Writer writer;
for (size_t i = 0; i < kItoaTrialCount; i++) {
for (size_t j = 0; j < randvalCount; j++) {
rapidjson::InsituStringStream ss(buffer);
writer.Reset(ss);
char* begin = ss.PutBegin();
writer.WriteInt64(randval[j] * randval[j]);
length += ss.PutEnd(begin);
}
}
OUTPUT_LENGTH(length);
};
// Full specialization for InsituStringStream to prevent memory copying
// (normally we will not use InsituStringStream for writing, just for testing)
namespace rapidjson {
template<>
bool rapidjson::Writer<InsituStringStream>::WriteInt(int i) {
char *buffer = os_->Push(11);
const char* end = internal::i32toa(i, buffer);
os_->Pop(11 - (end - buffer));
return true;
}
template<>
bool Writer<InsituStringStream>::WriteUint(unsigned u) {
char *buffer = os_->Push(10);
const char* end = internal::u32toa(u, buffer);
os_->Pop(10 - (end - buffer));
return true;
}
template<>
bool Writer<InsituStringStream>::WriteInt64(int64_t i64) {
char *buffer = os_->Push(21);
const char* end = internal::i64toa(i64, buffer);
os_->Pop(21 - (end - buffer));
return true;
}
template<>
bool Writer<InsituStringStream>::WriteUint64(uint64_t u) {
char *buffer = os_->Push(20);
const char* end = internal::u64toa(u, buffer);
os_->Pop(20 - (end - buffer));
return true;
}
} // namespace rapidjson
TEST_F(Misc, itoa_Writer_StringBufferVerify) { itoa_Writer_StringBufferVerify<rapidjson::Writer<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer1_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer1<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer2_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer2<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer3_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer3<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer4_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer4<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<rapidjson::Writer<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer1_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer1<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer2_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer2<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer3_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer3<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer4_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer4<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer_StringBuffer) { itoa_Writer_StringBuffer<rapidjson::Writer<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer1_StringBuffer) { itoa_Writer_StringBuffer<Writer1<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer2_StringBuffer) { itoa_Writer_StringBuffer<Writer2<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer3_StringBuffer) { itoa_Writer_StringBuffer<Writer3<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer4_StringBuffer) { itoa_Writer_StringBuffer<Writer4<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa_Writer_InsituStringStream) { itoa_Writer_InsituStringStream<rapidjson::Writer<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer1_InsituStringStream) { itoa_Writer_InsituStringStream<Writer1<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer2_InsituStringStream) { itoa_Writer_InsituStringStream<Writer2<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer3_InsituStringStream) { itoa_Writer_InsituStringStream<Writer3<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa_Writer4_InsituStringStream) { itoa_Writer_InsituStringStream<Writer4<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer_StringBufferVerify) { itoa64_Writer_StringBufferVerify<rapidjson::Writer<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer1_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer1<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer2_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer2<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer3_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer3<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer4_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer4<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<rapidjson::Writer<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer1_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer1<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer2_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer2<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer3_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer3<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer4_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer4<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer_StringBuffer) { itoa64_Writer_StringBuffer<rapidjson::Writer<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer1_StringBuffer) { itoa64_Writer_StringBuffer<Writer1<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer2_StringBuffer) { itoa64_Writer_StringBuffer<Writer2<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer3_StringBuffer) { itoa64_Writer_StringBuffer<Writer3<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer4_StringBuffer) { itoa64_Writer_StringBuffer<Writer4<rapidjson::StringBuffer> >(); }
TEST_F(Misc, itoa64_Writer_InsituStringStream) { itoa64_Writer_InsituStringStream<rapidjson::Writer<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer1_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer1<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer2_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer2<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer3_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer3<rapidjson::InsituStringStream> >(); }
TEST_F(Misc, itoa64_Writer4_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer4<rapidjson::InsituStringStream> >(); }
#endif // TEST_MISC

View File

@@ -0,0 +1,24 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "perftest.h"
int main(int argc, char **argv) {
#if _MSC_VER
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
//void *testWhetherMemoryLeakDetectionWorks = malloc(1);
#endif
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@@ -0,0 +1,185 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#ifndef PERFTEST_H_
#define PERFTEST_H_
#define TEST_RAPIDJSON 1
#define TEST_PLATFORM 0
#define TEST_MISC 0
#define TEST_VERSION_CODE(x,y,z) \
(((x)*100000) + ((y)*100) + (z))
// __SSE2__ and __SSE4_2__ are recognized by gcc, clang, and the Intel compiler.
// We use -march=native with gmake to enable -msse2 and -msse4.2, if supported.
// Likewise, __ARM_NEON is used to detect Neon.
#if defined(__SSE4_2__)
# define RAPIDJSON_SSE42
#elif defined(__SSE2__)
# define RAPIDJSON_SSE2
#elif defined(__ARM_NEON)
# define RAPIDJSON_NEON
#endif
#define RAPIDJSON_HAS_STDSTRING 1
////////////////////////////////////////////////////////////////////////////////
// Google Test
#ifdef __cplusplus
// gtest indirectly included inttypes.h, without __STDC_CONSTANT_MACROS.
#ifndef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS 1 // required by C++ standard
#endif
#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
#if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Weffc++"
#endif
#include "gtest/gtest.h"
#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#pragma GCC diagnostic pop
#endif
#ifdef _MSC_VER
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#pragma warning(disable : 4996) // 'function': was declared deprecated
#endif
//! Base class for all performance tests
class PerfTest : public ::testing::Test {
public:
PerfTest() : filename_(), json_(), length_(), whitespace_(), whitespace_length_() {}
virtual void SetUp() {
{
const char *paths[] = {
"data/sample.json",
"bin/data/sample.json",
"../bin/data/sample.json",
"../../bin/data/sample.json",
"../../../bin/data/sample.json"
};
FILE *fp = 0;
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
fp = fopen(filename_ = paths[i], "rb");
if (fp)
break;
}
ASSERT_TRUE(fp != 0);
fseek(fp, 0, SEEK_END);
length_ = (size_t)ftell(fp);
fseek(fp, 0, SEEK_SET);
json_ = (char*)malloc(length_ + 1);
ASSERT_EQ(length_, fread(json_, 1, length_, fp));
json_[length_] = '\0';
fclose(fp);
}
// whitespace test
{
whitespace_length_ = 1024 * 1024;
whitespace_ = (char *)malloc(whitespace_length_ + 4);
char *p = whitespace_;
for (size_t i = 0; i < whitespace_length_; i += 4) {
*p++ = ' ';
*p++ = '\n';
*p++ = '\r';
*p++ = '\t';
}
*p++ = '[';
*p++ = '0';
*p++ = ']';
*p++ = '\0';
}
// types test
{
const char *typespaths[] = {
"data/types",
"bin/types",
"../bin/types",
"../../bin/types/",
"../../../bin/types"
};
const char* typesfilenames[] = {
"booleans.json",
"floats.json",
"guids.json",
"integers.json",
"mixed.json",
"nulls.json",
"paragraphs.json"
};
for (size_t j = 0; j < sizeof(typesfilenames) / sizeof(typesfilenames[0]); j++) {
types_[j] = 0;
for (size_t i = 0; i < sizeof(typespaths) / sizeof(typespaths[0]); i++) {
char filename[256];
sprintf(filename, "%s/%s", typespaths[i], typesfilenames[j]);
if (FILE* fp = fopen(filename, "rb")) {
fseek(fp, 0, SEEK_END);
typesLength_[j] = (size_t)ftell(fp);
fseek(fp, 0, SEEK_SET);
types_[j] = (char*)malloc(typesLength_[j] + 1);
ASSERT_EQ(typesLength_[j], fread(types_[j], 1, typesLength_[j], fp));
types_[j][typesLength_[j]] = '\0';
fclose(fp);
break;
}
}
}
}
}
virtual void TearDown() {
free(json_);
free(whitespace_);
json_ = 0;
whitespace_ = 0;
for (size_t i = 0; i < 7; i++) {
free(types_[i]);
types_[i] = 0;
}
}
private:
PerfTest(const PerfTest&);
PerfTest& operator=(const PerfTest&);
protected:
const char* filename_;
char *json_;
size_t length_;
char *whitespace_;
size_t whitespace_length_;
char *types_[7];
size_t typesLength_[7];
static const size_t kTrialCount = 1000;
};
#endif // __cplusplus
#endif // PERFTEST_H_

View File

@@ -0,0 +1,166 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "perftest.h"
// This file is for giving the performance characteristics of the platform (compiler/OS/CPU).
#if TEST_PLATFORM
#include <cmath>
#include <fcntl.h>
// Windows
#ifdef _WIN32
#include <windows.h>
#endif
// UNIX
#if defined(unix) || defined(__unix__) || defined(__unix)
#include <unistd.h>
#ifdef _POSIX_MAPPED_FILES
#include <sys/mman.h>
#endif
#endif
class Platform : public PerfTest {
public:
virtual void SetUp() {
PerfTest::SetUp();
// temp buffer for testing
temp_ = (char *)malloc(length_ + 1);
memcpy(temp_, json_, length_);
checkSum_ = CheckSum();
}
char CheckSum() {
char c = 0;
for (size_t i = 0; i < length_; ++i)
c += temp_[i];
return c;
}
virtual void TearDown() {
PerfTest::TearDown();
free(temp_);
}
protected:
char *temp_;
char checkSum_;
};
TEST_F(Platform, CheckSum) {
for (int i = 0; i < kTrialCount; i++)
EXPECT_EQ(checkSum_, CheckSum());
}
TEST_F(Platform, strlen) {
for (int i = 0; i < kTrialCount; i++) {
size_t l = strlen(json_);
EXPECT_EQ(length_, l);
}
}
TEST_F(Platform, memcmp) {
for (int i = 0; i < kTrialCount; i++) {
EXPECT_EQ(0u, memcmp(temp_, json_, length_));
}
}
TEST_F(Platform, pow) {
double sum = 0;
for (int i = 0; i < kTrialCount * kTrialCount; i++)
sum += pow(10.0, i & 255);
EXPECT_GT(sum, 0.0);
}
TEST_F(Platform, Whitespace_strlen) {
for (int i = 0; i < kTrialCount; i++) {
size_t l = strlen(whitespace_);
EXPECT_GT(l, whitespace_length_);
}
}
TEST_F(Platform, Whitespace_strspn) {
for (int i = 0; i < kTrialCount; i++) {
size_t l = strspn(whitespace_, " \n\r\t");
EXPECT_EQ(whitespace_length_, l);
}
}
TEST_F(Platform, fread) {
for (int i = 0; i < kTrialCount; i++) {
FILE *fp = fopen(filename_, "rb");
ASSERT_EQ(length_, fread(temp_, 1, length_, fp));
EXPECT_EQ(checkSum_, CheckSum());
fclose(fp);
}
}
#ifdef _MSC_VER
TEST_F(Platform, read) {
for (int i = 0; i < kTrialCount; i++) {
int fd = _open(filename_, _O_BINARY | _O_RDONLY);
ASSERT_NE(-1, fd);
ASSERT_EQ(length_, _read(fd, temp_, length_));
EXPECT_EQ(checkSum_, CheckSum());
_close(fd);
}
}
#else
TEST_F(Platform, read) {
for (int i = 0; i < kTrialCount; i++) {
int fd = open(filename_, O_RDONLY);
ASSERT_NE(-1, fd);
ASSERT_EQ(length_, read(fd, temp_, length_));
EXPECT_EQ(checkSum_, CheckSum());
close(fd);
}
}
#endif
#ifdef _WIN32
TEST_F(Platform, MapViewOfFile) {
for (int i = 0; i < kTrialCount; i++) {
HANDLE file = CreateFile(filename_, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ASSERT_NE(INVALID_HANDLE_VALUE, file);
HANDLE mapObject = CreateFileMapping(file, NULL, PAGE_READONLY, 0, length_, NULL);
ASSERT_NE(INVALID_HANDLE_VALUE, mapObject);
void *p = MapViewOfFile(mapObject, FILE_MAP_READ, 0, 0, length_);
ASSERT_TRUE(p != NULL);
EXPECT_EQ(checkSum_, CheckSum());
ASSERT_TRUE(UnmapViewOfFile(p) == TRUE);
ASSERT_TRUE(CloseHandle(mapObject) == TRUE);
ASSERT_TRUE(CloseHandle(file) == TRUE);
}
}
#endif
#ifdef _POSIX_MAPPED_FILES
TEST_F(Platform, mmap) {
for (int i = 0; i < kTrialCount; i++) {
int fd = open(filename_, O_RDONLY);
ASSERT_NE(-1, fd);
void *p = mmap(NULL, length_, PROT_READ, MAP_PRIVATE, fd, 0);
ASSERT_TRUE(p != NULL);
EXPECT_EQ(checkSum_, CheckSum());
munmap(p, length_);
close(fd);
}
}
#endif
#endif // TEST_PLATFORM

View File

@@ -0,0 +1,546 @@
// Tencent is pleased to support the open source community by making RapidJSON available.
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#include "perftest.h"
#if TEST_RAPIDJSON
#include "rapidjson/rapidjson.h"
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/istreamwrapper.h"
#include "rapidjson/encodedstream.h"
#include "rapidjson/memorystream.h"
#include <fstream>
#ifdef RAPIDJSON_SSE2
#define SIMD_SUFFIX(name) name##_SSE2
#elif defined(RAPIDJSON_SSE42)
#define SIMD_SUFFIX(name) name##_SSE42
#elif defined(RAPIDJSON_NEON)
#define SIMD_SUFFIX(name) name##_NEON
#else
#define SIMD_SUFFIX(name) name
#endif
using namespace rapidjson;
class RapidJson : public PerfTest {
public:
RapidJson() : temp_(), doc_() {}
virtual void SetUp() {
PerfTest::SetUp();
// temp buffer for insitu parsing.
temp_ = (char *)malloc(length_ + 1);
// Parse as a document
EXPECT_FALSE(doc_.Parse(json_).HasParseError());
for (size_t i = 0; i < 7; i++)
EXPECT_FALSE(typesDoc_[i].Parse(types_[i]).HasParseError());
}
virtual void TearDown() {
PerfTest::TearDown();
free(temp_);
}
private:
RapidJson(const RapidJson&);
RapidJson& operator=(const RapidJson&);
protected:
char *temp_;
Document doc_;
Document typesDoc_[7];
};
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
InsituStringStream s(temp_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseInsituFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler_ValidateEncoding)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
InsituStringStream s(temp_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseInsituFlag | kParseValidateEncodingFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringStream s(json_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse(s, h));
}
}
#define TEST_TYPED(index, Name)\
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_##Name)) {\
for (size_t i = 0; i < kTrialCount * 10; i++) {\
StringStream s(types_[index]);\
BaseReaderHandler<> h;\
Reader reader;\
EXPECT_TRUE(reader.Parse(s, h));\
}\
}\
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseInsitu_DummyHandler_##Name)) {\
for (size_t i = 0; i < kTrialCount * 10; i++) {\
memcpy(temp_, types_[index], typesLength_[index] + 1);\
InsituStringStream s(temp_);\
BaseReaderHandler<> h;\
Reader reader;\
EXPECT_TRUE(reader.Parse<kParseInsituFlag>(s, h));\
}\
}
TEST_TYPED(0, Booleans)
TEST_TYPED(1, Floats)
TEST_TYPED(2, Guids)
TEST_TYPED(3, Integers)
TEST_TYPED(4, Mixed)
TEST_TYPED(5, Nulls)
TEST_TYPED(6, Paragraphs)
#undef TEST_TYPED
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FullPrecision)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringStream s(json_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseFullPrecisionFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterative_DummyHandler)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringStream s(json_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseIterativeFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativeInsitu_DummyHandler)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
InsituStringStream s(temp_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseIterativeFlag|kParseInsituFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativePull_DummyHandler)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringStream s(json_);
BaseReaderHandler<> h;
Reader reader;
reader.IterativeParseInit();
while (!reader.IterativeParseComplete()) {
if (!reader.IterativeParseNext<kParseDefaultFlags>(s, h))
break;
}
EXPECT_FALSE(reader.HasParseError());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParseIterativePullInsitu_DummyHandler)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
InsituStringStream s(temp_);
BaseReaderHandler<> h;
Reader reader;
reader.IterativeParseInit();
while (!reader.IterativeParseComplete()) {
if (!reader.IterativeParseNext<kParseDefaultFlags|kParseInsituFlag>(s, h))
break;
}
EXPECT_FALSE(reader.HasParseError());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_ValidateEncoding)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringStream s(json_);
BaseReaderHandler<> h;
Reader reader;
EXPECT_TRUE(reader.Parse<kParseValidateEncodingFlag>(s, h));
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseInsitu_MemoryPoolAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
Document doc;
doc.ParseInsitu(temp_);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterativeInsitu_MemoryPoolAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
Document doc;
doc.ParseInsitu<kParseIterativeFlag>(temp_);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_MemoryPoolAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
Document doc;
doc.Parse(json_);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseLength_MemoryPoolAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
Document doc;
doc.Parse(json_, length_);
ASSERT_TRUE(doc.IsObject());
}
}
#if RAPIDJSON_HAS_STDSTRING
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseStdString_MemoryPoolAllocator)) {
const std::string s(json_, length_);
for (size_t i = 0; i < kTrialCount; i++) {
Document doc;
doc.Parse(s);
ASSERT_TRUE(doc.IsObject());
}
}
#endif
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseIterative_MemoryPoolAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
Document doc;
doc.Parse<kParseIterativeFlag>(json_);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParse_CrtAllocator)) {
for (size_t i = 0; i < kTrialCount; i++) {
memcpy(temp_, json_, length_ + 1);
GenericDocument<UTF8<>, CrtAllocator> doc;
doc.Parse(temp_);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseEncodedInputStream_MemoryStream)) {
for (size_t i = 0; i < kTrialCount; i++) {
MemoryStream ms(json_, length_);
EncodedInputStream<UTF8<>, MemoryStream> is(ms);
Document doc;
doc.ParseStream<0, UTF8<> >(is);
ASSERT_TRUE(doc.IsObject());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(DocumentParseAutoUTFInputStream_MemoryStream)) {
for (size_t i = 0; i < kTrialCount; i++) {
MemoryStream ms(json_, length_);
AutoUTFInputStream<unsigned, MemoryStream> is(ms);
Document doc;
doc.ParseStream<0, AutoUTF<unsigned> >(is);
ASSERT_TRUE(doc.IsObject());
}
}
template<typename T>
size_t Traverse(const T& value) {
size_t count = 1;
switch(value.GetType()) {
case kObjectType:
for (typename T::ConstMemberIterator itr = value.MemberBegin(); itr != value.MemberEnd(); ++itr) {
count++; // name
count += Traverse(itr->value);
}
break;
case kArrayType:
for (typename T::ConstValueIterator itr = value.Begin(); itr != value.End(); ++itr)
count += Traverse(*itr);
break;
default:
// Do nothing.
break;
}
return count;
}
TEST_F(RapidJson, DocumentTraverse) {
for (size_t i = 0; i < kTrialCount; i++) {
size_t count = Traverse(doc_);
EXPECT_EQ(4339u, count);
//if (i == 0)
// std::cout << count << std::endl;
}
}
#ifdef __GNUC__
RAPIDJSON_DIAG_PUSH
RAPIDJSON_DIAG_OFF(effc++)
#endif
struct ValueCounter : public BaseReaderHandler<> {
ValueCounter() : count_(1) {} // root
bool EndObject(SizeType memberCount) { count_ += memberCount * 2; return true; }
bool EndArray(SizeType elementCount) { count_ += elementCount; return true; }
SizeType count_;
};
#ifdef __GNUC__
RAPIDJSON_DIAG_POP
#endif
TEST_F(RapidJson, DocumentAccept) {
for (size_t i = 0; i < kTrialCount; i++) {
ValueCounter counter;
doc_.Accept(counter);
EXPECT_EQ(4339u, counter.count_);
}
}
struct NullStream {
typedef char Ch;
NullStream() /*: length_(0)*/ {}
void Put(Ch) { /*++length_;*/ }
void Flush() {}
//size_t length_;
};
TEST_F(RapidJson, Writer_NullStream) {
for (size_t i = 0; i < kTrialCount; i++) {
NullStream s;
Writer<NullStream> writer(s);
doc_.Accept(writer);
//if (i == 0)
// std::cout << s.length_ << std::endl;
}
}
TEST_F(RapidJson, SIMD_SUFFIX(Writer_StringBuffer)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringBuffer s(0, 1024 * 1024);
Writer<StringBuffer> writer(s);
doc_.Accept(writer);
const char* str = s.GetString();
(void)str;
//if (i == 0)
// std::cout << strlen(str) << std::endl;
}
}
#define TEST_TYPED(index, Name)\
TEST_F(RapidJson, SIMD_SUFFIX(Writer_StringBuffer_##Name)) {\
for (size_t i = 0; i < kTrialCount * 10; i++) {\
StringBuffer s(0, 1024 * 1024);\
Writer<StringBuffer> writer(s);\
typesDoc_[index].Accept(writer);\
const char* str = s.GetString();\
(void)str;\
}\
}
TEST_TYPED(0, Booleans)
TEST_TYPED(1, Floats)
TEST_TYPED(2, Guids)
TEST_TYPED(3, Integers)
TEST_TYPED(4, Mixed)
TEST_TYPED(5, Nulls)
TEST_TYPED(6, Paragraphs)
#undef TEST_TYPED
TEST_F(RapidJson, SIMD_SUFFIX(PrettyWriter_StringBuffer)) {
for (size_t i = 0; i < kTrialCount; i++) {
StringBuffer s(0, 2048 * 1024);
PrettyWriter<StringBuffer> writer(s);
writer.SetIndent(' ', 1);
doc_.Accept(writer);
const char* str = s.GetString();
(void)str;
//if (i == 0)
// std::cout << strlen(str) << std::endl;
}
}
TEST_F(RapidJson, internal_Pow10) {
double sum = 0;
for (size_t i = 0; i < kTrialCount * kTrialCount; i++)
sum += internal::Pow10(int(i & 255));
EXPECT_GT(sum, 0.0);
}
TEST_F(RapidJson, SkipWhitespace_Basic) {
for (size_t i = 0; i < kTrialCount; i++) {
rapidjson::StringStream s(whitespace_);
while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
s.Take();
ASSERT_EQ('[', s.Peek());
}
}
TEST_F(RapidJson, SIMD_SUFFIX(SkipWhitespace)) {
for (size_t i = 0; i < kTrialCount; i++) {
rapidjson::StringStream s(whitespace_);
rapidjson::SkipWhitespace(s);
ASSERT_EQ('[', s.Peek());
}
}
TEST_F(RapidJson, SkipWhitespace_strspn) {
for (size_t i = 0; i < kTrialCount; i++) {
const char* s = whitespace_ + std::strspn(whitespace_, " \t\r\n");
ASSERT_EQ('[', *s);
}
}
TEST_F(RapidJson, UTF8_Validate) {
NullStream os;
for (size_t i = 0; i < kTrialCount; i++) {
StringStream is(json_);
bool result = true;
while (is.Peek() != '\0')
result &= UTF8<>::Validate(is, os);
EXPECT_TRUE(result);
}
}
TEST_F(RapidJson, FileReadStream) {
for (size_t i = 0; i < kTrialCount; i++) {
FILE *fp = fopen(filename_, "rb");
char buffer[65536];
FileReadStream s(fp, buffer, sizeof(buffer));
while (s.Take() != '\0')
;
fclose(fp);
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_FileReadStream)) {
for (size_t i = 0; i < kTrialCount; i++) {
FILE *fp = fopen(filename_, "rb");
char buffer[65536];
FileReadStream s(fp, buffer, sizeof(buffer));
BaseReaderHandler<> h;
Reader reader;
reader.Parse(s, h);
fclose(fp);
}
}
TEST_F(RapidJson, IStreamWrapper) {
for (size_t i = 0; i < kTrialCount; i++) {
std::ifstream is(filename_, std::ios::in | std::ios::binary);
char buffer[65536];
IStreamWrapper isw(is, buffer, sizeof(buffer));
while (isw.Take() != '\0')
;
is.close();
}
}
TEST_F(RapidJson, IStreamWrapper_Unbuffered) {
for (size_t i = 0; i < kTrialCount; i++) {
std::ifstream is(filename_, std::ios::in | std::ios::binary);
IStreamWrapper isw(is);
while (isw.Take() != '\0')
;
is.close();
}
}
TEST_F(RapidJson, IStreamWrapper_Setbuffered) {
for (size_t i = 0; i < kTrialCount; i++) {
std::ifstream is;
char buffer[65536];
is.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
is.open(filename_, std::ios::in | std::ios::binary);
IStreamWrapper isw(is);
while (isw.Take() != '\0')
;
is.close();
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_IStreamWrapper)) {
for (size_t i = 0; i < kTrialCount; i++) {
std::ifstream is(filename_, std::ios::in | std::ios::binary);
char buffer[65536];
IStreamWrapper isw(is, buffer, sizeof(buffer));
BaseReaderHandler<> h;
Reader reader;
reader.Parse(isw, h);
is.close();
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_IStreamWrapper_Unbuffered)) {
for (size_t i = 0; i < kTrialCount; i++) {
std::ifstream is(filename_, std::ios::in | std::ios::binary);
IStreamWrapper isw(is);
BaseReaderHandler<> h;
Reader reader;
reader.Parse(isw, h);
is.close();
}
}
TEST_F(RapidJson, SIMD_SUFFIX(ReaderParse_DummyHandler_IStreamWrapper_Setbuffered)) {
for (size_t i = 0; i < kTrialCount; i++) {
std::ifstream is;
char buffer[65536];
is.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
is.open(filename_, std::ios::in | std::ios::binary);
IStreamWrapper isw(is);
BaseReaderHandler<> h;
Reader reader;
reader.Parse(isw, h);
is.close();
}
}
TEST_F(RapidJson, StringBuffer) {
StringBuffer sb;
for (int i = 0; i < 32 * 1024 * 1024; i++)
sb.Put(i & 0x7f);
}
#endif // TEST_RAPIDJSON

View File

@@ -0,0 +1,223 @@
#include "perftest.h"
#if TEST_RAPIDJSON
#include "rapidjson/schema.h"
#include <ctime>
#include <string>
#include <vector>
#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
using namespace rapidjson;
RAPIDJSON_DIAG_PUSH
#if defined(__GNUC__) && __GNUC__ >= 7
RAPIDJSON_DIAG_OFF(format-overflow)
#endif
template <typename Allocator>
static char* ReadFile(const char* filename, Allocator& allocator) {
const char *paths[] = {
"",
"bin/",
"../bin/",
"../../bin/",
"../../../bin/"
};
char buffer[1024];
FILE *fp = 0;
for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) {
sprintf(buffer, "%s%s", paths[i], filename);
fp = fopen(buffer, "rb");
if (fp)
break;
}
if (!fp)
return 0;
fseek(fp, 0, SEEK_END);
size_t length = static_cast<size_t>(ftell(fp));
fseek(fp, 0, SEEK_SET);
char* json = reinterpret_cast<char*>(allocator.Malloc(length + 1));
size_t readLength = fread(json, 1, length, fp);
json[readLength] = '\0';
fclose(fp);
return json;
}
RAPIDJSON_DIAG_POP
class Schema : public PerfTest {
public:
Schema() {}
virtual void SetUp() {
PerfTest::SetUp();
const char* filenames[] = {
"additionalItems.json",
"additionalProperties.json",
"allOf.json",
"anyOf.json",
"default.json",
"definitions.json",
"dependencies.json",
"enum.json",
"items.json",
"maximum.json",
"maxItems.json",
"maxLength.json",
"maxProperties.json",
"minimum.json",
"minItems.json",
"minLength.json",
"minProperties.json",
"multipleOf.json",
"not.json",
"oneOf.json",
"pattern.json",
"patternProperties.json",
"properties.json",
"ref.json",
"refRemote.json",
"required.json",
"type.json",
"uniqueItems.json"
};
char jsonBuffer[65536];
MemoryPoolAllocator<> jsonAllocator(jsonBuffer, sizeof(jsonBuffer));
for (size_t i = 0; i < ARRAY_SIZE(filenames); i++) {
char filename[FILENAME_MAX];
sprintf(filename, "jsonschema/tests/draft4/%s", filenames[i]);
char* json = ReadFile(filename, jsonAllocator);
if (!json) {
printf("json test suite file %s not found", filename);
return;
}
Document d;
d.Parse(json);
if (d.HasParseError()) {
printf("json test suite file %s has parse error", filename);
return;
}
for (Value::ConstValueIterator schemaItr = d.Begin(); schemaItr != d.End(); ++schemaItr) {
std::string schemaDescription = (*schemaItr)["description"].GetString();
if (IsExcludeTestSuite(schemaDescription))
continue;
TestSuite* ts = new TestSuite;
ts->schema = new SchemaDocument((*schemaItr)["schema"]);
const Value& tests = (*schemaItr)["tests"];
for (Value::ConstValueIterator testItr = tests.Begin(); testItr != tests.End(); ++testItr) {
if (IsExcludeTest(schemaDescription + ", " + (*testItr)["description"].GetString()))
continue;
Document* d2 = new Document;
d2->CopyFrom((*testItr)["data"], d2->GetAllocator());
ts->tests.push_back(d2);
}
testSuites.push_back(ts);
}
}
}
virtual void TearDown() {
PerfTest::TearDown();
for (TestSuiteList::const_iterator itr = testSuites.begin(); itr != testSuites.end(); ++itr)
delete *itr;
testSuites.clear();
}
private:
// Using the same exclusion in https://github.com/json-schema/JSON-Schema-Test-Suite
static bool IsExcludeTestSuite(const std::string& description) {
const char* excludeTestSuites[] = {
//lost failing these tests
"remote ref",
"remote ref, containing refs itself",
"fragment within remote ref",
"ref within remote ref",
"change resolution scope",
// these below were added to get jsck in the benchmarks)
"uniqueItems validation",
"valid definition",
"invalid definition"
};
for (size_t i = 0; i < ARRAY_SIZE(excludeTestSuites); i++)
if (excludeTestSuites[i] == description)
return true;
return false;
}
// Using the same exclusion in https://github.com/json-schema/JSON-Schema-Test-Suite
static bool IsExcludeTest(const std::string& description) {
const char* excludeTests[] = {
//lots of validators fail these
"invalid definition, invalid definition schema",
"maxLength validation, two supplementary Unicode code points is long enough",
"minLength validation, one supplementary Unicode code point is not long enough",
//this is to get tv4 in the benchmarks
"heterogeneous enum validation, something else is invalid"
};
for (size_t i = 0; i < ARRAY_SIZE(excludeTests); i++)
if (excludeTests[i] == description)
return true;
return false;
}
Schema(const Schema&);
Schema& operator=(const Schema&);
protected:
typedef std::vector<Document*> DocumentList;
struct TestSuite {
TestSuite() : schema() {}
~TestSuite() {
delete schema;
for (DocumentList::iterator itr = tests.begin(); itr != tests.end(); ++itr)
delete *itr;
}
SchemaDocument* schema;
DocumentList tests;
};
typedef std::vector<TestSuite* > TestSuiteList;
TestSuiteList testSuites;
};
TEST_F(Schema, TestSuite) {
char validatorBuffer[65536];
MemoryPoolAllocator<> validatorAllocator(validatorBuffer, sizeof(validatorBuffer));
const int trialCount = 100000;
int testCount = 0;
clock_t start = clock();
for (int i = 0; i < trialCount; i++) {
for (TestSuiteList::const_iterator itr = testSuites.begin(); itr != testSuites.end(); ++itr) {
const TestSuite& ts = **itr;
GenericSchemaValidator<SchemaDocument, BaseReaderHandler<UTF8<> >, MemoryPoolAllocator<> > validator(*ts.schema, &validatorAllocator);
for (DocumentList::const_iterator testItr = ts.tests.begin(); testItr != ts.tests.end(); ++testItr) {
validator.Reset();
(*testItr)->Accept(validator);
testCount++;
}
validatorAllocator.Clear();
}
}
clock_t end = clock();
double duration = double(end - start) / CLOCKS_PER_SEC;
printf("%d trials in %f s -> %f trials per sec\n", trialCount, duration, trialCount / duration);
printf("%d tests per trial\n", testCount / trialCount);
}
#endif