Try simdjson: bloody hell, that's fast!!

Signed-off-by: Adrian Conlon <adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2021-10-11 22:09:03 +01:00
parent b5074ac48c
commit 91221aa975
12 changed files with 42300 additions and 1 deletions

View File

@ -163,6 +163,12 @@
<ItemGroup>
<ClCompile Include="json_t.cpp" />
<ClCompile Include="opcode_test_suite_t.cpp" />
<ClCompile Include="simdjson\simdjson.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="state_t.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
@ -178,6 +184,7 @@
<ClInclude Include="json_t.h" />
<ClInclude Include="nlohmann\json.hpp" />
<ClInclude Include="opcode_test_suite_t.h" />
<ClInclude Include="simdjson\simdjson.h" />
<ClInclude Include="state_t.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="TestRunner.h" />

View File

@ -12,6 +12,9 @@
<Filter Include="Header Files\nlohmann">
<UniqueIdentifier>{1b676a2e-dff7-46aa-b021-f4319b0419d7}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\simdjson">
<UniqueIdentifier>{92d132eb-117f-4f61-bad7-de75aa3cb6cf}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="tests.cpp">
@ -35,6 +38,9 @@
<ClCompile Include="TestRunner.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="simdjson\simdjson.cpp">
<Filter>Header Files\simdjson</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@ -58,6 +64,9 @@
<ClInclude Include="nlohmann\json.hpp">
<Filter>Header Files\nlohmann</Filter>
</ClInclude>
<ClInclude Include="simdjson\simdjson.h">
<Filter>Header Files\simdjson</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@ -9,6 +9,9 @@
#ifdef USE_JSONCPP_JSON
std::unique_ptr<Json::CharReader> opcode_test_suite_t::m_reader;
#endif
#ifdef USE_SIMDJSON_JSON
std::unique_ptr<simdjson::dom::parser> opcode_test_suite_t::m_parser;
#endif
std::string opcode_test_suite_t::read(std::string path) {
std::ifstream file(path, std::ios::in | std::ios::binary);
@ -57,3 +60,14 @@ void opcode_test_suite_t::load() {
}
#endif
#ifdef USE_SIMDJSON_JSON
void opcode_test_suite_t::load() {
if (m_parser == nullptr)
m_parser = std::make_unique<simdjson::dom::parser>();
const auto contents = read(path());
m_raw = m_parser->parse(contents);
}
#endif

View File

@ -15,11 +15,18 @@
# include <json/json.h>
#endif
#ifdef USE_SIMDJSON_JSON
# include "simdjson/simdjson.h"
#endif
class opcode_test_suite_t final {
private:
#ifdef USE_JSONCPP_JSON
static std::unique_ptr<Json::CharReader> m_reader;
#endif
#ifdef USE_SIMDJSON_JSON
static std::unique_ptr<simdjson::dom::parser> m_parser;
#endif
[[nodiscard]] static std::string read(std::string path);
@ -33,12 +40,20 @@ private:
#ifdef USE_JSONCPP_JSON
Json::Value m_raw;
#endif
#ifdef USE_SIMDJSON_JSON
simdjson::dom::element m_raw;
#endif
public:
opcode_test_suite_t(std::string path);
[[nodiscard]] constexpr const auto& path() const noexcept { return m_path; }
#ifdef JSON_PREFER_PASS_BY_VALUE
[[nodiscard]] const auto raw() const noexcept { return m_raw; }
#else
[[nodiscard]] constexpr const auto& raw() const noexcept { return m_raw; }
#endif
#ifdef USE_BOOST_JSON
[[nodiscard]] const boost::json::array& get_array() const noexcept;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -110,3 +110,38 @@ void state_t::initialise(const Json::Value& serialised) {
}
#endif
#ifdef USE_SIMDJSON_JSON
state_t::state_t(const simdjson::dom::element serialised) {
assert(serialised.is_object());
initialise(serialised);
assert(initialised());
}
void state_t::initialise(const simdjson::dom::element serialised) {
assert(!initialised());
m_pc = (uint64_t)serialised["pc"];
m_s = (uint64_t)serialised["s"];
m_a = (uint64_t)serialised["a"];
m_x = (uint64_t)serialised["x"];
m_y = (uint64_t)serialised["y"];
m_p = (uint64_t)serialised["p"];
const auto ram_entries = serialised["ram"];
assert(ram_entries.is_array());
for (const auto ram_entry : ram_entries) {
assert(ram_entry.is_array());
const auto ram_entry_array = ram_entry.get_array();
assert(ram_entry_array.size() == 2);
const auto address = (uint64_t)ram_entry_array.at(0);
const auto value = (uint64_t)ram_entry_array.at(1);
m_ram[address] = value;
}
m_initialised = true;
}
#endif

View File

@ -15,6 +15,10 @@
# include <json/json.h>
#endif
#ifdef USE_SIMDJSON_JSON
# include "simdjson/simdjson.h"
#endif
#include "json_t.h"
class state_t final : public json_t {
@ -43,6 +47,10 @@ private:
void initialise(const Json::Value& serialised);
#endif
#ifdef USE_SIMDJSON_JSON
void initialise(simdjson::dom::element serialised);
#endif
public:
state_t();
@ -59,6 +67,10 @@ public:
state_t(const Json::Value& serialised);
#endif
#ifdef USE_SIMDJSON_JSON
state_t(simdjson::dom::element serialised);
#endif
[[nodiscard]] constexpr auto pc() const noexcept { return m_pc; }
[[nodiscard]] constexpr auto s() const noexcept { return m_s; }
[[nodiscard]] constexpr auto a() const noexcept { return m_a; }

View File

@ -13,9 +13,10 @@
//#define TEST_JSON_PERFORMANCE
#define USE_BOOST_JSON // 32 seconds
//#define USE_BOOST_JSON // 32 seconds
//#define USE_NLOHMANN_JSON // 58 seconds
//#define USE_JSONCPP_JSON // 88 seconds
#define USE_SIMDJSON_JSON // 15 seconds
#ifdef USE_BOOST_JSON
# include <boost/json.hpp>
@ -28,3 +29,8 @@
#ifdef USE_JSONCPP_JSON
# include <json/json.h>
#endif
#ifdef USE_SIMDJSON_JSON
# define JSON_PREFER_PASS_BY_VALUE
# include "simdjson/simdjson.h"
#endif

View File

@ -104,3 +104,31 @@ void test_t::initialise(const Json::Value& serialised) {
}
#endif
#ifdef USE_SIMDJSON_JSON
test_t::test_t(const simdjson::dom::element serialised) {
assert(serialised.is_object());
initialise(serialised);
}
void test_t::initialise(const simdjson::dom::element serialised) {
m_name = serialised["name"];
m_initial_state = state_t(serialised["initial"]);
m_final_state = state_t(serialised["final"]);
const auto cycles_array = serialised["cycles"].get_array();
m_cycles.reserve(cycles_array.size());
for (const auto cycles_entry : cycles_array) {
const auto cycle_array = cycles_entry.get_array();
assert(cycle_array.size() == 3);
const auto address = (uint64_t)cycle_array.at(0);
const auto contents = (uint64_t)cycle_array.at(1);
const auto action = to_action((std::string)cycle_array.at(2));
m_cycles.push_back({ address, contents, action });
}
}
#endif

View File

@ -17,6 +17,10 @@
# include <json/json.h>
#endif
#ifdef USE_SIMDJSON_JSON
# include "simdjson/simdjson.h"
#endif
#include "state_t.h"
#include "json_t.h"
@ -48,6 +52,10 @@ private:
void initialise(const Json::Value& serialised);
#endif
#ifdef USE_SIMDJSON_JSON
void initialise(simdjson::dom::element serialised);
#endif
public:
#ifdef USE_BOOST_JSON
@ -63,6 +71,10 @@ public:
test_t(const Json::Value& serialised);
#endif
#ifdef USE_SIMDJSON_JSON
test_t(simdjson::dom::element serialised);
#endif
[[nodiscard]] constexpr const auto& name() const noexcept { return m_name; }
[[nodiscard]] constexpr const auto& initial_state() const noexcept { return m_initial_state; }
[[nodiscard]] constexpr const auto& final_state() const noexcept { return m_final_state; }

View File

@ -33,6 +33,10 @@ int main() {
#ifdef USE_JSONCPP_JSON
const auto& opcode_test_array = opcode.raw();
#endif
#ifdef USE_SIMDJSON_JSON
assert(opcode.raw().is_array());
const auto& opcode_test_array = opcode.raw().get_array();
#endif
bool opcode_bad = false;
for (const auto& opcode_test_element : opcode_test_array) {