Skip to content

Commit aa78b70

Browse files
committed
Introducing a "native" instruction set so that you do not need to do #ifdef to select the right SIMD set all the time.
Fixing indentation. Removing some obsolete WARN_UNUSED. Fixing a weird warning with optind variable.
1 parent 1b81e7c commit aa78b70

File tree

7 files changed

+50
-42
lines changed

7 files changed

+50
-42
lines changed

benchmark/parse.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,8 @@ int main(int argc, char *argv[]) {
144144
std::cout << "[verbose] allocated memory for parsed JSON " << std::endl;
145145
}
146146
unified.start();
147-
#ifdef __AVX2__
148-
isok = (find_structural_bits<simdjson::instruction_set::avx2>(p.data(), p.size(), pj) == simdjson::SUCCESS);
149-
#elif defined (__ARM_NEON)
150-
isok = (find_structural_bits<simdjson::instruction_set::neon>(p.data(), p.size(), pj) == simdjson::SUCCESS);
151-
#endif
147+
// The default template is simdjson::instruction_set::native.
148+
isok = (find_structural_bits<>(p.data(), p.size(), pj) == simdjson::SUCCESS);
152149
unified.end(results);
153150
cy1 += results[0];
154151
cl1 += results[1];
@@ -189,11 +186,8 @@ int main(int argc, char *argv[]) {
189186
}
190187

191188
auto start = std::chrono::steady_clock::now();
192-
#ifdef __AVX2__
193-
isok = (find_structural_bits<simdjson::instruction_set::avx2>(p.data(), p.size(), pj) == simdjson::SUCCESS);
194-
#elif defined (__ARM_NEON)
195-
isok = (find_structural_bits<simdjson::instruction_set::neon>(p.data(), p.size(), pj) == simdjson::SUCCESS);
196-
#endif
189+
// The default template is simdjson::instruction_set::native.
190+
isok = (find_structural_bits<>(p.data(), p.size(), pj) == simdjson::SUCCESS);
197191
isok = isok && (simdjson::SUCCESS == unified_machine(p.data(), p.size(), pj));
198192
auto end = std::chrono::steady_clock::now();
199193
std::chrono::duration<double> secs = end - start;

benchmark/statisticalmodel.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,8 @@ int main(int argc, char *argv[]) {
180180
results.resize(evts.size());
181181
for (uint32_t i = 0; i < iterations; i++) {
182182
unified.start();
183-
#ifdef __AVX2__
184-
bool isok = (find_structural_bits<simdjson::instruction_set::avx2>(p.data(), p.size(), pj) == simdjson::SUCCESS);
185-
#elif defined (__ARM_NEON)
186-
bool isok = (find_structural_bits<simdjson::instruction_set::neon>(p.data(), p.size(), pj) == simdjson::SUCCESS);
187-
#endif
183+
// The default template is simdjson::instruction_set::native.
184+
bool isok = (find_structural_bits<>(p.data(), p.size(), pj) == simdjson::SUCCESS);
188185
unified.end(results);
189186

190187
cy1 += results[0];

include/simdjson/jsonparser.h

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,20 @@
1515
#include <unistd.h>
1616
#endif
1717

18+
// The function that users are expected to call is json_parse.
19+
// We have more than one such function because we want to support several
20+
// instruction sets.
21+
1822
// function pointer type for json_parse
1923
using json_parse_functype = int (const uint8_t *buf, size_t len, ParsedJson &pj, bool reallocifneeded);
2024

2125
// Pointer that holds the json_parse implementation corresponding to the available SIMD instruction set
2226
extern json_parse_functype *json_parse_ptr;
2327

28+
29+
// json_parse_implementation is the generic function, it is specialized for various
30+
// SIMD instruction sets, e.g., as json_parse_implementation<simdjson::instruction_set::avx2>
31+
// or json_parse_implementation<simdjson::instruction_set::neon>
2432
template<simdjson::instruction_set T>
2533
int json_parse_implementation(const uint8_t *buf, size_t len, ParsedJson &pj, bool reallocifneeded = true) {
2634
if (pj.bytecapacity < len) {
@@ -29,22 +37,22 @@ int json_parse_implementation(const uint8_t *buf, size_t len, ParsedJson &pj, bo
2937
bool reallocated = false;
3038
if(reallocifneeded) {
3139
#ifdef ALLOW_SAME_PAGE_BUFFER_OVERRUN
32-
// realloc is needed if the end of the memory crosses a page
40+
// realloc is needed if the end of the memory crosses a page
3341
#ifdef _MSC_VER
34-
SYSTEM_INFO sysInfo;
35-
GetSystemInfo(&sysInfo);
36-
long pagesize = sysInfo.dwPageSize;
42+
SYSTEM_INFO sysInfo;
43+
GetSystemInfo(&sysInfo);
44+
long pagesize = sysInfo.dwPageSize;
3745
#else
3846
long pagesize = sysconf (_SC_PAGESIZE);
3947
#endif
40-
//////////////
41-
// We want to check that buf + len - 1 and buf + len - 1 + SIMDJSON_PADDING
42-
// are in the same page.
43-
// That is, we want to check that
44-
// (buf + len - 1) / pagesize == (buf + len - 1 + SIMDJSON_PADDING) / pagesize
45-
// That's true if (buf + len - 1) % pagesize + SIMDJSON_PADDING < pagesize.
46-
///////////
47-
if ( (reinterpret_cast<uintptr_t>(buf + len - 1) % pagesize ) + SIMDJSON_PADDING < static_cast<uintptr_t>(pagesize) ) {
48+
//////////////
49+
// We want to check that buf + len - 1 and buf + len - 1 + SIMDJSON_PADDING
50+
// are in the same page.
51+
// That is, we want to check that
52+
// (buf + len - 1) / pagesize == (buf + len - 1 + SIMDJSON_PADDING) / pagesize
53+
// That's true if (buf + len - 1) % pagesize + SIMDJSON_PADDING < pagesize.
54+
///////////
55+
if ( (reinterpret_cast<uintptr_t>(buf + len - 1) % pagesize ) + SIMDJSON_PADDING < static_cast<uintptr_t>(pagesize) ) {
4856
#else // SIMDJSON_SAFE_SAME_PAGE_READ_OVERRUN
4957
if(true) { // if not SIMDJSON_SAFE_SAME_PAGE_READ_OVERRUN, we always reallocate
5058
#endif
@@ -53,8 +61,8 @@ int json_parse_implementation(const uint8_t *buf, size_t len, ParsedJson &pj, bo
5361
if(buf == NULL) return simdjson::MEMALLOC;
5462
memcpy((void*)buf,tmpbuf,len);
5563
reallocated = true;
56-
}
57-
}
64+
} // if (true) OR if ( (reinterpret_cast<uintptr_t>(buf + len - 1) % pagesize ) + SIMDJSON_PADDING < static_cast<uintptr_t>(pagesize) ) {
65+
} // if(reallocifneeded) {
5866
int stage1_is_ok = find_structural_bits<T>(buf, len, pj);
5967
if(stage1_is_ok != simdjson::SUCCESS) {
6068
pj.errorcode = stage1_is_ok;
@@ -81,7 +89,6 @@ int json_parse_implementation(const uint8_t *buf, size_t len, ParsedJson &pj, bo
8189
// all bytes at and after buf + len are ignored (can be garbage).
8290
// The ParsedJson object can be reused.
8391

84-
WARN_UNUSED
8592
inline int json_parse(const uint8_t *buf, size_t len, ParsedJson &pj, bool reallocifneeded = true) {
8693
return json_parse_ptr(buf, len, pj, reallocifneeded);
8794
}
@@ -102,7 +109,6 @@ inline int json_parse(const uint8_t *buf, size_t len, ParsedJson &pj, bool reall
102109
// The input buf should be readable up to buf + len + SIMDJSON_PADDING if reallocifneeded is false,
103110
// all bytes at and after buf + len are ignored (can be garbage).
104111
// The ParsedJson object can be reused.
105-
WARN_UNUSED
106112
inline int json_parse(const char * buf, size_t len, ParsedJson &pj, bool reallocifneeded = true) {
107113
return json_parse_ptr(reinterpret_cast<const uint8_t *>(buf), len, pj, reallocifneeded);
108114
}
@@ -120,7 +126,6 @@ int json_parse(const char * buf, ParsedJson &pj) = delete;
120126
//
121127
// A temporary buffer is created when needed during processing
122128
// (a copy of the input string is made).
123-
WARN_UNUSED
124129
inline int json_parse(const std::string &s, ParsedJson &pj) {
125130
return json_parse(s.data(), s.length(), pj, true);
126131
}
@@ -135,7 +140,6 @@ inline int json_parse(const std::string &s, ParsedJson &pj) {
135140
//
136141
// You can also check validity
137142
// by calling pj.isValid(). The same ParsedJson can be reused for other documents.
138-
WARN_UNUSED
139143
inline int json_parse(const padded_string &s, ParsedJson &pj) {
140144
return json_parse(s.data(), s.length(), pj, false);
141145
}

include/simdjson/simdjson.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,20 @@ struct simdjson {
88
avx2,
99
sse4_2,
1010
neon,
11-
none
11+
none,
12+
// the 'native' enum class value should point at a good default on the current machine
13+
#ifdef __AVX2__
14+
native = avx2
15+
#elif defined(__ARM_NEON)
16+
native = neon
17+
#else
18+
// Let us assume that we have an old x64 processor, but one that has SSE (i.e., something
19+
// that came out in the second decade of the XXIst century.
20+
// It would be nicer to check explicitly, but there many not be a good way to do so
21+
// that is cross-platform.
22+
// Under Visual Studio, there is no way to check for SSE4.2 support at compile-time.
23+
native = sse4_2
24+
#endif
1225
};
1326

1427
enum errorValues {

include/simdjson/stage1_find_marks.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ really_inline uint64_t finalize_structurals(
697697
return structurals;
698698
}
699699

700-
template<simdjson::instruction_set T>
700+
template<simdjson::instruction_set T = simdjson::instruction_set::native>
701701
WARN_UNUSED
702702
/*never_inline*/ int find_structural_bits(const uint8_t *buf, size_t len,
703703
ParsedJson &pj) {
@@ -848,7 +848,7 @@ WARN_UNUSED
848848
#endif
849849
}
850850

851-
template<simdjson::instruction_set T>
851+
template<simdjson::instruction_set T = simdjson::instruction_set::native>
852852
WARN_UNUSED
853853
int find_structural_bits(const char *buf, size_t len, ParsedJson &pj) {
854854
return find_structural_bits<T>(reinterpret_cast<const uint8_t *>(buf), len, pj);

src/jsonparser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ ParsedJson build_parsed_json(const uint8_t *buf, size_t len, bool reallocifneede
6363
ParsedJson pj;
6464
bool ok = pj.allocateCapacity(len);
6565
if(ok) {
66-
(void)json_parse(buf, len, pj, reallocifneeded);
66+
json_parse(buf, len, pj, reallocifneeded);
6767
} else {
6868
std::cerr << "failure during memory allocation " << std::endl;
6969
}

tools/jsonstats.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,15 @@ stat_t simdjson_computestats(const padded_string &p) {
115115

116116

117117
int main(int argc, char *argv[]) {
118-
int optind = 1;
119-
if (optind >= argc) {
118+
int myoptind = 1;
119+
if (myoptind >= argc) {
120120
std::cerr << "Reads json, prints stats. " << std::endl;
121121
std::cerr << "Usage: " << argv[0] << " <jsonfile>" << std::endl;
122122
exit(1);
123123
}
124-
const char *filename = argv[optind];
125-
if (optind + 1 < argc) {
126-
std::cerr << "warning: ignoring everything after " << argv[optind + 1] << std::endl;
124+
const char *filename = argv[myoptind];
125+
if (myoptind + 1 < argc) {
126+
std::cerr << "warning: ignoring everything after " << argv[myoptind + 1] << std::endl;
127127
}
128128
padded_string p;
129129
try {

0 commit comments

Comments
 (0)