Fast BigDecimal - Mailing list pgsql-jdbc

From Heikki Linnakangas
Subject Fast BigDecimal
Date
Msg-id 49E72C90.9010903@enterprisedb.com
Whole thread Raw
Responses Re: Fast BigDecimal  (Kris Jurka <books@ejurka.com>)
Unit tests and ordering  (John Lister <john.lister-ps@kickstone.com>)
List pgsql-jdbc
Here's another patch I put together while trying to improve performance
for the customer that bumped into the repeated Describe thing yesterday.
It speeds up ResultSet.getBigDecimal() with the same fastpath
implementation we have for getInt and getLong.

I'm testing this with a test program that reads 10000 rows from a table
with 100 numeric columns, calling getBigDecimal() on each column. This
patch cuts the execution time roughly in half, from 2.4s to 1.2s.

--
   Heikki Linnakangas
   EnterpriseDB   http://www.enterprisedb.com
Index: org/postgresql/jdbc2/AbstractJdbc2ResultSet.java
===================================================================
RCS file: /cvsroot/jdbc/pgjdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java,v
retrieving revision 1.105
diff -u -r1.105 AbstractJdbc2ResultSet.java
--- org/postgresql/jdbc2/AbstractJdbc2ResultSet.java    30 Sep 2008 04:34:51 -0000    1.105
+++ org/postgresql/jdbc2/AbstractJdbc2ResultSet.java    16 Apr 2009 13:01:21 -0000
@@ -2137,6 +2137,65 @@
         return val;
     }

+    /**
+     * Optimised byte[] to number parser.  This code does not
+     * handle null values, so the caller must do checkResultSet
+     * and handle null values prior to calling this function.
+     *
+     * @param columnIndex The column to parse.
+     * @return The parsed number.
+     * @throws SQLException If an error occurs while fetching column.
+     * @throws NumberFormatException If the number is invalid or the
+     * out of range for fast parsing. The value must then be parsed by
+     * {@link #toBigDecimal(String)}.
+     */
+    private BigDecimal getFastBigDecimal(int columnIndex) throws SQLException,
+        NumberFormatException {
+
+        byte[] bytes = this_row[columnIndex - 1];
+
+        if (bytes.length == 0) {
+            throw FAST_NUMBER_FAILED;
+        }
+
+        int scale = 0;
+        long val = 0;
+        int start;
+        boolean neg;
+        if (bytes[0] == '-') {
+            neg = true;
+            start = 1;
+            if (bytes.length > 19) {
+                throw FAST_NUMBER_FAILED;
+            }
+        } else {
+            start = 0;
+            neg = false;
+            if (bytes.length > 18) {
+                throw FAST_NUMBER_FAILED;
+            }
+        }
+
+        while (start < bytes.length) {
+            byte b = bytes[start++];
+            if (b < '0' || b > '9') {
+                if (b == '.') {
+                    scale = bytes.length - start;
+                    continue;
+                } else
+                    throw FAST_NUMBER_FAILED;
+            }
+            val *= 10;
+            val += b - '0';
+        }
+
+        if (neg) {
+            val = -val;
+        }
+
+        return BigDecimal.valueOf(val, scale);
+    }
+
     public float getFloat(int columnIndex) throws SQLException
     {
         checkResultSet(columnIndex);
@@ -2161,6 +2220,14 @@
         if (wasNullFlag)
             return null;

+        Encoding encoding = connection.getEncoding();
+        if (encoding.hasAsciiNumbers()) {
+            try {
+                return getFastBigDecimal(columnIndex);
+            } catch (NumberFormatException ex) {
+            }
+        }
+
         return toBigDecimal( getFixedString(columnIndex), scale );
     }


pgsql-jdbc by date:

Previous
From: John Lister
Date:
Subject: Re: Query preparation
Next
From: Kris Jurka
Date:
Subject: Re: Fast BigDecimal