diff options
| author | Bruce Momjian <bruce@momjian.us> | 2000-10-08 19:37:56 +0000 |
|---|---|---|
| committer | Bruce Momjian <bruce@momjian.us> | 2000-10-08 19:37:56 +0000 |
| commit | 5383b5d8ed6da5c90bcbdb63401b7d1d75db563d (patch) | |
| tree | dcc17877a1d2cef8d267139f36078d53b8b471bf /src/interfaces/jdbc/org/postgresql/PG_Stream.java | |
| parent | 52cba15789c8c44f1edb9b6e3fb138736a550a58 (diff) | |
| download | postgresql-5383b5d8ed6da5c90bcbdb63401b7d1d75db563d.tar.gz | |
Okay, I have some new code in place that hopefully should work better. I
couldn't produce a full patch using cvs diff -c this time since I have
created new files and anonymous cvs usage doesn't allow you to
adds. I'm supplying the modified src/interfaces/jdbc as a tarball at :
http://www.candleweb.no/~gunnar/projects/pgsql/postgres-jdbc-2000-10-05.tgz
The new files that should be added are :
? org/postgresql/PGStatement.java
? org/postgresql/ObjectPool.java
? org/postgresql/ObjectPoolFactory.java
There is now a global static pool of free byte arrays and used byte arrays
connected to a statement object. This is the role of the new PGStatement
class. Access to the global free array is synchronized, while we rely on
the PG_Stream synchronization for the used array.
My measurements show that the perfomance boost on this code is not quite as
big as my last shot, but it is still an improvement. Maybe some of the
difference is due to the new synchronization on the global array. I think I
will look into choosing between on a connection level and global level.
I have also started experimented with improving the performance of the
various conversions. The problem here is ofcourse related handle the
various encodings. One thing I found to speed up ResultSet.getInt() a lot
was to do custom conversion on the byte array into int instead of going
through the getString() to do the conversion. But I'm unsure if this is
portable, can we assume that a digit never can be represented by more than
one byte ? It works fine in my iso-latin-8859-1 environment, but what about
other environments ? Maybe we could provide different ResultSet
implementations depending on the encoding used or delegate some methods of
the result set to an "converter class".
Check the org/postgresql/jdbc2/FastResultSet.java in the tarball above to
see the modified getInt() method.
Regards,
Gunnar
Diffstat (limited to 'src/interfaces/jdbc/org/postgresql/PG_Stream.java')
| -rw-r--r-- | src/interfaces/jdbc/org/postgresql/PG_Stream.java | 161 |
1 files changed, 147 insertions, 14 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/PG_Stream.java b/src/interfaces/jdbc/org/postgresql/PG_Stream.java index 22c41bdb3a..0e392fca09 100644 --- a/src/interfaces/jdbc/org/postgresql/PG_Stream.java +++ b/src/interfaces/jdbc/org/postgresql/PG_Stream.java @@ -22,7 +22,10 @@ public class PG_Stream private Socket connection; private InputStream pg_input; private BufferedOutputStream pg_output; - + + public PGStatement executingStatement; + + /** * Constructor: Connect to the PostgreSQL back end and return * a stream connection. @@ -45,6 +48,15 @@ public class PG_Stream } /** + * Set the currently executing statement. This is used to bind cached byte + * arrays to a Statement, so the statement can return the to the global + * pool of unused byte arrays when they are no longer inuse. + */ + public void setExecutingStatement(PGStatement executingStatement){ + this.executingStatement = executingStatement; + } + + /** * Sends a single character to the back end * * @param val the character to be sent @@ -70,7 +82,7 @@ public class PG_Stream */ public void SendInteger(int val, int siz) throws IOException { - byte[] buf = new byte[siz]; + byte[] buf = allocByteDim1(siz); while (siz-- > 0) { @@ -94,7 +106,7 @@ public class PG_Stream */ public void SendIntegerReverse(int val, int siz) throws IOException { - byte[] buf = new byte[siz]; + byte[] buf = allocByteDim1(siz); int p=0; while (siz-- > 0) { @@ -236,23 +248,52 @@ public class PG_Stream return n; } - public String ReceiveString(int maxsize) throws SQLException { - return ReceiveString(maxsize, null); - } - + /** * 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 + { + return ReceiveString(maxsiz, null); + } + + /** + * 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 * @param encoding the charset encoding to use. - * @param maxsiz maximum length of string in bytes * @return string from back end * @exception SQLException if an I/O error occurs */ public String ReceiveString(int maxsiz, String encoding) throws SQLException { - byte[] rst = new byte[maxsiz]; + byte[] rst = allocByteDim1(maxsiz); + return ReceiveString(rst, maxsiz, encoding); + } + + /** + * 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 rst byte array to read the String into. rst.length must + * equal to or greater than maxsize. + * @param maxsiz maximum length of string in bytes + * @param encoding the charset encoding to use. + * @return string from back end + * @exception SQLException if an I/O error occurs + */ + public String ReceiveString(byte rst[], int maxsiz, String encoding) + throws SQLException + { int s = 0; try @@ -262,9 +303,10 @@ public class PG_Stream int c = pg_input.read(); if (c < 0) throw new PSQLException("postgresql.stream.eof"); - else if (c == 0) - break; - else + else if (c == 0) { + rst[s] = 0; + break; + } else rst[s++] = (byte)c; } if (s >= maxsiz) @@ -299,7 +341,7 @@ public class PG_Stream { int i, bim = (nf + 7)/8; byte[] bitmask = Receive(bim); - byte[][] answer = new byte[nf][0]; + byte[][] answer = allocByteDim2(nf); int whichbit = 0x80; int whichbyte = 0; @@ -337,7 +379,7 @@ public class PG_Stream */ private byte[] Receive(int siz) throws SQLException { - byte[] answer = new byte[siz]; + byte[] answer = allocByteDim1(siz); Receive(answer,0,siz); return answer; } @@ -395,4 +437,95 @@ public class PG_Stream pg_input.close(); connection.close(); } + + /** + * Deallocate all resources that has been associated with any previous + * query. + */ + public void deallocate(PGStatement stmt){ + + for(int i = 0; i < maxsize_dim1; i++){ + synchronized(notusemap_dim1[i]){ + notusemap_dim1[i].addAll(stmt.inusemap_dim1[i]); + } + stmt.inusemap_dim1[i].clear(); + } + + for(int i = 0; i < maxsize_dim2; i++){ + synchronized(notusemap_dim2[i]){ + notusemap_dim2[i].addAll(stmt.inusemap_dim2[i]); + } + stmt.inusemap_dim2[i].clear(); + } + } + + public static final int maxsize_dim1 = 256; + public static ObjectPool notusemap_dim1[] = new ObjectPool[maxsize_dim1]; + public static byte binit[][] = new byte[maxsize_dim1][0]; + public static final int maxsize_dim2 = 32; + public static ObjectPool notusemap_dim2[] = new ObjectPool[maxsize_dim2]; + public static ObjectPoolFactory factory_dim1; + public static ObjectPoolFactory factory_dim2; + + static { + for(int i = 0; i < maxsize_dim1; i++){ + binit[i] = new byte[i]; + notusemap_dim1[i] = new ObjectPool(); + } + for(int i = 0; i < maxsize_dim2; i++){ + notusemap_dim2[i] = new ObjectPool(); + } + factory_dim1 = ObjectPoolFactory.getInstance(maxsize_dim1); + factory_dim2 = ObjectPoolFactory.getInstance(maxsize_dim2); + } + + public byte[] allocByteDim1(int size){ + if(size >= maxsize_dim1 || executingStatement == null){ + return new byte[size]; + } + ObjectPool not_usel = notusemap_dim1[size]; + ObjectPool in_usel = executingStatement.inusemap_dim1[size]; + + byte b[] = null; + + synchronized(not_usel){ + if(!not_usel.isEmpty()) { + Object o = not_usel.remove(); + b = (byte[]) o; + } else { + b = new byte[size]; + } + } + in_usel.add(b); + + return b; + } + + public byte[][] allocByteDim2(int size){ + if(size >= maxsize_dim2 || executingStatement == null){ + return new byte[size][0]; + } + ObjectPool not_usel = notusemap_dim2[size]; + ObjectPool in_usel = executingStatement.inusemap_dim2[size]; + + byte b[][] = null; + + synchronized(not_usel){ + if(!not_usel.isEmpty()) { + Object o = not_usel.remove(); + b = (byte[][]) o; + } else + b = new byte[size][0]; + + in_usel.add(b); + } + + return b; + } + } + + + + + |
