memory leak in sessions
Posted in 2004
Topics: Error Codes & Troubleshooting, Connectivity: ODBC / JDBC / .NET, Connectivity: ESQL/C, 4GL & Embedded SQL, Java & JDBC Development
version numbers:
IDS: 9.21.UC4
Solaris: 2.6
JDBC: 2.21.JC1
We are confronted with some memory leaks in our application. I am monitoring Total Memory
and Used Memory of some sessions (onstat -g ses sessid ) over a period of time and they are
growing at a steady pace. A session's total memory grew from 3563220 to 7139328 in just 20 hours.
And there are hundreds of similar sessions. All connected thru JDBC.
Couple of days back, a rogue program consumed huge memory in rapid succession,
forcing Informix to allocate more and more shared memory within an hour and
finally crashing when MAXMEM was reached. We were caught totally unprepared
for it. Subsequently we identified it and quarantined that rogue program.
I suspected that the most likely cause is not closing cursors properly or
prepared statement. As we checked later, the quarantined program was reusing
the same cursor without closing it.
In order to test memory leaks I wrote the following program in ESQL/C.
I am assuming that internally Informix's treatment of memory leaks is same
in C as in Java.
Pseudo code:-
CASE A:
$ prepare ppp from "select ...." ;
$ declare c cursor for ppp ;
while (1)
{
$ open c
while (1)
{
$fetch c into ..
if (SQLCODE == 100 ) break ;
}
$ close c;
sleep(10);
}
The above code calls the same cursor in an infinite loop every 10 seconds.
Each time it closes the cursor and opens it. I saw the total memory growing
every minute.
Next I changed the code as follows:-
CASE B:
$ prepare ppp from "select ...." ;
while (1)
{
$ declare c cursor for ppp
$ open c
while (1)
{
$fetch c into ..
if (SQLCODE == 100 ) break ;
}
$ close c;
$ free c ;
sleep(10);
}
In this case, I am closing and freeing the cursor every time, while retaining
the prepared statement. The idea is deallocate cursor resources but not prepared resource
since they are expensive (prepared statement checks for syntax, permission etc)
Again memory leak.
CASE C:
while (1)
{
$ prepare ppp from "select ...." ;
$ declare c cursor for ppp
$ open c
while (1)
{
$fetch c into ..
if (SQLCODE == 100 ) break ;
}
$ close c;
$ free c ;
$ free ppp;
sleep(10);
}
no leak.
I understand that the code mentioned in CASE C is very inefficient becos
it is not reusing the same cursor. It has to prepare every time.
What is wrong in A and B for it to leak memory. My understanding is that a cursor
or a prepared statement should be freed only when they are no longer needed.
if a cursor is reused every time, a simple close/open will do it.
TIA.
9.21.UC4??
Loads of memory leaks in that one!!
Latest 9.21 is UC7 and has a load of memory leaks fixed, but 9.21
stops being supported at the end of June.
Have you tried this with 9.40?
"rkusenet" <rkusenet@sympatico.ca> wrote in message news:<c2t81m$210p1k$1@ID-75254.news.uni-berlin.de>...
> version numbers:
>
> IDS: 9.21.UC4
> Solaris: 2.6
> JDBC: 2.21.JC1
>
> We are confronted with some memory leaks in our application. I am monitoring Total Memory
> and Used Memory of some sessions (onstat -g ses sessid ) over a period of time and they are
> growing at a steady pace. A session's total memory grew from 3563220 to 7139328 in just 20 hours.
> And there are hundreds of similar sessions. All connected thru JDBC.
>
> Couple of days back, a rogue program consumed huge memory in rapid succession,
> forcing Informix to allocate more and more shared memory within an hour and
> finally crashing when MAXMEM was reached. We were caught totally unprepared
> for it. Subsequently we identified it and quarantined that rogue program.
>
> I suspected that the most likely cause is not closing cursors properly or
> prepared statement. As we checked later, the quarantined program was reusing
> the same cursor without closing it.
>
> In order to test memory leaks I wrote the following program in ESQL/C.
> I am assuming that internally Informix's treatment of memory leaks is same
> in C as in Java.
>
> Pseudo code:-
>
> CASE A:
>
> $ prepare ppp from "select ...." ;
> $ declare c cursor for ppp ;
> while (1)
> {
> $ open c
> while (1)
> {
> $fetch c into ..
> if (SQLCODE == 100 ) break ;
> }
> $ close c;
> sleep(10);
> }>
> The above code calls the same cursor in an infinite loop every 10 seconds.
> Each time it closes the cursor and opens it. I saw the total memory growing
> every minute.
>
> Next I changed the code as follows:-
>
> CASE B:
> $ prepare ppp from "select ...." ;
> while (1)
> {
> $ declare c cursor for ppp
> $ open c
> while (1)
> {
> $fetch c into ..
> if (SQLCODE == 100 ) break ;
> }
> $ close c;
> $ free c ;
> sleep(10);
> }>
> In this case, I am closing and freeing the cursor every time, while retaining
> the prepared statement. The idea is deallocate cursor resources but not prepared resource
> since they are expensive (prepared statement checks for syntax, permission etc)
> Again memory leak.
>
> CASE C:
> while (1)
> {
> $ prepare ppp from "select ...." ;
> $ declare c cursor for ppp
> $ open c
> while (1)
> {
> $fetch c into ..
> if (SQLCODE == 100 ) break ;
> }
> $ close c;
> $ free c ;
> $ free ppp;
> sleep(10);
> }
> no leak.>
> I understand that the code mentioned in CASE C is very inefficient becos
> it is not reusing the same cursor. It has to prepare every time.
>
> What is wrong in A and B for it to leak memory. My understanding is that a cursor
> or a prepared statement should be freed only when they are no longer needed.
> if a cursor is reused every time, a simple close/open will do it.
>
> TIA.
Related threads
- Posting from the Informix-list
- Migrating from IDS 9.40.UC6 to 11.50.UC3
- Ip for a network session
- questions onstat -g