Re: Why is JDBC so slow? - Mailing list pgsql-jdbc

From Oliver Jowett
Subject Re: Why is JDBC so slow?
Date
Msg-id 20030902223540.GC26230@opencloud.com
Whole thread Raw
In response to Re: Why is JDBC so slow?  (Oliver Jowett <oliver@opencloud.com>)
List pgsql-jdbc
On Wed, Sep 03, 2003 at 09:59:51AM +1200, Oliver Jowett wrote:
> On Tue, Sep 02, 2003 at 02:05:15PM -0400, Joseph Shraibman wrote:
> > For this test I created a table named tt with ten entries in it.  These
> > selects thus select 10^6 rows.  As you can see time for jdbc is much
> > slower than psql.  Why is this?
>
> > ]$ time java -Xmx256m JDBCclient -U postgres -h localhost -c "select
> > 'blah' from tt tta, tt ttb, tt ttc, tt ttd, tt tte, tt ttf;" playpen >
> > /dev/null
> >
> > real    0m27.271s
> > user    0m21.040s
> > sys     0m0.710s
>
> With those heap settings you spend a lot of time doing GC. As pointed out by
> others you can reduce the memory footprint of the driver via setFetchSize().
> A quick estimate from the GC output shows that about 50% of allocations
> immediately become garbage, which can probably be improved on if it's coming
> from the driver. That's not an unusual allocation pattern for java programs,
> though.

Some quick heap profiling gives me (10^5 dataset):

          percent         live       alloc'ed  stack class
 rank   self  accum    bytes objs   bytes objs trace name
    1 31.39% 31.39%  9321928  272 9321928  272     1 [I
        (this is a profiling artifact)

    2  8.08% 39.47%  2400048 100002 2400048 100002   763 java.lang.String
        org.postgresql.core.Encoding.decodeUTF8(Encoding.java:283)
        org.postgresql.core.Encoding.decode(Encoding.java:181)
        org.postgresql.core.Encoding.decode(Encoding.java:197)
        org.postgresql.jdbc1.AbstractJdbc1ResultSet.getString(AbstractJdbc1ResultSet.java:179)

    3  8.08% 47.55%  2400048 100002 2400048 100002   764 [C
        java.lang.String.<init>(String.java:200)
        org.postgresql.core.Encoding.decodeUTF8(Encoding.java:283)
        org.postgresql.core.Encoding.decode(Encoding.java:181)
        org.postgresql.core.Encoding.decode(Encoding.java:197)

    4  5.39% 52.94%  1600160 100004 1600160 100004   709 [B
        org.postgresql.core.PGStream.Receive(PGStream.java:369)
        org.postgresql.core.PGStream.ReceiveTupleV2(PGStream.java:354)
        org.postgresql.core.QueryExecutor.receiveTupleV2(QueryExecutor.java:399)
        org.postgresql.core.QueryExecutor.executeV2(QueryExecutor.java:247)

    5  5.39% 58.33%  1600064 100004 1600064 100004   708 [B
        org.postgresql.core.PGStream.ReceiveTupleV2(PGStream.java:331)
        org.postgresql.core.QueryExecutor.receiveTupleV2(QueryExecutor.java:399)
        org.postgresql.core.QueryExecutor.executeV2(QueryExecutor.java:247)
        org.postgresql.core.QueryExecutor.execute(QueryExecutor.java:104)

    6  5.39% 63.71%  1600056 100003 1600056 100003   708 <Unknown_class>
        (same trace as above; this appears to be a byte[][] object)

    7  5.39% 69.10%  1600048 100003 1600048 100003   707 [B
        org.postgresql.core.PGStream.Receive(PGStream.java:369)
        org.postgresql.core.PGStream.ReceiveTupleV2(PGStream.java:330)
        org.postgresql.core.QueryExecutor.receiveTupleV2(QueryExecutor.java:399)
        org.postgresql.core.QueryExecutor.executeV2(QueryExecutor.java:247)

    8  5.39% 74.49%  1600000 100000 1600000 100000   795 java.lang.Object
        JDBCclient.getResults(JDBCclient.java:26)
        JDBCclient.doQuery(JDBCclient.java:15)
        JDBCclient.main(JDBCclient.java:95)

    9  5.39% 79.88%  1600000 100000 1600000 100000   815 java.lang.Integer
        org.postgresql.jdbc1.AbstractJdbc1Connection.getPGType(AbstractJdbc1Connection.java:1670)
        org.postgresql.core.Field.getPGType(Field.java:100)
        org.postgresql.jdbc2.AbstractJdbc2ResultSet.getObject(AbstractJdbc2ResultSet.java:150)
        JDBCclient.getResults(JDBCclient.java:30)

   10  5.39% 85.26%  1600000 100000 1600000 100000   797 java.lang.Integer
        org.postgresql.jdbc1.AbstractJdbc1Connection.getSQLType(AbstractJdbc1Connection.java:1593)
        org.postgresql.core.Field.getSQLType(Field.java:111)
        org.postgresql.jdbc2.AbstractJdbc2ResultSet.getObject(AbstractJdbc2ResultSet.java:105)
        JDBCclient.getResults(JDBCclient.java:30)

   11  5.39% 90.65%  1600000 100000 1600000 100000   796 <Unknown_class>
        org.postgresql.jdbc1.AbstractJdbc1ResultSet.next(AbstractJdbc1ResultSet.java:152)
        JDBCclient.getResults(JDBCclient.java:28)
        JDBCclient.doQuery(JDBCclient.java:15)
        JDBCclient.main(JDBCclient.java:95)

   12  4.41% 95.06%  1310864   14 1310864   14   785 java.lang.Object
        java.util.Vector.ensureCapacityHelper(Vector.java:222)
        java.util.Vector.addElement(Vector.java:584)
        org.postgresql.core.QueryExecutor.receiveTupleV2(QueryExecutor.java:403)
        org.postgresql.core.QueryExecutor.executeV2(QueryExecutor.java:247)

   13  1.35% 96.41%   400016    1  400016    1   795 <Unknown_class>
        JDBCclient.getResults(JDBCclient.java:26)
        JDBCclient.doQuery(JDBCclient.java:15)
        JDBCclient.main(JDBCclient.java:95)

Of these:

 #1 is a profiling artifact.
 #2 and #3 are unavoidable without changing the client.
 #4, #5, #7 are unavoidable without using setFetchSize() or a major resultset overhaul (resultsets are internally
storedas a byte[][]) 
 #8 is directly client-generated.
 #9, #10 could be fixed (temporary Integer objects used only to key the oid/type caches)
 #11 could be fixed (row_buffer is reallocated on every row even if it has not changed size.. and is always copied into
evenif no updates are ever done) 
 #12 is unavoidable unless the backend protocol provides a row count ahead of time (I don't think it does?)
 #13 is directly client-generated.

So some lowhanging fruit there, but not much.

-O


pgsql-jdbc by date:

Previous
From: Paul Thomas
Date:
Subject: Re: Why is JDBC so slow?
Next
From: Joseph Shraibman
Date:
Subject: Re: Why is JDBC so slow?