Commit e82c9590 authored by Matthias Vallentin's avatar Matthias Vallentin

Optimize for large contiguous byte sequences

When processing large amounts of data, it is common to store it as
std::vector<char> or std::vector<uint8_t>. Previously, such types put
heavy stress on the serialization framework, because each character was
processed separatedly. This patch changes this behavior such that the
entire sequence is processed at once.
parent a2418241
......@@ -184,7 +184,9 @@ public:
// Applies this processor as Derived to `xs` in saving mode.
template <class D, class T>
static typename std::enable_if<D::is_saving::value>::type
static typename std::enable_if<
D::is_saving::value && ! detail::is_byte_sequence<T>::value
>::type
apply_sequence(D& self, T& xs) {
auto s = xs.size();
self.begin_sequence(s);
......@@ -196,7 +198,9 @@ public:
// Applies this processor as Derived to `xs` in loading mode.
template <class D, class T>
static typename std::enable_if<! D::is_saving::value>::type
static typename std::enable_if<
! D::is_saving::value && ! detail::is_byte_sequence<T>::value
>::type
apply_sequence(D& self, T& xs) {
size_t num_elements;
self.begin_sequence(num_elements);
......@@ -209,6 +213,31 @@ public:
self.end_sequence();
}
// Optimized saving for contiguous byte sequences.
template <class D, class T>
static typename std::enable_if<
D::is_saving::value && detail::is_byte_sequence<T>::value
>::type
apply_sequence(D& self, T& xs) {
auto s = xs.size();
self.begin_sequence(s);
self.apply_raw(xs.size(), &xs[0]);
self.end_sequence();
}
// Optimized loading for contiguous byte sequences.
template <class D, class T>
static typename std::enable_if<
! D::is_saving::value && detail::is_byte_sequence<T>::value
>::type
apply_sequence(D& self, T& xs) {
size_t num_elements;
self.begin_sequence(num_elements);
xs.resize(num_elements);
self.apply_raw(xs.size(), &xs[0]);
self.end_sequence();
}
/// Applies this processor to a sequence of values.
template <class T>
typename std::enable_if<
......
......@@ -25,6 +25,7 @@
#include <utility>
#include <functional>
#include <type_traits>
#include <vector>
#include "caf/fwd.hpp"
......@@ -209,7 +210,7 @@ public:
std::is_same<bool, result_type>::value;
};
/// Checks wheter `T` has `begin()` and `end()` member
/// Checks whether `T` has `begin()` and `end()` member
/// functions returning forward iterators.
template <class T>
class is_iterable {
......@@ -241,9 +242,22 @@ public:
std::is_same<bool, result_type>::value;
};
template<class T>
template <class T>
constexpr bool is_iterable<T>::value;
/// Checks whether T is a contiguous sequence of byte.
template <class T>
struct is_byte_sequence : std::false_type { };
template <>
struct is_byte_sequence<std::vector<char>> : std::true_type { };
template <>
struct is_byte_sequence<std::vector<unsigned char>> : std::true_type { };
template <>
struct is_byte_sequence<std::string> : std::true_type { };
/// Checks whether `T` is an `std::tuple` or `std::pair`.
template <class T>
struct is_tuple : std::false_type { };
......
......@@ -437,4 +437,18 @@ CAF_TEST(streambuf_serialization) {
CAF_CHECK(data == target);
}
CAF_TEST(byte_sequence_optimization) {
std::vector<char> data(42);
std::fill(data.begin(), data.end(), 'a');
std::vector<char> buf;
stream_serializer<vectorbuf> bs{vectorbuf{buf}};
bs << data;
data.clear();
stream_deserializer<charbuf> bd{charbuf{buf}};
bd >> data;
CAF_CHECK_EQUAL(data.size(), 42u);
CAF_CHECK(std::all_of(data.begin(), data.end(),
[](char c) { return c == 'a'; }));
}
CAF_TEST_FIXTURE_SCOPE_END()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment