Why is snprintf consistently 2x faster than ostringstream for printing a single number?

南楼画角 提交于 2019-12-02 00:19:20

std::ostringstream calls vsnprintf twice: first time to try with a small buffer, and the second one with the correctly-sized buffer. See locale_facets.tcc around line 1011 (here std::__convert_from_v is a proxy for vsnprintf):

#if _GLIBCXX_USE_C99_STDIO
    // Precision is always used except for hexfloat format.
    const bool __use_prec =
      (__io.flags() & ios_base::floatfield) != ios_base::floatfield;

    // First try a buffer perhaps big enough (most probably sufficient
    // for non-ios_base::fixed outputs)
    int __cs_size = __max_digits * 3;
    char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
    if (__use_prec)
      __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
                    __fbuf, __prec, __v);
    else
      __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
                    __fbuf, __v);

    // If the buffer was not large enough, try again with the correct size.
    if (__len >= __cs_size)
      {
        __cs_size = __len + 1;
        __cs = static_cast<char*>(__builtin_alloca(__cs_size));
        if (__use_prec)
          __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
                        __fbuf, __prec, __v);
        else
          __len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
                        __fbuf, __v);
      }

This exactly matches the observation that for small requested precision performance is the same as that of snprintf, while for larger precision it's 2x poorer.

Moreover, since the buffer used doesn't depend on any properties of std::ostringstream buffer, only on __max_digits, which is defined as __gnu_cxx::__numeric_traits<_ValueT>::__digits10, there doesn't seem to be any natural fix for this other than fixing libstdc++ itself.

I've reported it as bug to libstdc++.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!