pg.ddx.io pgsql-performance@postgresql.org mailing list archive
help / color / mirror / Atom feed From: Andres Freund <andres@anarazel.de>
Subject: [PATCH] Hand code string to int32 conversion for performance.
Date: Fri, 8 Dec 2017 13:31:15 -0800
---
src/backend/utils/adt/int.c | 2 +-
src/backend/utils/adt/numutils.c | 90 ++++++++++++++++++++++++++++++++++++++++
src/include/utils/builtins.h | 1 +
3 files changed, 92 insertions(+), 1 deletion(-)
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index 4cd8960b3fc..8af4f8f3f7a 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -267,7 +267,7 @@ int4in(PG_FUNCTION_ARGS)
{
char *num = PG_GETARG_CSTRING(0);
- PG_RETURN_INT32(pg_atoi(num, sizeof(int32), '\0'));
+ PG_RETURN_INT32(pg_strto32(num));
}
/*
diff --git a/src/backend/utils/adt/numutils.c b/src/backend/utils/adt/numutils.c
index 244904ea940..f2281f86dae 100644
--- a/src/backend/utils/adt/numutils.c
+++ b/src/backend/utils/adt/numutils.c
@@ -18,6 +18,7 @@
#include <limits.h>
#include <ctype.h>
+#include "common/int.h"
#include "utils/builtins.h"
/*
@@ -108,6 +109,95 @@ pg_atoi(const char *s, int size, int c)
return (int32) l;
}
+
+/*
+ * Convert input string to a 32 bit integer.
+ *
+ * Allows any number of leading or trailing whitespace characters. This will
+ * throw ereport() upon bad input format or overflow.
+ *
+ * NB: Accumulate input as a negative number, to deal with two's complement
+ * representation of the most negative number, which can't be represented as a
+ * positive number.
+ */
+int32
+pg_strto32(const char *s)
+{
+ const char *in = s;
+ int32 tmp = 0;
+ bool neg = 0;
+
+
+ /* skip leading spaces */
+ while (likely(*in) && isspace((unsigned char) *in))
+ in++;
+
+ /* handle sign */
+ if (*in == '-')
+ {
+ in++;
+ neg = true;
+ }
+ else if (*in == '+')
+ in++;
+
+ /* require at least one digit */
+ if (unlikely(!isdigit((unsigned char) *in)))
+ goto err;
+
+ /* process digits */
+ while (true)
+ {
+ if (!*in)
+ goto out;
+ if (!isdigit((unsigned char) *in))
+ goto checkspace;
+
+ /* accumulate input */
+ if (unlikely(pg_mul32_overflow(tmp, 10, &tmp)) ||
+ unlikely(pg_sub32_overflow(tmp, *in - '0', &tmp)))
+ goto overflow;
+ in++;
+ }
+
+checkspace:
+ /* allow trailing whitespace, but not other trailing chars */
+ while (*in != '\0' && isspace((unsigned char) *in))
+ in++;
+
+ if (unlikely(*in != '\0'))
+ goto err;
+
+out:
+ /*
+ * Accumulated input as a negative number, so adjust if that's not what's
+ * needed.
+ */
+ if (!neg)
+ {
+ /* could fail if input is most negative number */
+ if (unlikely(tmp == PG_INT32_MIN))
+ goto overflow;
+
+ return -tmp;
+ }
+
+ return tmp;
+
+overflow:
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("value \"%s\" is out of range for type %s",
+ s, "integer")));
+
+err:
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for integer: \"%s\"",
+ s)));
+}
+
+
/*
* pg_itoa: converts a signed 16-bit integer to its string representation
*
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 762532f6369..fa45c84b752 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -43,6 +43,7 @@ extern int namestrcmp(Name name, const char *str);
/* numutils.c */
extern int32 pg_atoi(const char *s, int size, int c);
+extern int32 pg_strto32(const char *s);
extern void pg_itoa(int16 i, char *a);
extern void pg_ltoa(int32 l, char *a);
extern void pg_lltoa(int64 ll, char *a);
--
2.14.1.536.g6867272d5b.dirty
--wz6zoied66px3bgz--
Message-ID: <no-message-id-7371@localhost>
Permalink: ../no-message-id-7371@localhost/
Also on: postgresql.org/message-id/no-message-id-7371@localhost
copy link · copy postgr.es
reply Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-performance@postgresql.org
Cc: andres@anarazel.de
Subject: Re: [PATCH] Hand code string to int32 conversion for performance.
In-Reply-To: <no-message-id-7371@localhost>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox