#include #include #include #include #include // A buffer used for just counting the number of bytes needed class counting_buffer { public: counting_buffer(std::size_t=0) : total(0) {} void save_binary(const void *address, std::size_t count) { total += count; } std::size_t size() { return total;} private: std::size_t total; }; // A buffer inserting into a vector class vector_buffer { public: vector_buffer(std::size_t s=0) { reserve(s); } void save_binary(const void *address, std::size_t count) { buffer.insert(buffer.end(),static_cast(address), static_cast(address)+count); } std::size_t size() { return buffer.size();} void reserve(std::size_t n) { buffer.reserve(n);} private: std::vector buffer; }; // A buffer for writing using memcpy class fixed_array_buffer { public: fixed_array_buffer(std::size_t s=0) : buffer(new char[s]) , ptr(buffer) { } ~fixed_array_buffer() { delete[] buffer; } std::size_t size() { return ptr-buffer;} void reserve(std::size_t n) { delete[] buffer; buffer = new char[n]; ptr = buffer; } void save_binary(const void *address, std::size_t count) { std::memcpy(ptr,address,count); ptr += count; } private: char *buffer; char *ptr; }; // The class impolementing saving of primitive types and arrays // templated on and derived from one of the buffers above template class buffered_oprimitive : public Buffer { public: buffered_oprimitive(std::size_t n=0) : Buffer(n) {} // default saving of primitives. template void save(const T & t) { this->save_binary(&t, sizeof(T)); } // default saving of arrays. template void save_array(const T * p, std::size_t n) { this->save_binary(p, n*sizeof(T)); } void save(const std::string &s) {} }; // the archive class template class buffered_oarchive : public buffered_oprimitive, public boost::archive::basic_binary_oarchive > { public: buffered_oarchive(std::size_t buffersize=0, unsigned int flags=0) : buffered_oprimitive(buffersize) , boost::archive::basic_binary_oarchive >(flags) {} }; // Serialize the vector using Boost.serialization template void serialize(Archive& ar, const std::vector& v) { ar << v; } // Serialize the vector using direct calls to save from a loop template void serialize_save(Archive& ar, const std::vector& v) { for (typename std::vector::const_iterator it = v.begin(); it !=v.end(); ++it) ar.save(*it); } // Serialize the vector using a call to save_array template void serialize_save_array(Archive& ar, const std::vector& v) { ar.save_array(&v[0],v.size()); } // Here we do the actual timings template void time_it(const std::vector& v, bool count_it) { { buffered_oarchive ar; // the archive buffered_oarchive count_ar; // te counting archive boost::timer time; // if we want to preallocate by counting if (count_it) { // count the number of bytes if needed by using a counting buffer serialize(count_ar,v); ar.reserve(count_ar.size()); // reserve enough memory } // serialize serialize(ar,v); std::cout << "Time using serialization library: " << time.elapsed() << std::endl; } { buffered_oarchive ar; buffered_oarchive count_ar; boost::timer time; if (count_it) { serialize_save(count_ar,v); ar.reserve(count_ar.size()); } serialize_save(ar,v); std::cout << "Time using direct calls to save in a loop: " << time.elapsed() << std::endl; } { buffered_oarchive ar; buffered_oarchive count_ar; boost::timer time; if (count_it) { serialize_save_array(count_ar,v); ar.reserve(count_ar.size()); } serialize_save_array(ar,v); std::cout << "Time using direct call to save_array: " << time.elapsed() << std::endl; } std::cout << "\n\n"; } template void timings(std::size_t number_of_elements) { const std::vector v(number_of_elements); std::cout << "vector buffer non-reserved:\n"; time_it(v,false); std::cout << "vector buffer reserved:\n"; time_it(v,true); std::cout << "fixed array buffer:\n"; time_it(v,true); } int main() { std::size_t number_of_elements = 100000000; std::cout << "Timings for vector:\n"; timings(number_of_elements); std::cout << "\n\n\n\nTimings for vector:\n"; timings(number_of_elements/sizeof(short)); std::cout << "\n\n\n\nTimings for vector:\n"; timings(number_of_elements/sizeof(int)); std::cout << "\n\n\n\nTimings for vector:\n"; timings(number_of_elements/sizeof(double)); }