Files
clang-p2996/libcxx/include/__format/formatter_string.h
Mark de Wever 7f65377880 [libc++][format][2/3] Optimizes c-string arguments. (#101805)
The formatter specializations for _CharT* and const _CharT* typically
write all elements in a loop. This format's internal functions are
optimized for larger writes.

Instead of writing one element at a time, convert the range to a
basic_string_view and write that instead.

For C string of 6 characters this is a bit slower, but for 60 characters
it's faster. The improvements for back_inserter<std::list<_CharT>> are
not as great as the others; it just gets as slow as
basic_string_view<_CharT>.

omparing libcxx/test/benchmarks/write_string_comparison.bench.out-before to libcxx/test/benchmarks/write_string_comparison.bench.out-after
Benchmark                                                                            Time             CPU      Time Old      Time New       CPU Old       CPU New
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
BM_sprintf/C_string_len_6                                                         -0.0015         +0.0013             5             5             5             5
BM_format/C_string_len_6                                                          +0.0390         +0.0416            53            55            53            55
BM_format_to_back_inserter<std::string>/C_string_len_6                            +0.0381         +0.0408            53            55            53            55
BM_format_to_back_inserter<std::vector<char>>/C_string_len_6                      +0.0287         +0.0315            69            71            69            71
BM_format_to_back_inserter<std::deque<char>>/C_string_len_6                       +0.0503         +0.0530           123           129           123           129
BM_format_to_back_inserter<std::list<char>>/C_string_len_6                        -0.0241         -0.0213           133           130           133           130
BM_format_to_iterator/<std::array> C_string_len_6                                 -0.0075         -0.0049            45            45            45            45
BM_format_to_iterator/<std::string> C_string_len_6                                +0.0311         +0.0340            44            46            44            46
BM_format_to_iterator/<std::vector> C_string_len_6                                +0.0380         +0.0409            43            45            43            45
BM_format_to_iterator/<std::deque> C_string_len_6                                 +0.0366         +0.0392            48            50            48            50
BM_format/string_len_6                                                            -0.0010         -0.0007            56            55            55            55
BM_format_to_back_inserter<std::string>/string_len_6                              +0.0044         +0.0041            55            56            55            55
BM_format_to_back_inserter<std::vector<char>>/string_len_6                        +0.0128         +0.0128            70            71            70            71
BM_format_to_back_inserter<std::deque<char>>/string_len_6                         +0.0151         +0.0151           126           128           126           128
BM_format_to_back_inserter<std::list<char>>/string_len_6                          -0.0719         -0.0718           140           130           139           129
BM_format_to_iterator/<std::array> string_len_6                                   -0.0323         -0.0324            47            46            47            46
BM_format_to_iterator/<std::string> string_len_6                                  -0.0011         -0.0010            45            44            44            44
BM_format_to_iterator/<std::vector> string_len_6                                  -0.0002         -0.0001            45            45            44            44
BM_format_to_iterator/<std::deque> string_len_6                                   +0.0046         +0.0047            51            51            51            51
BM_format/string_view_len_6                                                       +0.0031         +0.0031            54            54            54            54
BM_format_to_back_inserter<std::string>/string_view_len_6                         +0.0041         +0.0040            54            54            54            54
BM_format_to_back_inserter<std::vector<char>>/string_view_len_6                   +0.0022         +0.0022            70            70            70            70
BM_format_to_back_inserter<std::deque<char>>/string_view_len_6                    +0.0392         +0.0391           124           129           124           129
BM_format_to_back_inserter<std::list<char>>/string_view_len_6                     -0.0680         -0.0680           139           129           138           129
BM_format_to_iterator/<std::array> string_view_len_6                              -0.0321         -0.0320            47            46            47            46
BM_format_to_iterator/<std::string> string_view_len_6                             -0.0013         -0.0011            45            44            44            44
BM_format_to_iterator/<std::vector> string_view_len_6                             -0.0024         -0.0023            45            44            44            44
BM_format_to_iterator/<std::deque> string_view_len_6                              +0.0057         +0.0057            51            51            51            51
BM_sprintf/C_string_len_60                                                        -0.0035         -0.0035             4             4             4             4
BM_format/C_string_len_60                                                         -0.5627         -0.5627           169            74           169            74
BM_format_to_back_inserter<std::string>/C_string_len_60                           -0.5642         -0.5641           170            74           169            74
BM_format_to_back_inserter<std::vector<char>>/C_string_len_60                     -0.5300         -0.5299           178            84           178            84
BM_format_to_back_inserter<std::deque<char>>/C_string_len_60                      -0.2548         -0.2548           356           265           355           264
BM_format_to_back_inserter<std::list<char>>/C_string_len_60                       -0.1013         -0.1013          1325          1191          1322          1188
BM_format_to_iterator/<std::array> C_string_len_60                                -0.6790         -0.6791           141            45           141            45
BM_format_to_iterator/<std::string> C_string_len_60                               -0.6738         -0.6740           143            47           142            46
BM_format_to_iterator/<std::vector> C_string_len_60                               -0.6807         -0.6808           142            45           142            45
BM_format_to_iterator/<std::deque> C_string_len_60                                -0.6488         -0.6486           144            51           144            51
BM_format/string_len_60                                                           +0.0118         +0.0117            73            74            73            73
BM_format_to_back_inserter<std::string>/string_len_60                             +0.0089         +0.0088            73            73            73            73
BM_format_to_back_inserter<std::vector<char>>/string_len_60                       +0.0080         +0.0081            83            84            83            83
BM_format_to_back_inserter<std::deque<char>>/string_len_60                        +0.0005         +0.0002           262           263           262           262
BM_format_to_back_inserter<std::list<char>>/string_len_60                         -0.0384         -0.0380          1236          1188          1232          1186
BM_format_to_iterator/<std::array> string_len_60                                  -0.0288         -0.0288            47            46            47            46
BM_format_to_iterator/<std::string> string_len_60                                 +0.0213         +0.0210            44            45            44            45
BM_format_to_iterator/<std::vector> string_len_60                                 +0.0202         +0.0205            45            45            44            45
BM_format_to_iterator/<std::deque> string_len_60                                  +0.0124         +0.0124            50            51            50            51
BM_format/string_view_len_60                                                      +0.0093         +0.0093            73            73            73            73
BM_format_to_back_inserter<std::string>/string_view_len_60                        +0.0055         +0.0055            73            73            73            73
BM_format_to_back_inserter<std::vector<char>>/string_view_len_60                  +0.0165         +0.0166            81            83            81            83
BM_format_to_back_inserter<std::deque<char>>/string_view_len_60                   +0.0138         +0.0140           260           263           259           263
BM_format_to_back_inserter<std::list<char>>/string_view_len_60                    -0.0334         -0.0335          1228          1187          1225          1184
BM_format_to_iterator/<std::array> string_view_len_60                             -0.0257         -0.0259            48            46            47            46
BM_format_to_iterator/<std::string> string_view_len_60                            +0.0324         +0.0323            45            46            44            46
BM_format_to_iterator/<std::vector> string_view_len_60                            +0.0174         +0.0177            45            45            44            45
BM_format_to_iterator/<std::deque> string_view_len_60                             +0.0076         +0.0076            50            51            50            51
BM_sprintf/C_string_len_6000                                                      +0.4922         +0.4921            77           115            77           114
BM_format/C_string_len_6000                                                       -0.9239         -0.9239         11780           897         11750           894
BM_format_to_back_inserter<std::string>/C_string_len_6000                         -0.9239         -0.9239         11792           898         11763           895
BM_format_to_back_inserter<std::vector<char>>/C_string_len_6000                   -0.9257         -0.9257         11709           870         11679           868
BM_format_to_back_inserter<std::deque<char>>/C_string_len_6000                    -0.4057         -0.4057         25616         15225         25553         15187
BM_format_to_back_inserter<std::list<char>>/C_string_len_6000                     -0.0832         -0.0833        127144        116569        126823        116265
BM_format_to_iterator/<std::array> C_string_len_6000                              -0.9853         -0.9853         10869           160         10843           160
BM_format_to_iterator/<std::string> C_string_len_6000                             -0.9864         -0.9864         10870           148         10841           148
BM_format_to_iterator/<std::vector> C_string_len_6000                             -0.9863         -0.9863         10874           149         10846           148
BM_format_to_iterator/<std::deque> C_string_len_6000                              -0.9629         -0.9629         11239           417         11212           416
BM_format/string_len_6000                                                         -0.0012         -0.0013           846           845           844           842
BM_format_to_back_inserter<std::string>/string_len_6000                           -0.0029         -0.0034           845           843           843           840
BM_format_to_back_inserter<std::vector<char>>/string_len_6000                     -0.0129         -0.0125           832           821           830           819
BM_format_to_back_inserter<std::deque<char>>/string_len_6000                      +0.0048         +0.0048         15042         15114         15004         15076
BM_format_to_back_inserter<std::list<char>>/string_len_6000                       -0.0017         -0.0017        116266        116072        115967        115768
BM_format_to_iterator/<std::array> string_len_6000                                -0.0257         -0.0256           120           117           120           117
BM_format_to_iterator/<std::string> string_len_6000                               -0.0025         -0.0029           117           117           117           117
BM_format_to_iterator/<std::vector> string_len_6000                               -0.0089         -0.0087           118           116           117           116
BM_format_to_iterator/<std::deque> string_len_6000                                -0.0478         -0.0477           379           361           378           360
BM_format/string_view_len_6000                                                    -0.0092         -0.0091           842           835           840           833
BM_format_to_back_inserter<std::string>/string_view_len_6000                      -0.0081         -0.0083           841           835           839           832
BM_format_to_back_inserter<std::vector<char>>/string_view_len_6000                +0.0089         +0.0088           808           815           806           813
BM_format_to_back_inserter<std::deque<char>>/string_view_len_6000                 +0.0068         +0.0068         15030         15131         14992         15093
BM_format_to_back_inserter<std::list<char>>/string_view_len_6000                  +0.0012         +0.0010        116099        116243        115813        115934
BM_format_to_iterator/<std::array> string_view_len_6000                           -0.0122         -0.0121           118           117           118           116
BM_format_to_iterator/<std::string> string_view_len_6000                          +0.0010         +0.0010           106           107           106           106
BM_format_to_iterator/<std::vector> string_view_len_6000                          -0.0008         -0.0006           106           106           106           106
BM_format_to_iterator/<std::deque> string_view_len_6000                           -0.0549         -0.0548           370           349           369           349
OVERALL_GEOMEAN
2024-10-06 21:20:22 +02:00

158 lines
6.4 KiB
C++

// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___FORMAT_FORMATTER_STRING_H
#define _LIBCPP___FORMAT_FORMATTER_STRING_H
#include <__config>
#include <__format/concepts.h>
#include <__format/format_parse_context.h>
#include <__format/formatter.h>
#include <__format/formatter_output.h>
#include <__format/parser_std_format_spec.h>
#include <__format/write_escaped.h>
#include <string>
#include <string_view>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20
template <__fmt_char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS __formatter_string {
public:
template <class _ParseContext>
_LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
typename _ParseContext::iterator __result = __parser_.__parse(__ctx, __format_spec::__fields_string);
__format_spec::__process_display_type_string(__parser_.__type_);
return __result;
}
template <class _FormatContext>
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator
format(basic_string_view<_CharT> __str, _FormatContext& __ctx) const {
# if _LIBCPP_STD_VER >= 23
if (__parser_.__type_ == __format_spec::__type::__debug)
return __formatter::__format_escaped_string(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx));
# endif
return __formatter::__write_string(__str, __ctx.out(), __parser_.__get_parsed_std_specifications(__ctx));
}
# if _LIBCPP_STD_VER >= 23
_LIBCPP_HIDE_FROM_ABI constexpr void set_debug_format() { __parser_.__type_ = __format_spec::__type::__debug; }
# endif
__format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__left};
};
// Formatter const char*.
template <__fmt_char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS formatter<const _CharT*, _CharT> : public __formatter_string<_CharT> {
using _Base = __formatter_string<_CharT>;
template <class _FormatContext>
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(const _CharT* __str, _FormatContext& __ctx) const {
_LIBCPP_ASSERT_INTERNAL(__str, "The basic_format_arg constructor should have prevented an invalid pointer.");
// Converting the input to a basic_string_view means the data is looped over twice;
// - once to determine the length, and
// - once to process the data.
//
// This sounds slower than writing the output directly. However internally
// the output algorithms have optimizations for "bulk" operations, which
// makes this faster than a single-pass character-by-character output.
return _Base::format(basic_string_view<_CharT>(__str), __ctx);
}
};
// Formatter char*.
template <__fmt_char_type _CharT>
struct _LIBCPP_TEMPLATE_VIS formatter<_CharT*, _CharT> : public formatter<const _CharT*, _CharT> {
using _Base = formatter<const _CharT*, _CharT>;
template <class _FormatContext>
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator format(_CharT* __str, _FormatContext& __ctx) const {
return _Base::format(__str, __ctx);
}
};
// Formatter char[].
template <__fmt_char_type _CharT, size_t _Size>
struct _LIBCPP_TEMPLATE_VIS formatter<_CharT[_Size], _CharT> : public __formatter_string<_CharT> {
using _Base = __formatter_string<_CharT>;
template <class _FormatContext>
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator
format(const _CharT (&__str)[_Size], _FormatContext& __ctx) const {
return _Base::format(basic_string_view<_CharT>(__str, _Size), __ctx);
}
};
// Formatter std::string.
template <__fmt_char_type _CharT, class _Traits, class _Allocator>
struct _LIBCPP_TEMPLATE_VIS formatter<basic_string<_CharT, _Traits, _Allocator>, _CharT>
: public __formatter_string<_CharT> {
using _Base = __formatter_string<_CharT>;
template <class _FormatContext>
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator
format(const basic_string<_CharT, _Traits, _Allocator>& __str, _FormatContext& __ctx) const {
// Drop _Traits and _Allocator to have one std::basic_string formatter.
return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx);
}
};
// Formatter std::string_view.
template <__fmt_char_type _CharT, class _Traits>
struct _LIBCPP_TEMPLATE_VIS formatter<basic_string_view<_CharT, _Traits>, _CharT> : public __formatter_string<_CharT> {
using _Base = __formatter_string<_CharT>;
template <class _FormatContext>
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator
format(basic_string_view<_CharT, _Traits> __str, _FormatContext& __ctx) const {
// Drop _Traits to have one std::basic_string_view formatter.
return _Base::format(basic_string_view<_CharT>(__str.data(), __str.size()), __ctx);
}
};
# if _LIBCPP_STD_VER >= 23
template <>
inline constexpr bool enable_nonlocking_formatter_optimization<char*> = true;
template <>
inline constexpr bool enable_nonlocking_formatter_optimization<const char*> = true;
template <size_t _Size>
inline constexpr bool enable_nonlocking_formatter_optimization<char[_Size]> = true;
template <class _Traits, class _Allocator>
inline constexpr bool enable_nonlocking_formatter_optimization<basic_string<char, _Traits, _Allocator>> = true;
template <class _Traits>
inline constexpr bool enable_nonlocking_formatter_optimization<basic_string_view<char, _Traits>> = true;
# ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
template <>
inline constexpr bool enable_nonlocking_formatter_optimization<wchar_t*> = true;
template <>
inline constexpr bool enable_nonlocking_formatter_optimization<const wchar_t*> = true;
template <size_t _Size>
inline constexpr bool enable_nonlocking_formatter_optimization<wchar_t[_Size]> = true;
template <class _Traits, class _Allocator>
inline constexpr bool enable_nonlocking_formatter_optimization<basic_string<wchar_t, _Traits, _Allocator>> = true;
template <class _Traits>
inline constexpr bool enable_nonlocking_formatter_optimization<basic_string_view<wchar_t, _Traits>> = true;
# endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS
# endif // _LIBCPP_STD_VER >= 23
#endif // _LIBCPP_STD_VER >= 20
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___FORMAT_FORMATTER_STRING_H