From 60dfe51f11d247f8490f54b4441a4fda14d6c66a Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 14 Sep 2016 22:17:29 +0300 Subject: Optimize fdstream so performance is on par with fstream --- tests/fdstream/driver.cxx | 137 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) (limited to 'tests/fdstream/driver.cxx') diff --git a/tests/fdstream/driver.cxx b/tests/fdstream/driver.cxx index 03eab80..2e3bac5 100644 --- a/tests/fdstream/driver.cxx +++ b/tests/fdstream/driver.cxx @@ -4,12 +4,17 @@ #include #include +#include +#include #include #include +#include +#include #include #include #include +#include #include using namespace std; @@ -38,9 +43,60 @@ to_file (const path& f, const string& s, fdopen_mode m = fdopen_mode::none) ofs.close (); } +template +static duration +write_time (const path& p, const T& s, size_t n) +{ + timestamp t (timestamp::clock::now ()); + S os (p.string (), ofstream::out); + os.exceptions (S::failbit | S::badbit); + + for (size_t i (0); i < n; ++i) + { + if (i > 0) + os << '\n'; // Important not to use endl as it syncs a stream. + + os << s; + } + + os.close (); + return timestamp::clock::now () - t; +} + +template +static duration +read_time (const path& p, const T& s, size_t n) +{ + vector v (n); + + timestamp t (timestamp::clock::now ()); + S is (p.string (), ofstream::in); + is.exceptions (S::failbit | S::badbit); + + for (auto& ve: v) + is >> ve; + + assert (is.eof ()); + + is.close (); + duration d (timestamp::clock::now () - t); + + for (const auto& ve: v) + assert (ve == s); + + return d; +} + int -main () +main (int argc, const char* argv[]) { + if (!(argc == 1 || (argc == 2 && argv[1] == string ("-v")))) + { + cerr << "usage: " << argv[0] << " [-v]" << endl; + return 1; + } + + bool v (argc == 2); dir_path td (dir_path::temp_directory () / dir_path ("butl-fdstream")); // Recreate the temporary directory (that possibly exists from the previous @@ -307,5 +363,84 @@ main () #endif + // Compare fdstream and fstream operations performance. + // + duration fwd (0); + duration dwd (0); + duration frd (0); + duration drd (0); + + path ff (td / path ("fstream")); + path fd (td / path ("fdstream")); + + // Make several measurements with different ordering for each benchmark to + // level fluctuations. + // + // Write/read ~10M-size files by 100, 1000, 10 000, 100 000 byte-length + // strings. + // + size_t sz (100); + for (size_t i (0); i < 4; ++i) + { + string s; + s.reserve (sz); + + // Fill string with characters from '0' to 'z'. + // + for (size_t i (0); i < sz; ++i) + s.push_back ('0' + i % (123 - 48)); + + size_t n (10 * 1024 * 1024 / sz); + + for (size_t i (0); i < 4; ++i) + { + if (i % 2 == 0) + { + fwd += write_time (ff, s, n); + dwd += write_time (fd, s, n); + frd += read_time (ff, s, n); + drd += read_time (fd, s, n); + } + else + { + dwd += write_time (fd, s, n); + fwd += write_time (ff, s, n); + drd += read_time (fd, s, n); + frd += read_time (ff, s, n); + } + } + + sz *= 10; + } + + // Write/read ~10M-size files by 64-bit integers. + // + uint64_t u (0x1234567890123456); + size_t n (10 * 1024 * 1024 / sizeof (u)); + + for (size_t i (0); i < 4; ++i) + { + if (i % 2 == 0) + { + fwd += write_time (ff, u, n); + dwd += write_time (fd, u, n); + frd += read_time (ff, u, n); + drd += read_time (fd, u, n); + } + else + { + dwd += write_time (fd, u, n); + fwd += write_time (ff, u, n); + drd += read_time (fd, u, n); + frd += read_time (ff, u, n); + } + } + + if (v) + cerr << "fdstream/fstream write and read duration ratios are " + << fixed << setprecision (2) + << static_cast (dwd.count ()) / fwd.count () << " and " + << static_cast (drd.count ()) / frd.count () << endl; + rmdir_r (td); } -- cgit v1.1