Received: from beertje.william.bogus (p503.vcu.wanadoo.nl [194.134.201.67]) by hub.org (8.10.1/8.10.1) with ESMTP id e6UGE6B44593 for ; Sun, 30 Jul 2000 12:14:08 -0400 (EDT) Received: (from williamc@localhost) by beertje.william.bogus (8.9.3/8.8.7) id SAA02908; Sun, 30 Jul 2000 18:21:08 +0200 Date: Sun, 30 Jul 2000 18:21:08 +0200 Message-Id: <200007301621.SAA02908@beertje.william.bogus> X-Authentication-Warning: beertje.william.bogus: williamc set sender to williamc@paneris.org using -f From: William Chesters To: pgsql-interfaces@postgresql.org Cc: melati_development@messageboards.paneris.org Subject: JDBC driver GREATLY speeded up by trivial fix X-Archive-Number: 200007/202 First, sorry if this has been discussed before---I'm working with the JDBC driver from the Postgresql 7.0 distribution. I recently had occasion to run a profiler over an app, and discovered that it was spending a lot of its time at the following line in org.postgresql.PG_Stream.ReceiveString: byte[] rst = new byte[maxsiz]; The point is that maxsiz is typically 8192, while the number of bytes actually read into the buffer is the length of a field name (i.e. never more than about 20). The resulting performance hit is absolutely horrendous---the fact that the poor JVM has to zero-initialise the array is bad enough, but think of the effect on the CPU cache and the garbage collector! My replacement for this routine is given below. It's not obviously the fastest possible implementation, but the effect on the performance of database-intensive applications is just _unreal_: I mean integer factors, rather than a few percent. I don't want to diss the efforts of the drivers' authors, but I couldn't help noticing a few other horrors lurking around, like in ResultSet.getDate and .getTimestamp both doing new SimpleDateFormat every time they are called, which is pretty expensive if you look at Sun's sources. [Incidentally .getTimestamp is broken by the 7.0 backend ...] Is it being actively maintained? Can I help? Best wishes, William private static final class FinalByteArrayOutputStream extends ByteArrayOutputStream { public FinalByteArrayOutputStream(int size) { super(size); } } /** * Receives a null-terminated string from the backend. Maximum of * maxsiz bytes - if we don't see a null, then we assume something * has gone wrong. * * @param maxsiz maximum length of string * @return string from back end * @exception SQLException if an I/O error occurs */ public String ReceiveString(int maxsiz) throws SQLException { FinalByteArrayOutputStream buf = new FinalByteArrayOutputStream(20); try { for (;;) { if (buf.size() >= maxsiz) throw new PSQLException("postgresql.stream.toomuch"); int c = pg_input.read(); if (c < 0) throw new PSQLException("postgresql.stream.eof"); else if (c == 0) break; else buf.write(c); } } catch (IOException e) { throw new PSQLException("postgresql.stream.ioerror",e); } return buf.toString(0); }