Thread: Re: [ADMIN] High memory usage [PATCH]

Re: [ADMIN] High memory usage [PATCH]

From
Bruce Momjian
Date:
JDBC folks, can you comment on this patch?  Thanks.


> Attached is my patch to the official 7.1.2 PreparedStatement.java class.
> This seems to work quite well for me in a test case. To try to reproduce the
> seen problem I will need to test all night. I'll report tomorrow.
>
> BTW, this is my first attempt at making a unified diff so I might have done
> something wrong. If this diff doesn't apply please tell me.
>
> --Rainer
>
> > -----Original Message-----
> > From: pgsql-admin-owner@postgresql.org
> > [mailto:pgsql-admin-owner@postgresql.org]On Behalf Of Rainer Mager
> > Sent: Wednesday, June 20, 2001 9:08 AM
> > To: Tom Lane
> > Cc: PostgreSQL Admin
> > Subject: RE: [ADMIN] High memory usage
> >
> >
> > I'll work on a patch but if someone has already done this I would be
> > grateful.

[ Attachment, skipping... ]

>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
--- PreparedStatement.java    Sat Feb 17 01:45:00 2001
+++ PreparedStatement.java.new    Wed Jun 20 12:34:57 2001
@@ -39,10 +39,12 @@
         // Some performance caches
         private StringBuffer sbuf = new StringBuffer();

-        // We use ThreadLocal for SimpleDateFormat's because they are not that
-        // thread safe, so each calling thread has its own object.
-        private ThreadLocal tl_df   = new ThreadLocal(); // setDate() SimpleDateFormat
-        private ThreadLocal tl_tsdf = new ThreadLocal(); // setTimestamp() SimpleDateFormat
+    // Because SimpleDateFormat is not thread safe we create one for each
+    // PreparedStatemnt here AND synchronize on it for each usage.
+    // We can NOT use ThreadLocal because they are not freed until the thread
+    // completes. This would be a memory leak for long running threads.
+    private SimpleDateFormat df = null;
+    private SimpleDateFormat tsdf = null;

     /**
      * Constructor for the PreparedStatement class.
@@ -90,9 +92,6 @@
          * New in 7.1 - overides Statement.close() to dispose of a few local objects
          */
         public void close() throws SQLException {
-          // free the ThreadLocal caches
-          tl_df.set(null);
-
           super.close();
         }

@@ -332,14 +331,18 @@
      */
     public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
     {
-          SimpleDateFormat df = (SimpleDateFormat) tl_df.get();
-          if(df==null) {
+        // The df DateFormat is initialized here to delay creation until needed.
+        if( df == null ) {
+            synchronized( this ) {
+                if( df == null ) {
             df = new SimpleDateFormat("''yyyy-MM-dd''");
-            tl_df.set(df);
+                }
+            }
           }

-      set(parameterIndex, df.format(x));
-
+        // We must synchronize here because SimpleDateFormat is not thread safe.
+        synchronized( df ) {
+            set( parameterIndex, df.format(x) );
       // The above is how the date should be handled.
       //
       // However, in JDK's prior to 1.1.6 (confirmed with the
@@ -351,6 +354,7 @@
       //
       //set(parameterIndex, df.format(new java.util.Date(x.getTime()+86400000)));
     }
+    }

     /**
      * Set a parameter to a java.sql.Time value.  The driver converts
@@ -375,17 +379,22 @@
      */
     public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
         {
-          SimpleDateFormat df = (SimpleDateFormat) tl_tsdf.get();
-          if(df==null) {
-            df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-            tl_tsdf.set(df);
+        // The tsdf DateFormat is initialized here to delay creation until needed.
+        if( tsdf == null ) {
+            synchronized( this ) {
+                if( tsdf == null ) {
+                    tsdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                    tsdf.setTimeZone(TimeZone.getTimeZone("GMT"));
+                }
+            }
           }
-          df.setTimeZone(TimeZone.getTimeZone("GMT"));

+        // We must synchronize here because SimpleDateFormat is not thread safe.
+        synchronized( tsdf ) {
           // Use the shared StringBuffer
           synchronized(sbuf) {
             sbuf.setLength(0);
-            sbuf.append("'").append(df.format(x)).append('.').append(x.getNanos()/10000000).append("+00'");
+                sbuf.append("'").append(tsdf.format(x)).append('.').append(x.getNanos()/10000000).append("+00'");
             set(parameterIndex, sbuf.toString());
           }

@@ -393,6 +402,7 @@
           // to be identical. Pays to read the docs ;-)
           //set(parameterIndex,"'"+x.toString()+"'");
     }
+    }

     /**
      * When a very large ASCII value is input to a LONGVARCHAR parameter,

Re: Re: [ADMIN] High memory usage [PATCH]

From
"Dave Cramer"
Date:
my two cents worth...

1) what is the problem that this is trying to solve, I assume from the
subject that it is some sort of high memory usage?
2) I am trying to understand how a statement would ever be used by more than
one thread at a time? I would think that it would be impossible to share
statements across threads.
3) The double locking method used is alledgedly unsafe on SMP machines
http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double_p.html.


Dave




----- Original Message -----
From: "Bruce Momjian" <pgman@candle.pha.pa.us>
To: "Rainer Mager" <rmager@vgkk.com>
Cc: "PostgreSQL jdbc list" <pgsql-jdbc@postgresql.org>; "PostgreSQL-patches"
<pgsql-patches@postgresql.org>
Sent: Thursday, June 21, 2001 6:23 PM
Subject: [JDBC] Re: [ADMIN] High memory usage [PATCH]


>
> JDBC folks, can you comment on this patch?  Thanks.
>
>
> > Attached is my patch to the official 7.1.2 PreparedStatement.java class.
> > This seems to work quite well for me in a test case. To try to reproduce
the
> > seen problem I will need to test all night. I'll report tomorrow.
> >
> > BTW, this is my first attempt at making a unified diff so I might have
done
> > something wrong. If this diff doesn't apply please tell me.
> >
> > --Rainer
> >
> > > -----Original Message-----
> > > From: pgsql-admin-owner@postgresql.org
> > > [mailto:pgsql-admin-owner@postgresql.org]On Behalf Of Rainer Mager
> > > Sent: Wednesday, June 20, 2001 9:08 AM
> > > To: Tom Lane
> > > Cc: PostgreSQL Admin
> > > Subject: RE: [ADMIN] High memory usage
> > >
> > >
> > > I'll work on a patch but if someone has already done this I would be
> > > grateful.
>
> [ Attachment, skipping... ]
>
> >
> > ---------------------------(end of broadcast)---------------------------
> > TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
>
> --
>   Bruce Momjian                        |  http://candle.pha.pa.us
>   pgman@candle.pha.pa.us               |  (610) 853-3000
>   +  If your life is a hard drive,     |  830 Blythe Avenue
>   +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
>


----------------------------------------------------------------------------
----


> --- PreparedStatement.java Sat Feb 17 01:45:00 2001
> +++ PreparedStatement.java.new Wed Jun 20 12:34:57 2001
> @@ -39,10 +39,12 @@
>          // Some performance caches
>          private StringBuffer sbuf = new StringBuffer();
>
> -        // We use ThreadLocal for SimpleDateFormat's because they are not
that
> -        // thread safe, so each calling thread has its own object.
> -        private ThreadLocal tl_df   = new ThreadLocal(); // setDate()
SimpleDateFormat
> -        private ThreadLocal tl_tsdf = new ThreadLocal(); //
setTimestamp() SimpleDateFormat
> + // Because SimpleDateFormat is not thread safe we create one for each
> + // PreparedStatemnt here AND synchronize on it for each usage.
> + // We can NOT use ThreadLocal because they are not freed until the
thread
> + // completes. This would be a memory leak for long running threads.
> + private SimpleDateFormat df = null;
> + private SimpleDateFormat tsdf = null;
>
>   /**
>   * Constructor for the PreparedStatement class.
> @@ -90,9 +92,6 @@
>           * New in 7.1 - overides Statement.close() to dispose of a few
local objects
>           */
>          public void close() throws SQLException {
> -          // free the ThreadLocal caches
> -          tl_df.set(null);
> -
>            super.close();
>          }
>
> @@ -332,14 +331,18 @@
>   */
>   public void setDate(int parameterIndex, java.sql.Date x) throws
SQLException
>   {
> -          SimpleDateFormat df = (SimpleDateFormat) tl_df.get();
> -          if(df==null) {
> + // The df DateFormat is initialized here to delay creation until needed.
> + if( df == null ) {
> + synchronized( this ) {
> + if( df == null ) {
>              df = new SimpleDateFormat("''yyyy-MM-dd''");
> -            tl_df.set(df);
> + }
> + }
>            }
>
> -   set(parameterIndex, df.format(x));
> -
> + // We must synchronize here because SimpleDateFormat is not thread safe.
> + synchronized( df ) {
> + set( parameterIndex, df.format(x) );
>     // The above is how the date should be handled.
>     //
>     // However, in JDK's prior to 1.1.6 (confirmed with the
> @@ -351,6 +354,7 @@
>     //
>     //set(parameterIndex, df.format(new
java.util.Date(x.getTime()+86400000)));
>   }
> + }
>
>   /**
>   * Set a parameter to a java.sql.Time value.  The driver converts
> @@ -375,17 +379,22 @@
>   */
>   public void setTimestamp(int parameterIndex, Timestamp x) throws
SQLException
>          {
> -          SimpleDateFormat df = (SimpleDateFormat) tl_tsdf.get();
> -          if(df==null) {
> -            df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
> -            tl_tsdf.set(df);
> + // The tsdf DateFormat is initialized here to delay creation until
needed.
> + if( tsdf == null ) {
> + synchronized( this ) {
> + if( tsdf == null ) {
> + tsdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
> + tsdf.setTimeZone(TimeZone.getTimeZone("GMT"));
> + }
> + }
>            }
> -          df.setTimeZone(TimeZone.getTimeZone("GMT"));
>
> + // We must synchronize here because SimpleDateFormat is not thread safe.
> + synchronized( tsdf ) {
>            // Use the shared StringBuffer
>            synchronized(sbuf) {
>              sbuf.setLength(0);
> -
sbuf.append("'").append(df.format(x)).append('.').append(x.getNanos()/100000
00).append("+00'");
> +
sbuf.append("'").append(tsdf.format(x)).append('.').append(x.getNanos()/1000
0000).append("+00'");
>              set(parameterIndex, sbuf.toString());
>            }
>
> @@ -393,6 +402,7 @@
>            // to be identical. Pays to read the docs ;-)
>            //set(parameterIndex,"'"+x.toString()+"'");
>   }
> + }
>
>   /**
>   * When a very large ASCII value is input to a LONGVARCHAR parameter,
>


----------------------------------------------------------------------------
----


>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/users-lounge/docs/faq.html
>


Re: Re: [ADMIN] High memory usage [PATCH]

From
Gunnar Rønning
Date:
* "Dave Cramer" <Dave@micro-automation.net> wrote:
|
| my two cents worth...
|
| 1) what is the problem that this is trying to solve, I assume from the
| subject that it is some sort of high memory usage?

I would like to know as well.

| 2) I am trying to understand how a statement would ever be used by more than
| one thread at a time? I would think that it would be impossible to share
| statements across threads.

Quite easy. Just the same way as you share any other object across threads
and according to the JDBC spec requires that the driver shoudl be thread
safe.


| 3) The double locking method used is alledgedly unsafe on SMP machines
| http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double_p.html.

Yup, double checked locking is not going to guarantee that you get
properly initialized objects with the current Java spec.

--
Gunnar Rønning - gunnar@polygnosis.com
Senior Consultant, Polygnosis AS, http://www.polygnosis.com/

RE: Re: [ADMIN] High memory usage [PATCH]

From
"Rainer Mager"
Date:
Good questions, I'll answer what I can...

> 1) what is the problem that this is trying to solve, I assume from the
> subject that it is some sort of high memory usage?

Yes it involves memory usage and a memory leak. Basically, the way the code
was before the patch, each instantiation of a PreparedStatement created 2
new ThreadLocal objects. According to Sun's Javadocs, these objects are not
freed until the thread is completed. For a single thread app or main thread
of an application (in our case a server) the thread NEVER goes away.
Therefore these ThreadLocal objects just keep adding up and using memory,
forever.

The patch removes the use of these ThreadLocals.


> 2) I am trying to understand how a statement would ever be used
> by more than
> one thread at a time? I would think that it would be impossible to share
> statements across threads.

This I can't really answer. The code appeared to be written to be thread
safe so I attempted to continue that. Whether thread safe for a Statement is
necessary or not I can't directly say. Although, I agree with you, I can't
imagine a need to use a single Statement in multiple threads.


> 3) The double locking method used is alledgedly unsafe on SMP machines
> http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double_p.html.

Interesting. I wasn't aware of this. If question #2 is answered such that
thread safe isn't necessary, then this problem goes away pretty easily. If
thread safety is needed then this would have to be rewritten, I can look
into doing this if you like.


> Dave

--Rainer



Re: Re: [ADMIN] High memory usage [PATCH]

From
Gunnar Rønning
Date:
* "Rainer Mager" <rmager@vgkk.com> wrote:
|

| Interesting. I wasn't aware of this. If question #2 is answered such that
| thread safe isn't necessary, then this problem goes away pretty easily. If
| thread safety is needed then this would have to be rewritten, I can look
| into doing this if you like.

Thread safety is required by the spec. Do you have "JDBC API tutorial and
reference, 2 ed." from Addison Wesley ? This book contains a section for
JDBC driver writers and explains this issue.

regards,

        Gunnar

--
Gunnar Rønning - gunnar@polygnosis.com
Senior Consultant, Polygnosis AS, http://www.polygnosis.com/

Re: Re: [ADMIN] High memory usage [PATCH]

From
Michael Stephenson
Date:
[snip]

Wouldn't it be more elegant simply to make the ThreadLocal's static (as
I'd have thought was probably the intention of the original author), this
would remove the possiblity of any memory leaks in a single threaded
environment, and have the same affect ultimately in a multithreaded
environment?

Michael Stephenson


RE: Re: [ADMIN] High memory usage [PATCH]

From
"Dave Cramer"
Date:
I am going to have a look at the spec in more detail to see how they
expect the driver to be used within threads

I am in a similar situation wrt using the driver in server and will
check if the memory usage is better.

Dave

-----Original Message-----
From: pgsql-jdbc-owner@postgresql.org
[mailto:pgsql-jdbc-owner@postgresql.org] On Behalf Of Rainer Mager
Sent: June 22, 2001 12:56 AM
To: Dave Cramer; Bruce Momjian
Cc: PostgreSQL jdbc list
Subject: RE: [JDBC] Re: [ADMIN] High memory usage [PATCH]

Good questions, I'll answer what I can...

> 1) what is the problem that this is trying to solve, I assume from the
> subject that it is some sort of high memory usage?

Yes it involves memory usage and a memory leak. Basically, the way the
code
was before the patch, each instantiation of a PreparedStatement created
2
new ThreadLocal objects. According to Sun's Javadocs, these objects are
not
freed until the thread is completed. For a single thread app or main
thread
of an application (in our case a server) the thread NEVER goes away.
Therefore these ThreadLocal objects just keep adding up and using
memory,
forever.

The patch removes the use of these ThreadLocals.


> 2) I am trying to understand how a statement would ever be used
> by more than
> one thread at a time? I would think that it would be impossible to
share
> statements across threads.

This I can't really answer. The code appeared to be written to be thread
safe so I attempted to continue that. Whether thread safe for a
Statement is
necessary or not I can't directly say. Although, I agree with you, I
can't
imagine a need to use a single Statement in multiple threads.


> 3) The double locking method used is alledgedly unsafe on SMP machines
> http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double_p.html.

Interesting. I wasn't aware of this. If question #2 is answered such
that
thread safe isn't necessary, then this problem goes away pretty easily.
If
thread safety is needed then this would have to be rewritten, I can look
into doing this if you like.


> Dave

--Rainer



---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
    (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)



RE: Re: [ADMIN] High memory usage [PATCH]

From
"Dave Cramer"
Date:
Here is a patch which inspired by Michael Stephens that should work

Dave


-----Original Message-----
From: pgsql-jdbc-owner@postgresql.org
[mailto:pgsql-jdbc-owner@postgresql.org] On Behalf Of Gunnar Rønning
Sent: June 22, 2001 10:14 AM
To: Rainer Mager
Cc: Dave Cramer; Bruce Momjian; PostgreSQL jdbc list
Subject: Re: [JDBC] Re: [ADMIN] High memory usage [PATCH]

* "Rainer Mager" <rmager@vgkk.com> wrote:
|

| Interesting. I wasn't aware of this. If question #2 is answered such
that
| thread safe isn't necessary, then this problem goes away pretty
easily. If
| thread safety is needed then this would have to be rewritten, I can
look
| into doing this if you like.

Thread safety is required by the spec. Do you have "JDBC API tutorial
and
reference, 2 ed." from Addison Wesley ? This book contains a section for

JDBC driver writers and explains this issue.

regards,

        Gunnar

--
Gunnar Rønning - gunnar@polygnosis.com
Senior Consultant, Polygnosis AS, http://www.polygnosis.com/

---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org


Attachment

Re: Re: [ADMIN] High memory usage [PATCH]

From
Bruce Momjian
Date:
Your patch has been added to the PostgreSQL unapplied patches list at:

    http://candle.pha.pa.us/cgi-bin/pgpatches

I will try to apply it within the next 48 hours.

> Here is a patch which inspired by Michael Stephens that should work
>
> Dave
>
>
> -----Original Message-----
> From: pgsql-jdbc-owner@postgresql.org
> [mailto:pgsql-jdbc-owner@postgresql.org] On Behalf Of Gunnar R?nning
> Sent: June 22, 2001 10:14 AM
> To: Rainer Mager
> Cc: Dave Cramer; Bruce Momjian; PostgreSQL jdbc list
> Subject: Re: [JDBC] Re: [ADMIN] High memory usage [PATCH]
>
> * "Rainer Mager" <rmager@vgkk.com> wrote:
> |
>
> | Interesting. I wasn't aware of this. If question #2 is answered such
> that
> | thread safe isn't necessary, then this problem goes away pretty
> easily. If
> | thread safety is needed then this would have to be rewritten, I can
> look
> | into doing this if you like.
>
> Thread safety is required by the spec. Do you have "JDBC API tutorial
> and
> reference, 2 ed." from Addison Wesley ? This book contains a section for
>
> JDBC driver writers and explains this issue.
>
> regards,
>
>         Gunnar
>
> --
> Gunnar R?nning - gunnar@polygnosis.com
> Senior Consultant, Polygnosis AS, http://www.polygnosis.com/
>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
>

[ Attachment, skipping... ]

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: Re: [ADMIN] High memory usage [PATCH]

From
Bruce Momjian
Date:
Patch applied.  Thanks.

> Here is a patch which inspired by Michael Stephens that should work
>
> Dave
>
>
> -----Original Message-----
> From: pgsql-jdbc-owner@postgresql.org
> [mailto:pgsql-jdbc-owner@postgresql.org] On Behalf Of Gunnar R?nning
> Sent: June 22, 2001 10:14 AM
> To: Rainer Mager
> Cc: Dave Cramer; Bruce Momjian; PostgreSQL jdbc list
> Subject: Re: [JDBC] Re: [ADMIN] High memory usage [PATCH]
>
> * "Rainer Mager" <rmager@vgkk.com> wrote:
> |
>
> | Interesting. I wasn't aware of this. If question #2 is answered such
> that
> | thread safe isn't necessary, then this problem goes away pretty
> easily. If
> | thread safety is needed then this would have to be rewritten, I can
> look
> | into doing this if you like.
>
> Thread safety is required by the spec. Do you have "JDBC API tutorial
> and
> reference, 2 ed." from Addison Wesley ? This book contains a section for
>
> JDBC driver writers and explains this issue.
>
> regards,
>
>         Gunnar
>
> --
> Gunnar R?nning - gunnar@polygnosis.com
> Senior Consultant, Polygnosis AS, http://www.polygnosis.com/
>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
>

[ Attachment, skipping... ]

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: [ADMIN] High memory usage [PATCH]

From
Barry Lind
Date:

Barry Lind wrote:

> Since this patch got applied before I got around to commenting on it, I
> have submitted a new patch to address my issues with the original patch.
>
> The problem with the patch as applied is that is always creates the
> SimpleDateFormat objects in the constructor of the PreparedStatement
> regardless of whether or not they will ever be used in the
> PreparedStatement.  I have reverted back to the old behavior that only
> creates them if necessary in the setDate and setTimestamp methods.
>
> I also removed the close() method.  It's only purpose was to free these
> two SimpleDateFormat objects.  I think it is much better to leave these
> two objects cached on the thread so that other PreparedStatements can
> use them.  (This was the intention of a patch I submitted back in
> February where I was trying to remove as many object creations as
> possible to improve performance.  That patch as written needed to get
> pulled because of the problem that SimpleDataFormat objects are not
> thread safe.  Peter then added the ThreadLocal code to try to solve the
> performance problem, but introduced the memory leak that originated this
> email thread.)  I think the cost of at most two SimpleDateFormat objects
> being cached on each thead is worth the benefits of less object creation
> and subsequent garbage collection.
>
> thanks,
> --Barry
>
>
> Bruce Momjian wrote:
>
>> Patch applied.  Thanks.
>>
>>
>>> Here is a patch which inspired by Michael Stephens that should work
>>>
>>> Dave
>>>
>>>
>>> -----Original Message-----
>>> From: pgsql-jdbc-owner@postgresql.org
>>> [mailto:pgsql-jdbc-owner@postgresql.org] On Behalf Of Gunnar R?nning
>>> Sent: June 22, 2001 10:14 AM
>>> To: Rainer Mager
>>> Cc: Dave Cramer; Bruce Momjian; PostgreSQL jdbc list
>>> Subject: Re: [JDBC] Re: [ADMIN] High memory usage [PATCH]
>>>
>>> * "Rainer Mager" <rmager@vgkk.com> wrote:
>>> |
>>>
>>> | Interesting. I wasn't aware of this. If question #2 is answered such
>>> that
>>> | thread safe isn't necessary, then this problem goes away pretty
>>> easily. If
>>> | thread safety is needed then this would have to be rewritten, I can
>>> look
>>> | into doing this if you like.
>>>
>>> Thread safety is required by the spec. Do you have "JDBC API tutorial
>>> and reference, 2 ed." from Addison Wesley ? This book contains a
>>> section for
>>>
>>> JDBC driver writers and explains this issue.
>>>
>>> regards,
>>>        Gunnar
>>>
>>> --
>>> Gunnar R?nning - gunnar@polygnosis.com
>>> Senior Consultant, Polygnosis AS, http://www.polygnosis.com/
>>>
>>> ---------------------------(end of broadcast)---------------------------
>>> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
>>>
>>>
>>
>> [ Attachment, skipping... ]
>>
>>
>
>
> ------------------------------------------------------------------------
>
> *** ./interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java.orig    Sun Jun 24 21:05:29 2001
> --- ./interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java    Sun Jun 24 21:13:15 2001
> ***************
> *** 65,78 ****
>           this.sql = sql;
>           this.connection = connection;
>
> -         // might just as well create it here, so we don't take the hit later
> -
> -                 SimpleDateFormat df = new SimpleDateFormat("''yyyy-MM-dd''");
> -                 tl_df.set(df);
> -
> -                 df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
> -                 tl_tsdf.set(df);
> -
>           for (i = 0; i < sql.length(); ++i)
>           {
>               int c = sql.charAt(i);
> --- 65,70 ----
> ***************
> *** 95,111 ****
>               templateStrings[i] = (String)v.elementAt(i);
>       }
>
> -         /**
> -          * New in 7.1 - overides Statement.close() to dispose of a few local objects
> -          */
> -         public void close() throws SQLException
> -      {
> -           // free the ThreadLocal caches
> -           tl_df.set(null);
> -       tl_tsdf.set(null);
> -           super.close();
> -         }
> -
>       /**
>        * A Prepared SQL query is executed and its ResultSet is returned
>        *
> --- 87,92 ----
> ***************
> *** 343,348 ****
> --- 324,333 ----
>       public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
>       {
>             SimpleDateFormat df = (SimpleDateFormat) tl_df.get();
> +           if(df==null) {
> +             df = new SimpleDateFormat("''yyyy-MM-dd''");
> +             tl_df.set(df);
> +           }
>
>         set(parameterIndex, df.format(x));
>
> ***************
> *** 382,387 ****
> --- 367,376 ----
>       public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
>           {
>             SimpleDateFormat df = (SimpleDateFormat) tl_tsdf.get();
> +           if(df==null) {
> +             df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
> +             tl_tsdf.set(df);
> +           }
>             df.setTimeZone(TimeZone.getTimeZone("GMT"));
>
>             // Use the shared StringBuffer
>
> patch.txt
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> 7bit
>
>



Re: [ADMIN] High memory usage [PATCH]

From
Barry Lind
Date:
resending since I sent it from the wrong email address last time.



 Since this patch got applied before I got around to commenting on it,

 I have submitted a new patch to address my issues with the original
 patch.

 The problem with the patch as applied is that is always creates the
 SimpleDateFormat objects in the constructor of the PreparedStatement
 regardless of whether or not they will ever be used in the
 PreparedStatement.  I have reverted back to the old behavior that only
 creates them if necessary in the setDate and setTimestamp methods.

 I also removed the close() method.  It's only purpose was to free
 these two SimpleDateFormat objects.  I think it is much better to
 leave these two objects cached on the thread so that other
 PreparedStatements can use them.  (This was the intention of a patch I
 submitted back in February where I was trying to remove as many object
 creations as possible to improve performance.  That patch as written
 needed to get pulled because of the problem that SimpleDataFormat
 objects are not thread safe.  Peter then added the ThreadLocal code to
 try to solve the performance problem, but introduced the memory leak
 that originated this email thread.)  I think the cost of at most two
 SimpleDateFormat objects being cached on each thead is worth the
 benefits of less object creation and subsequent garbage collection.

 thanks,
 --Barry


>> Bruce Momjian wrote:
>>
>>> Patch applied.  Thanks.
>>>
>>>
>>>> Here is a patch which inspired by Michael Stephens that should work
>>>>
>>>> Dave
>>>>
>>>>
>>>> -----Original Message-----
>>>> From: pgsql-jdbc-owner@postgresql.org
>>>> [mailto:pgsql-jdbc-owner@postgresql.org] On Behalf Of Gunnar R?nning
>>>> Sent: June 22, 2001 10:14 AM
>>>> To: Rainer Mager
>>>> Cc: Dave Cramer; Bruce Momjian; PostgreSQL jdbc list
>>>> Subject: Re: [JDBC] Re: [ADMIN] High memory usage [PATCH]
>>>>
>>>> * "Rainer Mager" <rmager@vgkk.com> wrote:
>>>> |
>>>>
>>>> | Interesting. I wasn't aware of this. If question #2 is answered such
>>>> that
>>>> | thread safe isn't necessary, then this problem goes away pretty
>>>> easily. If
>>>> | thread safety is needed then this would have to be rewritten, I can
>>>> look
>>>> | into doing this if you like.
>>>>
>>>> Thread safety is required by the spec. Do you have "JDBC API tutorial
>>>> and reference, 2 ed." from Addison Wesley ? This book contains a
>>>> section for
>>>>
>>>> JDBC driver writers and explains this issue.
>>>>
>>>> regards,
>>>>        Gunnar
>>>>
>>>> --
>>>> Gunnar R?nning - gunnar@polygnosis.com
>>>> Senior Consultant, Polygnosis AS, http://www.polygnosis.com/
>>>>
>>>> ---------------------------(end of
>>>> broadcast)---------------------------
>>>> TIP 1: subscribe and unsubscribe commands go to
>>>> majordomo@postgresql.org
>>>>
>>>>
>>>
>>> [ Attachment, skipping... ]
>>>
>>>
>>
>>
>> ------------------------------------------------------------------------
>>
>> ***
>> ./interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java.orig
>> Sun Jun 24 21:05:29 2001
>> --- ./interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java
>> Sun Jun 24 21:13:15 2001
>> ***************
>> *** 65,78 ****
>>           this.sql = sql;
>>           this.connection = connection;
>>
>> -         // might just as well create it here, so we don't take the
>> hit later
>> - -                 SimpleDateFormat df = new
>> SimpleDateFormat("''yyyy-MM-dd''");
>> -                 tl_df.set(df);
>> -
>> -                 df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
>> -                 tl_tsdf.set(df);
>> -                     for (i = 0; i < sql.length(); ++i)
>>           {
>>               int c = sql.charAt(i);
>> --- 65,70 ----
>> ***************
>> *** 95,111 ****
>>               templateStrings[i] = (String)v.elementAt(i);
>>       }
>>   -         /**
>> -          * New in 7.1 - overides Statement.close() to dispose of a
>> few local objects
>> -          */
>> -         public void close() throws SQLException
>> -      {
>> -           // free the ThreadLocal caches
>> -           tl_df.set(null);
>> -       tl_tsdf.set(null);
>> -           super.close();
>> -         }
>> -       /**
>>        * A Prepared SQL query is executed and its ResultSet is returned
>>        *
>> --- 87,92 ----
>> ***************
>> *** 343,348 ****
>> --- 324,333 ----
>>       public void setDate(int parameterIndex, java.sql.Date x) throws
>> SQLException
>>       {
>>             SimpleDateFormat df = (SimpleDateFormat) tl_df.get();
>> +           if(df==null) {
>> +             df = new SimpleDateFormat("''yyyy-MM-dd''");
>> +             tl_df.set(df);
>> +           }
>>           set(parameterIndex, df.format(x));
>>   ***************
>> *** 382,387 ****
>> --- 367,376 ----
>>       public void setTimestamp(int parameterIndex, Timestamp x) throws
>> SQLException
>>           {
>>             SimpleDateFormat df = (SimpleDateFormat) tl_tsdf.get();
>> +           if(df==null) {
>> +             df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
>> +             tl_tsdf.set(df);
>> +           }
>>             df.setTimeZone(TimeZone.getTimeZone("GMT"));
>>               // Use the shared StringBuffer
>>
>> patch.txt
>>
>> Content-Type:
>>
>> text/plain
>> Content-Encoding:
>>
>> 7bit
>>
>>
>
>



Re: [PATCHES] Re: [ADMIN] High memory usage [PATCH]

From
Bruce Momjian
Date:
> resending since I sent it from the wrong email address last time.
>
>
>
>  Since this patch got applied before I got around to commenting on it,
>
>  I have submitted a new patch to address my issues with the original
>  patch.
>
>  The problem with the patch as applied is that is always creates the
>  SimpleDateFormat objects in the constructor of the PreparedStatement
>  regardless of whether or not they will ever be used in the
>  PreparedStatement.  I have reverted back to the old behavior that only
>  creates them if necessary in the setDate and setTimestamp methods.

Barry, did I miss the actual patch you sent?

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

RE: Re: Re: [ADMIN] High memory usage [PATCH]

From
"Dave Cramer"
Date:
Yes, this is the correct approach, great advice!

-----Original Message-----
From: pgsql-jdbc-owner@postgresql.org
[mailto:pgsql-jdbc-owner@postgresql.org] On Behalf Of Michael Stephenson
Sent: June 22, 2001 10:42 AM
To: PostgreSQL jdbc list
Subject: [JDBC] Re: Re: [ADMIN] High memory usage [PATCH]

[snip]

Wouldn't it be more elegant simply to make the ThreadLocal's static (as
I'd have thought was probably the intention of the original author),
this
would remove the possiblity of any memory leaks in a single threaded
environment, and have the same affect ultimately in a multithreaded
environment?

Michael Stephenson


---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

http://www.postgresql.org/search.mpl



RE: Re: [ADMIN] High memory usage [PATCH]

From
"Dave Cramer"
Date:
On the thread safe issue: I am having a hard time understanding how one
would share a statement across threads. I would expect that threadsafe
just means don't use static buffers so that I can have multiple
statements in multiple threads. I don't think it is possible to have two
threads concurrently doing a query using one statement. This being said,
I don't thing it is necessary to go to great lengths to lock within the
statement as long as all the members within the statement are
non-static.

Comments?

-----Original Message-----
From: gunnar@polygnosis.com [mailto:gunnar@polygnosis.com]
Sent: June 22, 2001 7:42 AM
To: Dave Cramer
Cc: Bruce Momjian; Rainer Mager; PostgreSQL jdbc list
Subject: Re: [JDBC] Re: [ADMIN] High memory usage [PATCH]

* "Dave Cramer" <Dave@micro-automation.net> wrote:
|
| my two cents worth...
|
| 1) what is the problem that this is trying to solve, I assume from the
| subject that it is some sort of high memory usage?

I would like to know as well.

| 2) I am trying to understand how a statement would ever be used by
more than
| one thread at a time? I would think that it would be impossible to
share
| statements across threads.

Quite easy. Just the same way as you share any other object across
threads
and according to the JDBC spec requires that the driver shoudl be thread

safe.


| 3) The double locking method used is alledgedly unsafe on SMP machines
| http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double_p.html.

Yup, double checked locking is not going to guarantee that you get
properly initialized objects with the current Java spec.

--
Gunnar Rønning - gunnar@polygnosis.com
Senior Consultant, Polygnosis AS, http://www.polygnosis.com/



Re: [ADMIN] High memory usage [PATCH]

From
Barry Lind
Date:
Since this patch got applied before I got around to commenting on it, I
have submitted a new patch to address my issues with the original patch.

The problem with the patch as applied is that is always creates the
SimpleDateFormat objects in the constructor of the PreparedStatement
regardless of whether or not they will ever be used in the
PreparedStatement.  I have reverted back to the old behavior that only
creates them if necessary in the setDate and setTimestamp methods.

I also removed the close() method.  It's only purpose was to free these
two SimpleDateFormat objects.  I think it is much better to leave these
two objects cached on the thread so that other PreparedStatements can
use them.  (This was the intention of a patch I submitted back in
February where I was trying to remove as many object creations as
possible to improve performance.  That patch as written needed to get
pulled because of the problem that SimpleDataFormat objects are not
thread safe.  Peter then added the ThreadLocal code to try to solve the
performance problem, but introduced the memory leak that originated this
email thread.)  I think the cost of at most two SimpleDateFormat objects
being cached on each thead is worth the benefits of less object creation
and subsequent garbage collection.

thanks,
--Barry


Bruce Momjian wrote:

> Patch applied.  Thanks.
>
>
>>Here is a patch which inspired by Michael Stephens that should work
>>
>>Dave
>>
>>
>>-----Original Message-----
>>From: pgsql-jdbc-owner@postgresql.org
>>[mailto:pgsql-jdbc-owner@postgresql.org] On Behalf Of Gunnar R?nning
>>Sent: June 22, 2001 10:14 AM
>>To: Rainer Mager
>>Cc: Dave Cramer; Bruce Momjian; PostgreSQL jdbc list
>>Subject: Re: [JDBC] Re: [ADMIN] High memory usage [PATCH]
>>
>>* "Rainer Mager" <rmager@vgkk.com> wrote:
>>|
>>
>>| Interesting. I wasn't aware of this. If question #2 is answered such
>>that
>>| thread safe isn't necessary, then this problem goes away pretty
>>easily. If
>>| thread safety is needed then this would have to be rewritten, I can
>>look
>>| into doing this if you like.
>>
>>Thread safety is required by the spec. Do you have "JDBC API tutorial
>>and
>>reference, 2 ed." from Addison Wesley ? This book contains a section for
>>
>>JDBC driver writers and explains this issue.
>>
>>regards,
>>
>>        Gunnar
>>
>>--
>>Gunnar R?nning - gunnar@polygnosis.com
>>Senior Consultant, Polygnosis AS, http://www.polygnosis.com/
>>
>>---------------------------(end of broadcast)---------------------------
>>TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
>>
>>
>
> [ Attachment, skipping... ]
>
>

*** ./interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java.orig    Sun Jun 24 21:05:29 2001
--- ./interfaces/jdbc/org/postgresql/jdbc2/PreparedStatement.java    Sun Jun 24 21:13:15 2001
***************
*** 65,78 ****
          this.sql = sql;
          this.connection = connection;

-         // might just as well create it here, so we don't take the hit later
-
-                 SimpleDateFormat df = new SimpleDateFormat("''yyyy-MM-dd''");
-                 tl_df.set(df);
-
-                 df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-                 tl_tsdf.set(df);
-
          for (i = 0; i < sql.length(); ++i)
          {
              int c = sql.charAt(i);
--- 65,70 ----
***************
*** 95,111 ****
              templateStrings[i] = (String)v.elementAt(i);
      }

-         /**
-          * New in 7.1 - overides Statement.close() to dispose of a few local objects
-          */
-         public void close() throws SQLException
-      {
-           // free the ThreadLocal caches
-           tl_df.set(null);
-       tl_tsdf.set(null);
-           super.close();
-         }
-
      /**
       * A Prepared SQL query is executed and its ResultSet is returned
       *
--- 87,92 ----
***************
*** 343,348 ****
--- 324,333 ----
      public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
      {
            SimpleDateFormat df = (SimpleDateFormat) tl_df.get();
+           if(df==null) {
+             df = new SimpleDateFormat("''yyyy-MM-dd''");
+             tl_df.set(df);
+           }

        set(parameterIndex, df.format(x));

***************
*** 382,387 ****
--- 367,376 ----
      public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
          {
            SimpleDateFormat df = (SimpleDateFormat) tl_tsdf.get();
+           if(df==null) {
+             df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+             tl_tsdf.set(df);
+           }
            df.setTimeZone(TimeZone.getTimeZone("GMT"));

            // Use the shared StringBuffer