nit-pick optimization for findColumn() - Mailing list pgsql-jdbc

From Peter Speck
Subject nit-pick optimization for findColumn()
Date
Msg-id 4CDDFBBC-9EB3-11D7-BE5A-0030654BB35C@ruc.dk
Whole thread Raw
Responses Re: nit-pick optimization for findColumn()
List 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..."

pgsql-jdbc by date:

Previous
From: Erik Price
Date:
Subject: Re: pg JDBC driver feature question
Next
From: Barry Lind
Date:
Subject: Re: pg JDBC driver feature question