hiraditya created this revision. The function __num_get<_CharT>::__stage2_int_prep makes unnecessary copy of __src into __atoms when char_type is char. This can be avoided by creating a switch on type and just returning __src when char_type is char. Running a synthetic benchmark shows the impact of this change:
The test case can be found here: https://github.com/hiraditya/std-benchmark/blob/master/cxx/stringstream.bench.cpp Without the change with llvm-project/trunk $ export LD_LIBRARY_PATH=/work/llvm-project/install/lib; ./cxx/stringstream.bench.cpp.out Run on (24 X 1200 MHz CPU s) 2017-02-22 14:37:34 Benchmark Time CPU Iterations -------------------------------------------------------------- BM_Istream_numbers/32 8328 ns 8336 ns 83121 BM_Istream_numbers/64 8312 ns 8320 ns 83754 BM_Istream_numbers/128 8301 ns 8309 ns 83975 BM_Istream_numbers/256 8298 ns 8306 ns 84349 BM_Istream_numbers/512 8303 ns 8311 ns 84308 BM_Istream_numbers/1024 8301 ns 8309 ns 84316 With the change on llvm-project/trunk $ export LD_LIBRARY_PATH=/work/llvm-project/install-sstream/lib; ./cxx/stringstream.bench.cpp.out Run on (24 X 1200 MHz CPU s) 2017-02-22 14:37:55 Benchmark Time CPU Iterations -------------------------------------------------------------- BM_Istream_numbers/32 7465 ns 7472 ns 91957 BM_Istream_numbers/64 7460 ns 7467 ns 93824 BM_Istream_numbers/128 7457 ns 7464 ns 93875 BM_Istream_numbers/256 7456 ns 7463 ns 93781 BM_Istream_numbers/512 7455 ns 7462 ns 93793 BM_Istream_numbers/1024 7457 ns 7464 ns 93757 https://reviews.llvm.org/D30268 Files: libcxx/include/locale Index: libcxx/include/locale =================================================================== --- libcxx/include/locale +++ libcxx/include/locale @@ -380,25 +380,45 @@ struct __num_get : protected __num_get_base { - static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep); + static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep); static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep); + const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const + { + return __do_widen_p(__iob, __atoms); + } + + static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end, unsigned& __dc, _CharT __thousands_sep, const string& __grouping, - unsigned* __g, unsigned*& __g_end, _CharT* __atoms); + unsigned* __g, unsigned*& __g_end, const _CharT* __atoms); static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end, _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping, unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms); +private: + template<typename T> + const T* __do_widen_p(ios_base& __iob, T* __atoms) const + { + locale __loc = __iob.getloc(); + use_facet<ctype<T> >(__loc).widen(__src, __src + 26, __atoms); + return __atoms; + } + + const char* __do_widen_p(ios_base& __iob, char* __atoms) const + { + (void)__iob; + (void)__atoms; + return __src; + } }; template <class _CharT> string -__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep) +__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) { locale __loc = __iob.getloc(); - use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms); const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); __thousands_sep = __np.thousands_sep(); return __np.grouping(); @@ -421,7 +441,7 @@ int __num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end, unsigned& __dc, _CharT __thousands_sep, const string& __grouping, - unsigned* __g, unsigned*& __g_end, _CharT* __atoms) + unsigned* __g, unsigned*& __g_end, const _CharT* __atoms) { if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25])) { @@ -854,9 +874,10 @@ // Stage 1 int __base = this->__get_base(__iob); // Stage 2 - char_type __atoms[26]; + char_type __atoms1[26]; char_type __thousands_sep; - string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep); + const char_type *__atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); string __buf; __buf.resize(__buf.capacity()); char* __a = &__buf[0]; @@ -904,9 +925,10 @@ // Stage 1 int __base = this->__get_base(__iob); // Stage 2 - char_type __atoms[26]; + char_type __atoms1[26]; char_type __thousands_sep; - string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep); + const char_type *__atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); string __buf; __buf.resize(__buf.capacity()); char* __a = &__buf[0];
Index: libcxx/include/locale =================================================================== --- libcxx/include/locale +++ libcxx/include/locale @@ -380,25 +380,45 @@ struct __num_get : protected __num_get_base { - static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep); + static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep); static string __stage2_float_prep(ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep); + const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const + { + return __do_widen_p(__iob, __atoms); + } + + static int __stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end, unsigned& __dc, _CharT __thousands_sep, const string& __grouping, - unsigned* __g, unsigned*& __g_end, _CharT* __atoms); + unsigned* __g, unsigned*& __g_end, const _CharT* __atoms); static int __stage2_float_loop(_CharT __ct, bool& __in_units, char& __exp, char* __a, char*& __a_end, _CharT __decimal_point, _CharT __thousands_sep, const string& __grouping, unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms); +private: + template<typename T> + const T* __do_widen_p(ios_base& __iob, T* __atoms) const + { + locale __loc = __iob.getloc(); + use_facet<ctype<T> >(__loc).widen(__src, __src + 26, __atoms); + return __atoms; + } + + const char* __do_widen_p(ios_base& __iob, char* __atoms) const + { + (void)__iob; + (void)__atoms; + return __src; + } }; template <class _CharT> string -__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep) +__num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) { locale __loc = __iob.getloc(); - use_facet<ctype<_CharT> >(__loc).widen(__src, __src + 26, __atoms); const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc); __thousands_sep = __np.thousands_sep(); return __np.grouping(); @@ -421,7 +441,7 @@ int __num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end, unsigned& __dc, _CharT __thousands_sep, const string& __grouping, - unsigned* __g, unsigned*& __g_end, _CharT* __atoms) + unsigned* __g, unsigned*& __g_end, const _CharT* __atoms) { if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25])) { @@ -854,9 +874,10 @@ // Stage 1 int __base = this->__get_base(__iob); // Stage 2 - char_type __atoms[26]; + char_type __atoms1[26]; char_type __thousands_sep; - string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep); + const char_type *__atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); string __buf; __buf.resize(__buf.capacity()); char* __a = &__buf[0]; @@ -904,9 +925,10 @@ // Stage 1 int __base = this->__get_base(__iob); // Stage 2 - char_type __atoms[26]; + char_type __atoms1[26]; char_type __thousands_sep; - string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep); + const char_type *__atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); string __buf; __buf.resize(__buf.capacity()); char* __a = &__buf[0];
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits