nit-pick optimization for findColumn()

From: Peter Speck <speck(at)ruc(dot)dk>
To: pgsql-jdbc(at)postgresql(dot)org
Subject: nit-pick optimization for findColumn()
Date: 2003-06-14 21:58:15
Message-ID: 4CDDFBBC-9EB3-11D7-BE5A-0030654BB35C@ruc.dk
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-jdbc

Hi,

(I have not submitted this to the patch list, as I do not know if I
should do that, or if there is a jdbc maintainer which gatekeeps
patches)

A very small optimization, but anyway. findColumn() uses
String.equalsIgnoreCase() which is slow. I've made a simple
optimization which first tries a simple ASCII ignorecase loop, and
falls back to equalsIgnoreCase if the simple loop can't find the column
(should only happend if you have non-ascii characters in the name).

Using findColumn from 7.3.3:
Time for test: 1446 msecs.
Time for TEST: 2382 msecs.
Time for TeSt: 1975 msecs.
Time for héllo: 6342 msecs.
Time for HÉLLO: 7511 msecs.
Time for col_1: 556 msecs.
Time for col_2: 1488 msecs. // long common prefix
Time for col_3: 2421 msecs.
Time for col_4: 3286 msecs.
Time for col_5: 4227 msecs.

Using optimized findColumn:
Time for test: 767 msecs.
Time for TEST: 777 msecs.
Time for TeSt: 777 msecs.
Time for héllo: 1443 msecs.
Time for HÉLLO: 8626 msecs.
Time for col_1: 613 msecs.
Time for col_2: 1109 msecs.
Time for col_3: 1651 msecs.
Time for col_4: 2087 msecs.
Time for col_5: 2622 msecs.

(java 1.4.1, PowerPC, Mac OS X 10.2.6)

@@@@@@@@@@@@@ DIFF FOR CVS HEAD @@@@@@@@@@@@@@

Index:
pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/
AbstractJdbc1ResultSet.java
===================================================================
RCS file:
/projects/cvsroot/pgsql-server/src/interfaces/jdbc/org/postgresql/
jdbc1/AbstractJdbc1ResultSet.java,v
retrieving revision 1.12
diff -u -d -b -w -r1.12 AbstractJdbc1ResultSet.java
---
pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/
AbstractJdbc1ResultSet.java 3 May 2003 20:40:45 -0000 1.12
+++
pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/
AbstractJdbc1ResultSet.java 14 Jun 2003 21:50:27 -0000
@@ -607,6 +607,25 @@
int i;

final int flen = fields.length;
+ final int cnlen = columnName.length();
+ for (i = 0 ; i < flen; ++i) {
+ String fieldName = fields[i].getName();
+ if (fieldName.length() != cnlen)
+ continue;
+ int j = 0;
+ while (true) {
+ int ch1 = columnName.charAt(j);
+ int ch2 = fieldName.charAt(j);
+ if (ch1 >= 'A' && ch1 <= 'Z')
+ ch1 += 'a' - 'A';
+ if (ch2 >= 'A' && ch2 <= 'Z')
+ ch2 += 'a' - 'A';
+ if (ch1 != ch2)
+ break;
+ if (++j >= cnlen)
+ return i + 1;
+ }
+ }
for (i = 0 ; i < flen; ++i)
if
(fields[i].getName().equalsIgnoreCase(columnName))
return (i + 1);

@@@@@@@@@@@@@ DIFF FOR 7.3.3 @@@@@@@@@@@@@@

--- org/postgresql/jdbc1/orig-AbstractJdbc1ResultSet.java Tue Jan
14 10:15:35 2003
+++ org/postgresql/jdbc1/AbstractJdbc1ResultSet.java Sat Jun 14
23:24:09 2003
@@ -522,6 +522,25 @@
int i;

final int flen = fields.length;
+ final int cnlen = columnName.length();
+ for (i = 0 ; i < flen; ++i) {
+ String fieldName = fields[i].getName();
+ if (fieldName.length() != cnlen)
+ continue;
+ int j = 0;
+ while (true) {
+ int ch1 = columnName.charAt(j);
+ int ch2 = fieldName.charAt(j);
+ if (ch1 >= 'A' && ch1 <= 'Z')
+ ch1 += 'a' - 'A';
+ if (ch2 >= 'A' && ch2 <= 'Z')
+ ch2 += 'a' - 'A';
+ if (ch1 != ch2)
+ break;
+ if (++j >= cnlen)
+ return i + 1;
+ }
+ }
for (i = 0 ; i < flen; ++i)
if
(fields[i].getName().equalsIgnoreCase(columnName))
return (i + 1);

// TEST APPLICATION.

import java.sql.*;

public class test
{
// must pass connection URL as first argument.
public static void main(String[] argv)
{
try {
DriverManager.registerDriver(new org.postgresql.Driver());
Connection conn = DriverManager.getConnection(argv[0]);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(
"SELECT\n" +
" 1 as col_1,\n" +
" 2 as col_2,\n" +
" 3 as col_3,\n" +
" 4 as col_4,\n" +
" 5 as col_5,\n" +
" 6 as col_6,\n" +
" 7 as col_7,\n" +
" 8 as \"héllo\",\n" + // with accent: e´
" 9 as warm_up,\n" +
" 0 as test\n");
time(rs, 9, "warm_up");
time(rs, 9, "warm_up");
time(rs, 10, "test");
time(rs, 10, "TEST");
time(rs, 10, "TeSt");
time(rs, 8, "héllo");
time(rs, 8, "HÉLLO");
time(rs, 1, "col_1");
time(rs, 2, "col_2");
time(rs, 3, "col_3");
time(rs, 4, "col_4");
time(rs, 5, "col_5");
System.err.println(sb.toString());
}
catch (Exception ex) {
ex.printStackTrace();
}
}

static StringBuffer sb = new StringBuffer();
static void time(ResultSet rs, int wanted, String colName) throws
SQLException
{
if (rs.findColumn(colName) != wanted)
throw new SQLException("Fails for " + colName);
int num = 1000000;
long st0 = System.currentTimeMillis();
for (int i = num; i > 0; i--)
rs.findColumn(colName);
long st1 = System.currentTimeMillis();
sb.append(" Time for " + colName + ": " + (st1 - st0) + " msecs.\n");
}
}

// END OF FILE
----
- Peter Speck

"The difference between theory and practice
is small in theory and large in practice..."

Responses

Browse pgsql-jdbc by date

  From Date Subject
Next Message Erik Price 2003-06-16 15:55:33 Re: pg JDBC driver feature question
Previous Message Barry Lind 2003-06-14 01:05:16 Re: pg JDBC driver feature question