Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/linux.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ jobs:
echo '## Benchmarks across different formats' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=canada_read >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=parser_inlining >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=canada_write >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=licenses_read >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=licenses_write >> $GITHUB_STEP_SUMMARY
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/macos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ jobs:
echo '## Benchmarks across different formats' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=canada_read >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=parser_inlining >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=canada_write >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=licenses_read >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=licenses_write >> $GITHUB_STEP_SUMMARY
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/windows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jobs:
echo '## Benchmarks across different formats' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=canada_read >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=parser_inlining >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=canada_write >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=licenses_read >> $GITHUB_STEP_SUMMARY
./build/benchmarks/all/reflect-cpp-all-format-benchmarks --benchmark_filter=licenses_write >> $GITHUB_STEP_SUMMARY
Expand Down
76 changes: 76 additions & 0 deletions benchmarks/all/parser_inlining.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#ifndef BENCHMARK_PARSER_INLINING_HPP_
#define BENCHMARK_PARSER_INLINING_HPP_
#include <benchmark/benchmark.h>

#include <cstdint>
#include <vector>
namespace parser_inlining {
struct Record2 {
float field0 = 0;
float field1 = 1;
bool operator==(const Record2&) const = default;
};
struct Record16 {
float field0 = 0;
float field1 = 1;
float field2 = 2;
float field3 = 3;
float field4 = 4;
float field5 = 5;
float field6 = 6;
float field7 = 7;
float field8 = 8;
float field9 = 9;
float field10 = 10;
float field11 = 11;
float field12 = 12;
float field13 = 13;
float field14 = 14;
float field15 = 15;
bool operator==(const Record16&) const = default;
};
template <class Record>
struct Data {
std::vector<Record> records;
bool operator==(const Data&) const = default;
};
template <class Record>
auto make_data(std::size_t size) {
Data<Record> data;
data.records.resize(size);
for (std::size_t i = 0; i < size; ++i) {
data.records[i].field0 = static_cast<float>(i) * 0.5f;
data.records[i].field1 = -static_cast<float>(i) * 0.25f;
}
return data;
}
template <class Record, class Write, class Read>
void run(benchmark::State& state, Write write, Read read) {
const auto input = make_data<Record>(state.range(0));
const auto bytes = write(input);
{
const auto result = read(bytes);
if (!result) {
state.SkipWithError(result.error().what());
return;
}
if (*result != input) {
state.SkipWithError("Fields changed during round trip");
return;
}
}
for (auto _ : state) {
auto result = read(bytes);
if (!result) {
state.SkipWithError(result.error().what());
break;
}
benchmark::DoNotOptimize(result);
}
state.SetItemsProcessed(state.iterations() * state.range(0));
state.SetBytesProcessed(state.iterations() *
static_cast<std::int64_t>(bytes.size()));
state.counters["serialized_bytes"] = static_cast<double>(bytes.size());
}
} // namespace parser_inlining
#endif
19 changes: 19 additions & 0 deletions benchmarks/all/parser_inlining_cereal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <rfl/cereal.hpp>

#include "parser_inlining.hpp"
namespace parser_inlining {
template <class Record>
void BM_parser_inlining_cereal(benchmark::State& state) {
run<Record>(
state, [&](const auto& input) { return rfl::cereal::write(input); },
[&](const auto& bytes) {
return rfl::cereal::read<Data<Record>>(bytes);
});
}
BENCHMARK_TEMPLATE(BM_parser_inlining_cereal, Record2)
->Arg(100000)
->Unit(benchmark::kMillisecond);
BENCHMARK_TEMPLATE(BM_parser_inlining_cereal, Record16)
->Arg(100000)
->Unit(benchmark::kMillisecond);
} // namespace parser_inlining
17 changes: 17 additions & 0 deletions benchmarks/all/parser_inlining_json.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <rfl/json.hpp>

#include "parser_inlining.hpp"
namespace parser_inlining {
template <class Record>
void BM_parser_inlining_json(benchmark::State& state) {
run<Record>(
state, [&](const auto& input) { return rfl::json::write(input); },
[&](const auto& bytes) { return rfl::json::read<Data<Record>>(bytes); });
}
BENCHMARK_TEMPLATE(BM_parser_inlining_json, Record2)
->Arg(100000)
->Unit(benchmark::kMillisecond);
BENCHMARK_TEMPLATE(BM_parser_inlining_json, Record16)
->Arg(100000)
->Unit(benchmark::kMillisecond);
} // namespace parser_inlining
19 changes: 19 additions & 0 deletions benchmarks/all/parser_inlining_msgpack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <rfl/msgpack.hpp>

#include "parser_inlining.hpp"
namespace parser_inlining {
template <class Record>
void BM_parser_inlining_msgpack(benchmark::State& state) {
run<Record>(
state, [&](const auto& input) { return rfl::msgpack::write(input); },
[&](const auto& bytes) {
return rfl::msgpack::read<Data<Record>>(bytes);
});
}
BENCHMARK_TEMPLATE(BM_parser_inlining_msgpack, Record2)
->Arg(100000)
->Unit(benchmark::kMillisecond);
BENCHMARK_TEMPLATE(BM_parser_inlining_msgpack, Record16)
->Arg(100000)
->Unit(benchmark::kMillisecond);
} // namespace parser_inlining
9 changes: 6 additions & 3 deletions include/rfl/cereal/Reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "../Result.hpp"
#include "../Vectorstring.hpp"
#include "../always_false.hpp"
#include "../internal/always_inline.hpp"
#include "../internal/is_literal.hpp"
#include "../parsing/schemaful/IsSchemafulReader.hpp"

Expand Down Expand Up @@ -63,7 +64,8 @@ struct Reader {
/// @param _var The Cereal archive variable containing the value
/// @return A Result containing the converted value or an error
template <class T>
rfl::Result<T> to_basic_type(const InputVarType& _var) const noexcept {
RFL_ALWAYS_INLINE rfl::Result<T> to_basic_type(
const InputVarType& _var) const noexcept {
try {
if constexpr (internal::is_literal_v<T>) {
std::string str;
Expand Down Expand Up @@ -168,8 +170,9 @@ struct Reader {
/// @param _obj The Cereal object structure
/// @return std::nullopt on success, or an Error if reading fails
template <class ObjectReader>
std::optional<Error> read_object(const ObjectReader& _object_reader,
const InputObjectType& _obj) const noexcept {
RFL_ALWAYS_INLINE std::optional<Error> read_object(
const ObjectReader& _object_reader,
const InputObjectType& _obj) const noexcept {
try {
for (size_t i = 0; i < ObjectReader::size(); ++i) {
_object_reader.read(i, InputVarType{_obj.archive_});
Expand Down
12 changes: 12 additions & 0 deletions include/rfl/internal/always_inline.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef RFL_INTERNAL_ALWAYS_INLINE_HPP_
#define RFL_INTERNAL_ALWAYS_INLINE_HPP_

#if defined(_MSC_VER)
#define RFL_ALWAYS_INLINE __forceinline
#elif defined(__GNUC__) || defined(__clang__)
#define RFL_ALWAYS_INLINE inline __attribute__((always_inline))
#else
#define RFL_ALWAYS_INLINE inline
#endif

#endif
3 changes: 2 additions & 1 deletion include/rfl/internal/cpp20/Result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <type_traits>

#include "../Error.hpp"
#include "../always_inline.hpp"

namespace rfl::internal::cpp20 {

Expand Down Expand Up @@ -331,7 +332,7 @@ class Result {
/// @note This overload is for rvalue references (&&), so the contained value
/// is moved.
template <class F>
auto transform(const F& _f) && {
RFL_ALWAYS_INLINE auto transform(const F& _f) && {
/// Result_U is expected to be of type Result<U>.
using U = std::invoke_result_t<F, T>;
if (success_) {
Expand Down
22 changes: 12 additions & 10 deletions include/rfl/parsing/NamedTupleParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "../NamedTuple.hpp"
#include "../Result.hpp"
#include "../internal/always_inline.hpp"
#include "../internal/default_if_missing_v.hpp"
#include "../internal/has_default_val_v.hpp"
#include "../internal/has_reflection_method_v.hpp"
Expand Down Expand Up @@ -145,10 +146,10 @@ struct NamedTupleParser {
* @return A pair containing a boolean array indicating which fields were
* found and an optional error.
*/
static std::pair<std::array<bool, NamedTupleType::size()>,
std::optional<Error>>
read_view(const R& _r, const InputVarType& _var,
NamedTuple<FieldTypes...>* _view) noexcept {
static RFL_ALWAYS_INLINE
std::pair<std::array<bool, NamedTupleType::size()>, std::optional<Error>>
read_view(const R& _r, const InputVarType& _var,
NamedTuple<FieldTypes...>* _view) noexcept {
if constexpr (_no_field_names) {
auto arr = _r.to_array(_var);
if (!arr) [[unlikely]] {
Expand Down Expand Up @@ -321,7 +322,7 @@ struct NamedTupleParser {

/// Generates error messages for when fields are missing.
template <int _i>
static void handle_one_missing_field(
static RFL_ALWAYS_INLINE void handle_one_missing_field(
const std::array<bool, size_>& _found, const NamedTupleType& _view,
std::array<bool, size_>* _set,
std::vector<std::string>* _errors) noexcept {
Expand Down Expand Up @@ -357,7 +358,7 @@ struct NamedTupleParser {

/// Generates error messages for when fields are missing.
template <int... _is>
static void handle_missing_fields(
static RFL_ALWAYS_INLINE void handle_missing_fields(
const std::array<bool, size_>& _found, const NamedTupleType& _view,
std::array<bool, size_>* _set, std::vector<std::string>* _errors,
std::integer_sequence<int, _is...>) noexcept {
Expand All @@ -373,10 +374,11 @@ struct NamedTupleParser {
}
}

static std::pair<std::array<bool, NamedTupleType::size()>,
std::optional<Error>>
read_object_or_array(const R& _r, const InputObjectOrArrayType& _obj_or_arr,
NamedTupleType* _view) noexcept {
static RFL_ALWAYS_INLINE
std::pair<std::array<bool, NamedTupleType::size()>, std::optional<Error>>
read_object_or_array(const R& _r,
const InputObjectOrArrayType& _obj_or_arr,
NamedTupleType* _view) noexcept {
auto found = std::array<bool, NamedTupleType::size()>();
found.fill(false);
auto set = std::array<bool, NamedTupleType::size()>();
Expand Down
9 changes: 6 additions & 3 deletions include/rfl/parsing/Parser_default.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "../Result.hpp"
#include "../always_false.hpp"
#include "../internal/HasFromReflectionMethod.hpp"
#include "../internal/always_inline.hpp"
#include "../internal/default_if_missing_v.hpp"
#include "../internal/has_default_val_v.hpp"
#include "../internal/has_reflection_method_v.hpp"
Expand Down Expand Up @@ -87,7 +88,7 @@ struct Parser {
* @param _var The input variable to read from.
* @return A Result containing the parsed value or an error.
*/
static auto read(const R& _r, const InputVarType& _var) {
static RFL_ALWAYS_INLINE auto read(const R& _r, const InputVarType& _var) {
if constexpr (internal::is_basic_type_v<T>) {
return ParserBasicType<R, W, T, ProcessorsType>::read(_r, _var);

Expand Down Expand Up @@ -686,10 +687,12 @@ struct Parser {
/// 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) {
static RFL_ALWAYS_INLINE Result<T> read_struct(const R& _r,
const InputVarType& _var) {
alignas(T) unsigned char buf[sizeof(T)]{};
auto ptr = internal::ptr_cast<T*>(&buf);
auto view = ProcessorsType::template process<T>(to_view(*ptr));
auto raw_view = to_view(*ptr);
auto view = ProcessorsType::template process<T>(std::move(raw_view));
using ViewType = std::remove_cvref_t<decltype(view)>;
const auto [set, err] =
Parser<R, W, ViewType, ProcessorsType>::read_view(_r, _var, &view);
Expand Down
3 changes: 2 additions & 1 deletion include/rfl/parsing/VectorReader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <type_traits>

#include "../Result.hpp"
#include "../internal/always_inline.hpp"
#include "Parser_base.hpp"
#include "is_inplace_vector.hpp"
#include "is_map_like.hpp"
Expand Down Expand Up @@ -36,7 +37,7 @@ class VectorReader {
* @param _var The input variable to read from.
* @return An optional error.
*/
std::optional<Error> read(const InputVarType& _var) const {
RFL_ALWAYS_INLINE std::optional<Error> read(const InputVarType& _var) const {
const auto parse = [this](const InputVarType& _var) {
if constexpr (is_map_like_v<VecType>) {
return get_pair(_var);
Expand Down
10 changes: 5 additions & 5 deletions include/rfl/parsing/ViewReader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <vector>

#include "../Tuple.hpp"
#include "../internal/always_inline.hpp"
#include "../internal/is_array.hpp"
#include "../internal/no_extra_fields_v.hpp"
#include "Parser_base.hpp"
Expand Down Expand Up @@ -81,11 +82,10 @@ class ViewReader {
}

template <int i>
static void assign_if_field_matches(const R& _r,
const auto _current_name_or_index,
const auto& _var, auto* _view,
auto* _errors, auto* _found, auto* _set,
bool* _already_assigned) {
static RFL_ALWAYS_INLINE void assign_if_field_matches(
const R& _r, const auto _current_name_or_index, const auto& _var,
auto* _view, auto* _errors, auto* _found, auto* _set,
bool* _already_assigned) {
using FieldType = tuple_element_t<i, typename ViewType::Fields>;
using OriginalType = typename FieldType::Type;
using T =
Expand Down
Loading