aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2021-10-28 13:39:57 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2021-10-28 13:39:57 -0400
commit3c17926eedd51c4094db7c62f59950918044ab1c (patch)
tree4a1fecd1e8298656cb8da581ae53d1418bb295fa /src
parent7f580aa5d88a9b03d66fcb9a1d7c4fcd69d9e126 (diff)
downloadpostgresql-3c17926eedd51c4094db7c62f59950918044ab1c.tar.gz
postgresql-3c17926eedd51c4094db7c62f59950918044ab1c.zip
Speed up printing of integers in snprintf.c.
Since the only possible divisors are 8, 10, and 16, it doesn't cost much code space to replace the division loop with three copies using constant divisors. On most machines, division by a constant can be done a lot more cheaply than division by an arbitrary value. A microbenchmark testing just snprintf("foo %d") with a 9-digit value showed about a 2X speedup for me (tgl). Most of Postgres isn't too dependent on the speed of snprintf, so that the effect in real-world cases is barely measurable. Still, a cycle saved is a cycle earned. Arjan van de Ven Discussion: https://postgr.es/m/40a4b32a-b841-4667-11b2-a0baedb12714@linux.intel.com Discussion: https://postgr.es/m/6e51c644-1b6d-956e-ac24-2d1b0541d532@linux.intel.com
Diffstat (limited to 'src')
-rw-r--r--src/port/snprintf.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index 7c214293699..1e59ca36e2c 100644
--- a/src/port/snprintf.c
+++ b/src/port/snprintf.c
@@ -1015,8 +1015,8 @@ fmtint(long long value, char type, int forcesign, int leftjust,
int minlen, int zpad, int precision, int pointflag,
PrintfTarget *target)
{
- unsigned long long base;
unsigned long long uvalue;
+ int base;
int dosign;
const char *cvt = "0123456789abcdef";
int signvalue = 0;
@@ -1075,12 +1075,36 @@ fmtint(long long value, char type, int forcesign, int leftjust,
vallen = 0;
else
{
- /* make integer string */
- do
+ /*
+ * Convert integer to string. We special-case each of the possible
+ * base values so as to avoid general-purpose divisions. On most
+ * machines, division by a fixed constant can be done much more
+ * cheaply than a general divide.
+ */
+ if (base == 10)
+ {
+ do
+ {
+ convert[sizeof(convert) - (++vallen)] = cvt[uvalue % 10];
+ uvalue = uvalue / 10;
+ } while (uvalue);
+ }
+ else if (base == 16)
{
- convert[sizeof(convert) - (++vallen)] = cvt[uvalue % base];
- uvalue = uvalue / base;
- } while (uvalue);
+ do
+ {
+ convert[sizeof(convert) - (++vallen)] = cvt[uvalue % 16];
+ uvalue = uvalue / 16;
+ } while (uvalue);
+ }
+ else /* base == 8 */
+ {
+ do
+ {
+ convert[sizeof(convert) - (++vallen)] = cvt[uvalue % 8];
+ uvalue = uvalue / 8;
+ } while (uvalue);
+ }
}
zeropad = Max(0, precision - vallen);