Don't create a new locale on every to_string() call.
Creating locales is surprisingly expensive. We have an application where we - especially during tests - write large amounts of Thrift dumps to disk, and is this application we currently spend around 17% of total CPU time in std::locale's constructor. With this change, it's basically down to zero.
diff --git a/lib/cpp/src/thrift/TToString.h b/lib/cpp/src/thrift/TToString.h
index 79743fd..474429d 100644
--- a/lib/cpp/src/thrift/TToString.h
+++ b/lib/cpp/src/thrift/TToString.h
@@ -35,7 +35,8 @@
template <typename T>
std::string to_string(const T& t) {
std::ostringstream o;
- o.imbue(std::locale("C"));
+ const static auto locale = std::locale("C");
+ o.imbue(locale);
o << t;
return o.str();
}
@@ -44,7 +45,8 @@
// is enabled.
inline std::string to_string(const float& t) {
std::ostringstream o;
- o.imbue(std::locale("C"));
+ const static auto locale = std::locale("C");
+ o.imbue(locale);
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<float>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();
@@ -52,7 +54,8 @@
inline std::string to_string(const double& t) {
std::ostringstream o;
- o.imbue(std::locale("C"));
+ const static auto locale = std::locale("C");
+ o.imbue(locale);
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<double>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();
@@ -60,7 +63,8 @@
inline std::string to_string(const long double& t) {
std::ostringstream o;
- o.imbue(std::locale("C"));
+ const static auto locale = std::locale("C");
+ o.imbue(locale);
o.precision(static_cast<std::streamsize>(std::ceil(static_cast<double>(std::numeric_limits<long double>::digits * std::log10(2.0f) + 1))));
o << t;
return o.str();