#include #include #include #include #include #include #include #include #include #include #include #include #include #include enum CompressionScheme { NO_COMPRESSION, ZLIB_COMPRESSION, BZIP2_COMPRESSION }; typedef boost::posix_time::ptime TimeType; //---------------------------------------------------------------------------- void add_compressor ( boost::iostreams::filtering_streambuf& out, CompressionScheme scheme ) { switch (scheme) { case ZLIB_COMPRESSION: { out.push(boost::iostreams::zlib_compressor()); break; } case BZIP2_COMPRESSION: { out.push(boost::iostreams::bzip2_compressor()); break; } default: { break; } } } //---------------------------------------------------------------------------- void add_decompressor ( boost::iostreams::filtering_streambuf& in, CompressionScheme scheme ) { switch (scheme) { case ZLIB_COMPRESSION: { in.push(boost::iostreams::zlib_decompressor()); break; } case BZIP2_COMPRESSION: { in.push(boost::iostreams::bzip2_decompressor()); break; } default: { break; } } } //---------------------------------------------------------------------------- std::string compress ( const std::string& data ) { std::stringstream compressed; std::stringstream decompressed; decompressed << data; boost::iostreams::filtering_streambuf out; out.push(boost::iostreams::zlib_compressor()); out.push(decompressed); boost::iostreams::copy(out, compressed); return compressed.str(); } //---------------------------------------------------------------------------- std::string compress1 ( const std::string& data, CompressionScheme scheme ) { std::string compressed; boost::iostreams::filtering_streambuf out; add_compressor(out, scheme); out.push(boost::iostreams::back_inserter(compressed)); boost::iostreams::copy(boost::make_iterator_range(data), out); return compressed; } //---------------------------------------------------------------------------- void compress2 ( const std::string& data, std::string& buffer, CompressionScheme scheme ) { buffer.clear(); boost::iostreams::filtering_streambuf out; add_compressor(out, scheme); out.push(boost::iostreams::back_inserter(buffer)); boost::iostreams::copy(boost::make_iterator_range(data), out); } //---------------------------------------------------------------------------- std::string decompress ( const std::string& data ) { std::stringstream compressed; std::stringstream decompressed; compressed << data; boost::iostreams::filtering_streambuf in; in.push(boost::iostreams::zlib_decompressor()); in.push(compressed); boost::iostreams::copy(in, decompressed); return decompressed.str(); } //---------------------------------------------------------------------------- std::string decompress1 ( const std::string& data, CompressionScheme scheme ) { boost::iostreams::filtering_streambuf in; add_decompressor(in, scheme); in.push(boost::make_iterator_range(data)); std::string decompressed; boost::iostreams::copy(in, boost::iostreams::back_inserter(decompressed)); return decompressed; } //---------------------------------------------------------------------------- void decompress2 ( const std::string& buffer, std::string& data, CompressionScheme scheme ) { boost::iostreams::filtering_streambuf in; add_decompressor(in, scheme); in.push(boost::make_iterator_range(buffer)); data.clear(); boost::iostreams::copy(in, boost::iostreams::back_inserter(data)); } //---------------------------------------------------------------------------- TimeType current_time ( ) { return boost::posix_time::microsec_clock::local_time(); } //---------------------------------------------------------------------------- double elapsed_seconds ( const TimeType& start_time ) { static const double MSEC_PER_SEC = 1000.0; TimeType end_time = current_time(); boost::posix_time::time_duration elapsed = end_time - start_time; return boost::numeric_cast(elapsed.total_milliseconds()) / MSEC_PER_SEC; } //---------------------------------------------------------------------------- int test_main ( int /*argc*/, char* /*argv*/[] ) { const int NUM_ITERATIONS = 10000; const std::string send_data = "boo! how are you?"; const std::string base_statement = "ALGO %|1$-3s|: %2% cycles took %|3$0.3f| seconds"; double t0; // Try original algorithm { const std::string time_statement = base_statement + " (Original)\n"; TimeType start_time = current_time(); std::string received_data; for (int i = 0; i < NUM_ITERATIONS; ++i) { const std::string buffer = compress(send_data); received_data = decompress(buffer); } BOOST_CHECK(send_data == received_data); t0 = elapsed_seconds(start_time); std::cout << (boost::format(time_statement) % 0 % NUM_ITERATIONS % t0); } const std::string improvement_statement = base_statement + " (Improvement %|4$5.2f| %%)\n"; typedef std::vector SchemeVectorType; const SchemeVectorType schemes = boost::assign::list_of(NO_COMPRESSION)(ZLIB_COMPRESSION)(BZIP2_COMPRESSION); // Try new algorithm 1 BOOST_FOREACH(CompressionScheme scheme, schemes) { TimeType start_time = current_time(); std::string received_data; for (int i = 0; i < NUM_ITERATIONS; ++i) { const std::string buffer = compress1(send_data, scheme); received_data = decompress1(buffer, scheme); } BOOST_CHECK(send_data == received_data); const std::string algo = std::string("1,") + boost::lexical_cast(scheme); const double e = elapsed_seconds(start_time); const double improvement = ((t0 - e) / t0) * 100.0; std::cout << (boost::format(improvement_statement) % algo % NUM_ITERATIONS % e % improvement); } // Try new algorithm 2 BOOST_FOREACH(CompressionScheme scheme, schemes) { TimeType start_time = current_time(); std::string received_data; for (int i = 0; i < NUM_ITERATIONS; ++i) { std::string buffer; compress2(send_data, buffer, scheme); decompress2(buffer, received_data, scheme); } BOOST_CHECK(send_data == received_data); const std::string algo = std::string("2,") + boost::lexical_cast(scheme); const double e = elapsed_seconds(start_time); const double improvement = ((t0 - e) / t0) * 100.0; std::cout << (boost::format(improvement_statement) % algo % NUM_ITERATIONS % e % improvement); } return 0; }