Skip to content

Commit

Permalink
Trying very brute optimization technique
Browse files Browse the repository at this point in the history
  • Loading branch information
liuzicheng1987 committed May 28, 2024
1 parent c4a9679 commit 2088598
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 70 deletions.
2 changes: 1 addition & 1 deletion benchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O2")
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std:c++20")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -Wall -O2 -s")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20 -Wall -O2")
endif()

add_subdirectory(json)
20 changes: 2 additions & 18 deletions benchmarks/json/simple_read.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,6 @@ struct Person {
std::string age;
};

struct View {
std::string *ptr0;
std::string *ptr1;
std::string *ptr2;
};

template <int _i>
inline auto get(auto &_view) {
if constexpr (_i == 0) {
return _view.ptr0;
} else if constexpr (_i == 1) {
return _view.ptr1;
} else if constexpr (_i == 2) {
return _view.ptr2;
}
};

static rfl::Result<Person> read_using_yyjson_comparison() {
yyjson_doc *doc = yyjson_read(json_string.c_str(), json_string.size(), 0);
if (!doc) {
Expand All @@ -47,7 +30,7 @@ static rfl::Result<Person> read_using_yyjson_comparison() {

alignas(Person) unsigned char buf[sizeof(Person)];
auto ptr = reinterpret_cast<Person *>(buf);
auto view = rfl::to_view(*ptr);
auto view = rfl::Processors<>::template process<Person>(rfl::to_view(*ptr));

const auto reader = rfl::json::Reader();

Expand All @@ -58,6 +41,7 @@ static rfl::Result<Person> read_using_yyjson_comparison() {
&view);

if (err) {
yyjson_doc_free(doc);
return *err;
}

Expand Down
21 changes: 18 additions & 3 deletions include/rfl/json/read.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,24 @@ Result<internal::wrap_in_rfl_array_t<T>> read(const std::string& _json_str) {
}
yyjson_val* root = yyjson_doc_get_root(doc);
const auto r = Reader();
auto res = Parser<T, Processors<Ps...>>::read(r, InputVarType(root));
yyjson_doc_free(doc);
return res;
if constexpr (std::is_class_v<T> && std::is_aggregate_v<T>) {
using ProcessorsType = Processors<Ps...>;
alignas(T) unsigned char buf[sizeof(T)];
auto ptr = reinterpret_cast<T*>(buf);
auto view = ProcessorsType::template process<T>(to_view(*ptr));
using ViewType = std::remove_cvref_t<decltype(view)>;
const auto err = Parser<ViewType, ProcessorsType>::read_view(
r, InputVarType(root), &view);
yyjson_doc_free(doc);
if (err) [[unlikely]] {
return *err;
}
return std::move(*ptr);
} else {
auto res = Parser<T, Processors<Ps...>>::read(r, InputVarType(root));
yyjson_doc_free(doc);
return res;
}
}

/// Parses an object from a stringstream.
Expand Down
10 changes: 5 additions & 5 deletions include/rfl/parsing/NamedTupleParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ struct NamedTupleParser {
using ViewType = std::remove_cvref_t<decltype(view)>;
const auto err =
Parser<R, W, ViewType, ProcessorsType>::read_view(_r, _var, &view);
if (err) {
if (err) [[unlikely]] {
return *err;
}
return *ptr;
Expand All @@ -70,11 +70,11 @@ struct NamedTupleParser {
static std::optional<Error> read_view(
const R& _r, const InputVarType& _var,
NamedTuple<FieldTypes...>* _view) noexcept {
const auto obj = _r.to_object(_var);
if (obj) {
return read_object(_r, *obj, _view);
auto obj = _r.to_object(_var);
if (!obj) [[unlikely]] {
return obj.error();
}
return obj.error();
return read_object(_r, *obj, _view);
}

/// For writing, we do not need to make the distinction between
Expand Down
21 changes: 19 additions & 2 deletions include/rfl/parsing/Parser_default.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
#include "../internal/is_validator.hpp"
#include "../internal/processed_t.hpp"
#include "../internal/to_ptr_named_tuple.hpp"
#include "../to_view.hpp"
#include "../type_name_t.hpp"
#include "AreReaderAndWriter.hpp"
#include "Parent.hpp"
#include "Parser_base.hpp"
#include "StructReader.hpp"
#include "is_tagged_union_wrapper.hpp"
#include "schema/Type.hpp"

Expand Down Expand Up @@ -55,7 +55,7 @@ struct Parser {
return Parser<R, W, ReflectionType, ProcessorsType>::read(_r, _var)
.and_then(wrap_in_t);
} else if constexpr (std::is_class_v<T> && std::is_aggregate_v<T>) {
return StructReader<R, W, T, ProcessorsType>::read(_r, _var);
return read_struct(_r, _var);
} else if constexpr (std::is_enum_v<T>) {
using StringConverter = internal::enums::StringConverter<T>;
return _r.template to_basic_type<std::string>(_var).and_then(
Expand Down Expand Up @@ -211,6 +211,23 @@ struct Parser {
}
}

/// The way this works is that we allocate space on the stack in this size of
/// the struct in which we then write the individual fields using
/// views and placement new. This is how we deal with the fact that some
/// fields might not be default-constructible.
static Result<T> read_struct(const R& _r, const InputVarType& _var) {
alignas(T) unsigned char buf[sizeof(T)];
auto ptr = reinterpret_cast<T*>(buf);
auto view = ProcessorsType::template process<T>(to_view(*ptr));
using ViewType = std::remove_cvref_t<decltype(view)>;
const auto err =
Parser<R, W, ViewType, ProcessorsType>::read_view(_r, _var, &view);
if (err) [[unlikely]] {
return *err;
}
return std::move(*ptr);
}

static std::string replace_non_alphanumeric(std::string _str) {
for (auto& ch : _str) {
ch = std::isalnum(ch) ? ch : '_';
Expand Down
41 changes: 0 additions & 41 deletions include/rfl/parsing/StructReader.hpp

This file was deleted.

0 comments on commit 2088598

Please sign in to comment.