#include #include #include #include #include #include #include using namespace std; typedef unsigned char byte; namespace io = boost::iostreams; typedef std::vector buffer_type; typedef io::stream< io::back_insert_device > my_ostream; struct Buffer { Buffer(unsigned Size) : BufBegin(new byte[Size]), BufPtr(BufBegin), BufEnd(BufBegin+Size) {} void Reset() { BufPtr = BufBegin; } // Write Size bytes to the buffer void Write(byte const* Data, unsigned Size); void WriteDouble(double const* Data); // in a real situation, this would do something sensible void Overflow() { abort(); } byte* BufBegin; byte* BufPtr; byte* BufEnd; }; inline void Buffer::Write(byte const* Data, unsigned Size) { if (BufEnd-BufPtr < Size) this->Overflow(); memcpy(BufPtr, Data, Size); //std::copy(Data, Data+Size, BufPtr); BufPtr += Size; } inline void Buffer::WriteDouble(double const* Data) { if (BufEnd-BufPtr < sizeof(double)) this->Overflow(); *(double*)BufPtr = *Data; BufPtr += sizeof(double); } byte live_code; double test_loop_io(size_t Repeat, size_t n) { std::vector data(n, 1.0); // make a buffer large enough that it won't overflow buffer_type buf; buf.reserve(n*sizeof(double)); my_ostream OutStream(buf); // warm up the cache, if necessary for (size_t i = 0; i < n; ++i) { OutStream.write((byte*)&data[i], sizeof(double)); } buf.clear(); boost::timer time; for (size_t rep = 0; rep < Repeat; ++rep) { for (size_t i = 0; i < n; ++i) { OutStream.write((byte*)&data[i], sizeof(double)); } buf.clear(); } live_code = buf[1]; return time.elapsed(); } double test_loop(size_t Repeat, size_t n) { std::vector data(n, 1.0); // make a buffer large enough that it won't overflow Buffer buf(n * sizeof(double)); // warm up the cache, if necessary for (size_t i = 0; i < n; ++i) { buf.Write((byte*)&data[i], sizeof(double)); } buf.Reset(); boost::timer time; for (size_t rep = 0; rep < Repeat; ++rep) { for (size_t i = 0; i < n; ++i) { buf.Write((byte*)&data[i], sizeof(double)); } buf.Reset(); } live_code = *buf.BufEnd; return time.elapsed(); } double test_loop_x(size_t Repeat, size_t n) { std::vector data(n, 1.0); // make a buffer large enough that it won't overflow Buffer buf(n * sizeof(double)); // warm up the cache, if necessary for (size_t i = 0; i < n; ++i) { buf.Write((byte*)&data[i], sizeof(double)); } buf.Reset(); boost::timer time; for (size_t rep = 0; rep < Repeat; ++rep) { for (size_t i = 0; i < n; ++i) { buf.WriteDouble(&data[i]); } buf.Reset(); } live_code = *buf.BufEnd; return time.elapsed(); } double test_array(size_t Repeat, size_t n) { std::vector data(n, 1.0); // make a buffer large enough that it won't overflow Buffer buf(n * sizeof(double)); // warm up the cache, if necessary buf.Write((byte*)&data[0], sizeof(double)*n); buf.Reset(); boost::timer time; for (size_t rep = 0; rep < Repeat; ++rep) { buf.Write((byte*)&data[0], sizeof(double)*n); buf.Reset(); } live_code = *buf.BufEnd; return time.elapsed(); } int main() { size_t const n = 10000000; size_t repeat = 10; // size_t const n = 1000; // size_t repeat = 100000; double IOLoopTime = test_loop_io(repeat, n); double LoopTime = test_loop(repeat, n); double LoopXTime = test_loop_x(repeat, n); double ArrayTime = test_array(repeat, n); std::cout << "iostreams loop: " << IOLoopTime << "\nloop: " << LoopTime << "\noptimized loop time: " << LoopXTime << "\narray: " << ArrayTime << '\n'; return live_code == 0; }