[PATCH] D30268: Avoid copy of __atoms when char_type is char

Aditya Kumar via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 22 12:47:15 PST 2017


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];


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D30268.89407.patch
Type: text/x-patch
Size: 3693 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170222/fd59c361/attachment.bin>


More information about the cfe-commits mailing list