While working on I/O for std::decimal types (which I'm not going to complete for gcc 8) I realised that std::num_get still uses the old COW std::string for reading floating point types, which always allocates memory.
With this patch (which is missing the fixes for the linker script to give the new symbols the right version) we use the new std::string, so if the value being read from the stream is shorter than 16 bytes we don't need to allocate, and so can read much faster. I think this is worth changing, but I need to do some more ABI verification (and fix the linker script).
commit 19fd69a07bdd7fbb39fdf053756b1ae1c8457f5a Author: Jonathan Wakely <jwak...@redhat.com> Date: Fri Nov 17 21:07:28 2017 +0000 improve float parsing perf diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc index d7710e6bb32..f43b66c0761 100644 --- a/libstdc++-v3/include/bits/locale_facets.tcc +++ b/libstdc++-v3/include/bits/locale_facets.tcc @@ -207,8 +207,10 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL bool __found_dec = false; bool __found_sci = false; string __found_grouping; +#if !_GLIBCXX_USE_CXX11_ABI if (__lc->_M_use_grouping) __found_grouping.reserve(32); +#endif const char_type* __lit_zero = __lit + __num_base::_S_izero; if (!__lc->_M_allocated) @@ -465,8 +467,10 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL // Extract. typedef __gnu_cxx::__numeric_traits<_ValueT> __num_traits; string __found_grouping; +#if !_GLIBCXX_USE_CXX11_ABI if (__lc->_M_use_grouping) __found_grouping.reserve(32); +#endif bool __testfail = false; bool __testoverflow = false; const __unsigned_type __max = @@ -692,7 +696,9 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL ios_base::iostate& __err, float& __v) const { string __xtrc; +#if !_GLIBCXX_USE_CXX11_ABI __xtrc.reserve(32); +#endif __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); if (__beg == __end) @@ -707,7 +713,9 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL ios_base::iostate& __err, double& __v) const { string __xtrc; +#if !_GLIBCXX_USE_CXX11_ABI __xtrc.reserve(32); +#endif __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); if (__beg == __end) @@ -723,7 +731,9 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL ios_base::iostate& __err, double& __v) const { string __xtrc; +#if !_GLIBCXX_USE_CXX11_ABI __xtrc.reserve(32); +#endif __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); if (__beg == __end) @@ -739,7 +749,9 @@ _GLIBCXX_BEGIN_NAMESPACE_LDBL ios_base::iostate& __err, long double& __v) const { string __xtrc; +#if !_GLIBCXX_USE_CXX11_ABI __xtrc.reserve(32); +#endif __beg = _M_extract_float(__beg, __end, __io, __err, __xtrc); std::__convert_to_v(__xtrc.c_str(), __v, __err, _S_get_c_locale()); if (__beg == __end) diff --git a/libstdc++-v3/src/c++11/locale-inst.cc b/libstdc++-v3/src/c++11/locale-inst.cc index c1b8e8d2b6b..8022113867b 100644 --- a/libstdc++-v3/src/c++11/locale-inst.cc +++ b/libstdc++-v3/src/c++11/locale-inst.cc @@ -95,7 +95,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 template class numpunct_byname<C>; _GLIBCXX_END_NAMESPACE_CXX11 _GLIBCXX_BEGIN_NAMESPACE_LDBL -#if ! _GLIBCXX_USE_CXX11_ABI +#if GLIBCXX_USE_DUAL_ABI && ! _GLIBCXX_USE_CXX11_ABI + template istreambuf_iterator<C> + num_get<C, istreambuf_iterator<C>>:: + _M_extract_float(istreambuf_iterator<C>, istreambuf_iterator<C>, + ios_base&, ios_base::iostate&, string&); +#else template class num_get<C, istreambuf_iterator<C> >; #endif