Skip to content

Instantly share code, notes, and snippets.

@yuvalif
Last active November 8, 2018 20:59
Show Gist options
  • Save yuvalif/aa3691c62959b1a9d7dbf7adceac0c78 to your computer and use it in GitHub Desktop.
Save yuvalif/aa3691c62959b1a9d7dbf7adceac0c78 to your computer and use it in GitHub Desktop.
boost::circular_buffer serialization benchmark
// boost::circular_buffer serialization
// using: g++ (GCC) 8.2.1 20181011 (Red Hat 8.2.1-4)
//
// g++ -Wall -O2 -o cb_serialization cb_serialization.cpp -lboost_serialization
// g++ -Wall -O2 -DUSE_BINARY -o cb_serialization cb_serialization.cpp -lboost_serialization
//
//
#include <boost/circular_buffer.hpp>
#include <boost/serialization/split_free.hpp>
#include <sstream>
#include <iostream>
#include <cstdlib>
#include <random>
#include <chrono>
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
// implement serialization for boost::circular_buffer
namespace boost { namespace serialization {
template <class Archive, class T>
void save(Archive& ar, const circular_buffer<T>& b, const unsigned int /* version */)
{
typename circular_buffer<T>::size_type size = b.size();
ar << b.capacity();
ar << size;
#ifdef USE_BINARY
const typename circular_buffer<T>::const_array_range one = b.array_one();
const typename circular_buffer<T>::const_array_range two = b.array_two();
ar.save_binary(one.first, one.second*sizeof(T));
ar.save_binary(two.first, two.second*sizeof(T));
#else
while (size > 0) {
--size;
ar << b[size];
}
#endif
}
template <class Archive, class T>
void load(Archive& ar, circular_buffer<T>& b, const unsigned int /* version */)
{
typename circular_buffer<T>::capacity_type capacity;
typename circular_buffer<T>::size_type size;
ar >> capacity;
b.set_capacity(capacity);
ar >> size;
b.clear();
#ifdef USE_BINARY
const typename circular_buffer<T>::pointer buff = new T[size*sizeof(T)];
ar.load_binary(buff, size*sizeof(T));
b.insert(b.begin(), buff, buff+size);
delete[] buff;
#else
T elem;
while (size > 0) {
--size;
ar >> elem;
b.push_front(elem);
}
#endif
}
template<class Archive, class T>
inline void serialize(Archive & ar, circular_buffer<T>& b, const unsigned int version)
{
split_free(ar, b, version);
}
} } // end namespace boost::serialization
int main(int argc, char** argv)
{
if (argc != 2) {
std::cout << "usage: " << argv[0] << " <buffer size>" << std::endl;
return 1;
}
const auto buffer_size = std::atoi(argv[1]);
if (buffer_size <= 0) {
std::cout << "invalid buffer size" << std::endl;
return 1;
}
// Seed with a real random value, if available
std::random_device r;
// Choose a randomly whether to push or pop
std::default_random_engine e(r());
std::uniform_int_distribution<int> uniform_dist(1, 10);
boost::circular_buffer<double> cb1(buffer_size);
for (auto i = 0; i < buffer_size; ++i) {
auto draw = uniform_dist(e);
if (draw < 8)
cb1.push_back(i);
else
cb1.pop_front();
}
#ifdef USE_BINARY
std::cout << "binary serialization..." << std::endl;
#else
std::cout << "text serialization..." << std::endl;
#endif
{
// memory storage - low overhead
std::stringstream ss;
boost::archive::text_oarchive oa(ss);
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
boost::serialization::serialize(oa, cb1, 0);
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "low overhead serialization for buffer: " << buffer_size << " took: " <<
std::chrono::duration_cast<std::chrono::microseconds> (end - begin).count() << " usec" << std::endl;
boost::circular_buffer<double> cb2(0);
boost::archive::text_iarchive ia(ss);
begin = std::chrono::steady_clock::now();
boost::serialization::serialize(ia, cb2, 0);
end = std::chrono::steady_clock::now();
std::cout << "low overhead deserialization for buffer: " << buffer_size << " took: " <<
std::chrono::duration_cast<std::chrono::microseconds> (end - begin).count() << " usec" << std::endl;
if (cb1 != cb2) {
std::cout << "circular buffer did not recover correctly" << std::endl;
}
}
{
// file storage - high overhead
{
std::ofstream ofs("cb.tmp");
boost::archive::text_oarchive oa(ofs);
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
boost::serialization::serialize(oa, cb1, 0);
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "high overhead serialization for buffer: " << buffer_size << " took: " <<
std::chrono::duration_cast<std::chrono::microseconds> (end - begin).count() << " usec" << std::endl;
}
{
std::ifstream ifs("cb.tmp");
boost::circular_buffer<double> cb2(0);
boost::archive::text_iarchive ia(ifs);
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
boost::serialization::serialize(ia, cb2, 0);
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "high overhead deserialization for buffer: " << buffer_size << " took: " <<
std::chrono::duration_cast<std::chrono::microseconds> (end - begin).count() << " usec" << std::endl;
if (cb1 != cb2) {
std::cout << "circular buffer did not recover correctly" << std::endl;
}
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment