I was trying to pick a standard way to convert integrals to strings, so I went on and did a small performance evaluation by measuring the execution time of
Question 1. Why is the string stream method consistently the worst?
The classical mistake: creating a new stringstream every single time
template<typename T> // 1. Using stringstream
string StringFromIntegral_SS(T const &value) {
thread_local stringstream ss;
ss.str("");
ss.clear();
ss << value;
return ss.str();
}
Question 2. Why is lexical cast consistently the best? Can we assume that this is the fastest implementation ?
Because it's most specialized; and, no, faster implementations exist. FastFormat and Boost Spirit have competitive offerings, as far as I know.
Update Boost Spirit Karma still easily beats the bunch:
template<typename T> // 4. Karma to string
std::string StringFromIntegral_K(T const &value) {
thread_local auto const gen = boost::spirit::traits::create_generator<T>::call();
thread_local char buf[20];
char* it = buf;
boost::spirit::karma::generate(it, gen, value);
return std::string(buf, it);
}
Timings:
C++ 11 method 111
String stream method 103
Lexical cast method 57
Spirit Karma method 36
Spirit Karma method with string_ref 13
See it Live On Coliru Clang or GCC
Just to goof off, a version using boost::string_ref
is much faster still due the reduced allocations:
template<typename T> // 5. Karma to string_ref
boost::string_ref StringFromIntegral_KSR(T const &value) {
thread_local auto const gen = boost::spirit::traits::create_generator<T>::call();
thread_local char buf[20];
char* it = buf;
boost::spirit::karma::generate(it, gen, value);
return boost::string_ref(buf, it-buf);
}
I've tested all modified methods for correctness using an asserting test loop:
return measure<>::execution(
//[&]() { for (auto const &i : v1) { func(i); }});
[&]() { for (auto const &i : v1) { assert(func(i) == StringFromIntegral_LC(i)); }});