src/port/snprintf.c: Optimize the common base=10 case in fmtint

Поиск
Список
Период
Сортировка
От Arjan van de Ven
Тема src/port/snprintf.c: Optimize the common base=10 case in fmtint
Дата
Msg-id 40a4b32a-b841-4667-11b2-a0baedb12714@linux.intel.com
обсуждение исходный текст
Ответы Re: src/port/snprintf.c: Optimize the common base=10 case in fmtint
Re: src/port/snprintf.c: Optimize the common base=10 case in fmtint
Список pgsql-hackers
src/port/snprintf.c: Optimize the common base=10 case in fmtint

fmtint() turns an integer into a string for a given base, and to do this
it does a divide/modulo operation iteratively.

On just about any CPU, divides are a pretty expensive operation, generally
10x to 20x or more expensive than adds or multiplies.

By special casing the super common case of base==10, the (gcc) compiler can (and will)
replace the divide by a multiply with 0xcccccccccccccccd, yielding a lot faster code.
(fmtint dropped drastically in the perf profiles after this change)

Even though this only shows up in the database creation phase of pgbench and not so much
during the normal run time, the optimization is simple and high value enough that
in my opinion it's worth doing




diff --git a/src/port/snprintf.c b/src/port/snprintf.c
index 7c21429369..5957e6f2aa 100644
--- a/src/port/snprintf.c
+++ b/src/port/snprintf.c
@@ -1076,11 +1076,24 @@ fmtint(long long value, char type, int forcesign, int leftjust,
      else
      {
          /* make integer string */
-        do
-        {
-            convert[sizeof(convert) - (++vallen)] = cvt[uvalue % base];
-            uvalue = uvalue / base;
-        } while (uvalue);
+
+        /*
+         * Special case a base of 10 because it is super common and by special casing the compiler can
+         * avoid an expensive divide operation (the compiler will use a multiply for this)
+         */
+        if (likely(base == 10)) {
+            do
+            {
+                convert[sizeof(convert) - (++vallen)] = cvt[uvalue % 10];
+                uvalue = uvalue / 10;
+            } while (uvalue);
+        } else {
+            do
+            {
+                convert[sizeof(convert) - (++vallen)] = cvt[uvalue % base];
+                uvalue = uvalue / base;
+            } while (uvalue);
+        }
      }

      zeropad = Max(0, precision - vallen);



В списке pgsql-hackers по дате отправления:

Предыдущее
От: Fujii Masao
Дата:
Сообщение: Re: Allow pg_signal_backend members to use pg_log_backend_memory_stats().
Следующее
От: Robert Haas
Дата:
Сообщение: Re: Refactoring: join MakeSingleTupleTableSlot() and MakeTupleTableSlot()