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
Unit tests and ordering |
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: