Skip to content

Commit

Permalink
Added format module benchmark. Updated documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
Thermadiag committed Apr 27, 2023
1 parent 14e6942 commit df20143
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 80 deletions.
1 change: 1 addition & 0 deletions benchs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ enable_testing()
# create the testing file and list of tests
create_test_sourcelist (Benchs
seq_benchs.cpp
bench_format.cpp
bench_hash.cpp
bench_mem_pool.cpp
bench_map.cpp
Expand Down
83 changes: 83 additions & 0 deletions benchs/bench_format.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <seq/testing.hpp>
#include <seq/format.hpp>
#include <vector>
#include <iostream>

#ifdef SEQ_HAS_CPP_20
#include <format>
#endif

int bench_format(int, char ** const)
{

using namespace seq;

// Generate 4M double values
using ftype = double;
random_float_genertor<ftype> rgn;
std::vector<ftype> vec_d;
for (int i = 0; i < 4000000; ++i)
vec_d.push_back(rgn());

// Null ostream object
nullbuf n;
std::ostream oss(&n);
oss.sync_with_stdio(false);

// Build a table of 4 * 1000000 double values separated by a '|'. All values are centered on a 20 characters space
tick();
oss << std::setprecision(6);
for (size_t i = 0; i < vec_d.size() / 4; ++i)
{
oss << std::left << std::setw(20) << vec_d[i * 4] << "|";
oss << std::left << std::setw(20) << vec_d[i * 4 + 1] << "|";
oss << std::left << std::setw(20) << vec_d[i * 4 + 2] << "|";
oss << std::left << std::setw(20) << vec_d[i * 4 + 3] << "|";
oss << std::endl;
}
size_t el = tock_ms();
std::cout << "Write table with streams: " << el << " ms" << std::endl;


// Build the same table with format module

// Create the format object
auto slot = _g<ftype>().p(6).l(20); // floating point slot with a precision of 6 and left-aligned on a 20 characters width
auto f = join("|",slot, slot, slot, slot, "");
tick();
for (size_t i = 0; i < vec_d.size() / 4; ++i)
oss << f(vec_d[i * 4], vec_d[i * 4 + 1], vec_d[i * 4 + 2], vec_d[i * 4 + 3]) << std::endl;
el = tock_ms();
std::cout << "Write table with seq formatting module: " << el << " ms" << std::endl;


// Compare to std::format for C++20 compilers
#ifdef SEQ_HAS_CPP_20
tick();
for (size_t i = 0; i < vec_d.size() / 4; ++i)
std::format_to(
std::ostreambuf_iterator<char>(oss),
"{:^20.6g} | {:^20.6g} | {:^20.6g} | {:^20.6g}\n",
vec_d[i * 4], vec_d[i * 4 + 1], vec_d[i * 4 + 2], vec_d[i * 4 + 3]);
el = tock_ms();
std::cout << "Write table with std::format : " << el << " ms" << std::endl;
#endif

// Just for comparison, directly dump the double values without the '|' character (but keeping alignment)

tick();
auto f2 = g<ftype>().l(20);
for (size_t i = 0; i < vec_d.size(); ++i)
oss << f2(vec_d[i]);
el = tock_ms();
std::cout << "Write left-aligned double with seq::fmt: " << el << " ms" << std::endl;



// use std::ostream::bad() to make sure the above tests are not simply ignored by the compiler
if (oss.bad())
std::cout << "error" << std::endl;


return 0;
}
62 changes: 37 additions & 25 deletions docs/format.md
Original file line number Diff line number Diff line change
Expand Up @@ -648,14 +648,19 @@ The following code is a simple benchmark on writing a 4 * 1000000 table of doubl
#include <seq/testing.hpp>
#include <seq/format.hpp>
#ifdef SEQ_HAS_CPP_20
#include <format>
#endif
int main(int argc, char ** argv)
{
using namespace seq;
// Generate 4M double values
using float_type = double;
random_float_genertor<float_type> rgn;
std::vector<float_type> vec_d;
using ftype = double;
random_float_genertor<ftype> rgn;
std::vector<ftype> vec_d;
for (int i = 0; i < 4000000; ++i)
vec_d.push_back(rgn());
Expand All @@ -667,50 +672,55 @@ int main(int argc, char ** argv)
// Build a table of 4 * 1000000 double values separated by a '|'. All values are centered on a 20 characters space
tick();
oss << std::setprecision(6);
for (size_t i = 0; i < vec_d.size()/4; ++i)
for (size_t i = 0; i < vec_d.size() / 4; ++i)
{
oss << std::left << std::setw(20) << vec_d[i * 4] << "|";
oss << std::left << std::setw(20) << vec_d[i * 4+1] << "|";
oss << std::left << std::setw(20) << vec_d[i * 4+2] << "|";
oss << std::left << std::setw(20) << vec_d[i * 4+3] << "|";
oss << std::left << std::setw(20) << vec_d[i * 4 + 1] << "|";
oss << std::left << std::setw(20) << vec_d[i * 4 + 2] << "|";
oss << std::left << std::setw(20) << vec_d[i * 4 + 3] << "|";
oss << std::endl;
}
size_t el = tock_ms();
std::cout << "Write table with streams: " <<el<<" ms"<< std::endl;
std::cout << "Write table with streams: " << el << " ms" << std::endl;
// Build the same table with format module
// Create the format object
auto f = fmt(pos<0, 2, 4, 6>(), g<float_type>().p(6).c(20), "|", g<float_type>().p(6).c(20), "|", g<float_type>().p(6).c(20), "|", g<float_type>().p(6).c(20), "|");
auto slot = _g<ftype>().p(6).l(20); // floating point slot with a precision of 6 and left-aligned on a 20 characters width
auto f = join("|",slot, slot, slot, slot, "");
tick();
for (size_t i = 0; i < vec_d.size() / 4; ++i)
oss << f(vec_d[i * 4], vec_d[i * 4+1], vec_d[i * 4+2], vec_d[i * 4+3]) << std::endl;
oss << f(vec_d[i * 4], vec_d[i * 4 + 1], vec_d[i * 4 + 2], vec_d[i * 4 + 3]) << std::endl;
el = tock_ms();
std::cout << "Write table with seq formatting module: " << el << " ms" << std::endl;
// Compare to std::format for C++20 compilers
// tick();
// for (size_t i = 0; i < vec_d.size() / 4; ++i)
// std::format_to(std::ostreambuf_iterator<char>(oss), "{:^20.6g} | {:^20.6g} | {:^20.6g} | {:^20.6g}\n", vec_d[i * 4], vec_d[i * 4 + 1], vec_d[i * 4 + 2], vec_d[i * 4 + 3]);
// el = tock_ms();
// std::cout << "Write table with std::format : " << el << " ms" << std::endl;
#ifdef SEQ_HAS_CPP_20
tick();
for (size_t i = 0; i < vec_d.size() / 4; ++i)
std::format_to(
std::ostreambuf_iterator<char>(oss),
"{:^20.6g} | {:^20.6g} | {:^20.6g} | {:^20.6g}\n",
vec_d[i * 4], vec_d[i * 4 + 1], vec_d[i * 4 + 2], vec_d[i * 4 + 3]);
el = tock_ms();
std::cout << "Write table with std::format : " << el << " ms" << std::endl;
#endif
// Just for comparison, directly dump the double values without the '|' character (but keeping centering)
// Just for comparison, directly dump the double values without the '|' character (but keeping alignment)
tick();
auto f2 = seq::fmt(float_type(), 'g').c(20);
auto f2 = g<ftype>().l(20);
for (size_t i = 0; i < vec_d.size(); ++i)
oss << f2(vec_d[i]);
el = tock_ms();
std::cout << "Write centered double with seq::fmt: " << el << " ms" << std::endl;
std::cout << "Write left-aligned double with seq::fmt: " << el << " ms" << std::endl;
// use std::ostream::bad() to make sure the above tests are not simply ignored by the compiler
if ((int)oss.bad())
if (oss.bad())
std::cout << "error" << std::endl;
Expand All @@ -719,10 +729,12 @@ int main(int argc, char ** argv)
```

Above example compiled with gcc 10.1.0 (-O3) for msys2 on Windows 10 on a Intel(R) Core(TM) i7-10850H at 2.70GHz gives the following output:
Above example compiled with msvc 14.20 (all optimization flags, C++20 support) on Windows 10 on a Intel(R) Core(TM) i7-10850H at 2.70GHz gives the following output:

> Write table with streams: 3469 ms
> Write table with streams: 4482 ms
>
> Write table with seq formatting module: 677 ms
>
> Write table with seq formatting module: 413 ms
> Write table with std::format : 1107 ms
>
> Write centered double with seq::fmt: 366 ms
> Write left-aligned double with seq::fmt: 519 ms
6 changes: 6 additions & 0 deletions seq/bits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,16 @@ static constexpr void* __dummy_ptr_with_long_name = nullptr;
#if _MSVC_LANG >= 201703L
#define SEQ_HAS_CPP_17
#endif
#if _MSVC_LANG >= 202002L
#define SEQ_HAS_CPP_20
#endif
#else
#if __cplusplus >= 201703L
#define SEQ_HAS_CPP_17
#endif
#if __cplusplus >= 202002L
#define SEQ_HAS_CPP_20
#endif
#endif

// If constexpr
Expand Down
Loading

0 comments on commit df20143

Please sign in to comment.