[PATCH 2/7] stdio-common: Iterate over the huge width for one printf function only
Matt Turner <[email protected]>
| Newsgroups | gmane.comp.lib.glibc.alpha |
|---|---|
| Message-ID | <[email protected]> |
HUGE_WIDTH is chosen so that none of the strings produced are truncated,
which for the floating-point types means every record it takes part in
carries hundreds or thousands of digits. Those records dominate the
cost of this whole family of tests: for the long double conversions they
are 99% of the bytes produced, and the long double targets alone account
for 92% of the time the tests take.
The digits being checked are produced by the same conversion code
whichever of the printf family of functions is used; what differs
between the twelve of them is the sink the result is written to, which
the smaller widths cover already.
Iterate over HUGE_WIDTH for a single function then, chosen as printf,
and let the remaining eleven stop at MID_WIDTH. This applies to the
double and long double conversions only; for the other types
full-precision output is short and costs nothing, so they keep iterating
over it as before.
Together with the switch to verifying in Python this takes the tests
from 935s to 375s of processor time on x86_64-linux-gnu, with all 576
results continuing to pass. What remains is mostly intrinsic: the f and
F conversions print the whole integer part regardless of the precision
requested, so LDBL_MAX runs to some 4932 digits even at MID_WIDTH.
---
stdio-common/tst-printf-format-p.h | 4 ++++
.../tst-printf-format-skeleton-double.c | 2 ++
.../tst-printf-format-skeleton-ldouble.c | 2 ++
stdio-common/tst-printf-format-skeleton.c | 19 ++++++++++++++++++-
4 files changed, 26 insertions(+), 1 deletion(-)
diff --git ./stdio-common/tst-printf-format-p.h ./stdio-common/tst-printf-format-p.h
index 48dcc3b48c..c35ca2c44d 100644
--- ./stdio-common/tst-printf-format-p.h
+++ ./stdio-common/tst-printf-format-p.h
@@ -18,6 +18,10 @@
#include <stdio.h>
+/* Conversions are verified at the full width and precision through this
+ function; see the comment on WPHUGE in tst-printf-format-skeleton.c. */
+#define TST_PRINTF_HUGE 1
+
#define printf_under_test(...) \
({ \
int result; \
diff --git ./stdio-common/tst-printf-format-skeleton-double.c ./stdio-common/tst-printf-format-skeleton-double.c
index e740c193b5..4dbf3fc1ed 100644
--- ./stdio-common/tst-printf-format-skeleton-double.c
+++ ./stdio-common/tst-printf-format-skeleton-double.c
@@ -21,6 +21,8 @@
#define MID_WIDTH 20
#define HUGE_WIDTH 320
+/* Full-precision output runs to hundreds of digits here. */
+#define TST_PRINTF_WIDE_TYPE 1
#define REF_FMT ".35e"
#define REF_VAL(v) (v)
#define PREC DBL_MANT_DIG
diff --git ./stdio-common/tst-printf-format-skeleton-ldouble.c ./stdio-common/tst-printf-format-skeleton-ldouble.c
index 29bc8b7d36..d959f9dc2d 100644
--- ./stdio-common/tst-printf-format-skeleton-ldouble.c
+++ ./stdio-common/tst-printf-format-skeleton-ldouble.c
@@ -22,6 +22,8 @@
#define MID_WIDTH 20
#define HUGE_WIDTH 4950
+/* Full-precision output runs to thousands of digits here. */
+#define TST_PRINTF_WIDE_TYPE 1
#define REF_FMT ".35Le"
#define REF_VAL(v) (v)
#define PREC LDBL_MANT_DIG
diff --git ./stdio-common/tst-printf-format-skeleton.c ./stdio-common/tst-printf-format-skeleton.c
index 000d8fa50d..3594124513 100644
--- ./stdio-common/tst-printf-format-skeleton.c
+++ ./stdio-common/tst-printf-format-skeleton.c
@@ -102,6 +102,23 @@ static struct
#define STR(v) #v
#define WPINIT(v) {0, STR (v)}, {v, NULL}, {-v, NULL}
+/* HUGE_WIDTH is chosen so that nothing is truncated, which for the wider
+ floating-point types means thousands of digits in every record it takes
+ part in. Those records dominate the run time of this whole family of
+ tests. The digits they check are produced by the same conversion code
+ regardless of which of the printf family of functions is used; only the
+ sink the result is written to differs, and that is covered at the
+ smaller widths already. So iterate over HUGE_WIDTH for one function
+ only, chosen as 'printf' by having tst-printf-format-p.h define
+ TST_PRINTF_HUGE, and let the remaining functions stop at MID_WIDTH.
+ Types whose full-precision output is short keep it unconditionally, as
+ it costs nothing there. */
+#if defined TST_PRINTF_WIDE_TYPE && !defined TST_PRINTF_HUGE
+# define WPHUGE
+#else
+# define WPHUGE , WPINIT (HUGE_WIDTH)
+#endif
+
/* Width and precision settings to iterate over; zero is initialized
directly as it has no corresponding negated value and other values
use the helper above. */
@@ -113,7 +130,7 @@ static struct wp
const char *s;
} const wp[] =
{ {0, "0"}, {0, NULL}, WPINIT (1), WPINIT (2),
- WPINIT (MID_WIDTH), WPINIT (HUGE_WIDTH) };
+ WPINIT (MID_WIDTH) WPHUGE };
/* Produce a record according to '%' and zero or more output format flags
already provided in FMT at indices 0..IDX-1, width W if non-NULL, '.'
--
2.54.0