Memory leak when using prepared commands and a v2 connection

Discussion of open issues, suggestions and bugs regarding ADO.NET provider for PostgreSQL
Post Reply
bozr
Posts: 17
Joined: Mon 21 Jun 2010 12:39

Memory leak when using prepared commands and a v2 connection

Post by bozr » Thu 16 Dec 2010 12:36

Hello,

My application hit an OutOfMemoryException. That's why I attached a memory profiler to find out that the problem was caused by dotConnect for ProsreSQL. I'm using version 4.95.190.

I used the following code to narrow the problem down to dotConnect.

Code: Select all

using System;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Threading;

namespace ProveDotConnectBug
{
    internal class Program
    {
        private enum TestEnum
        {
            TestA,
            TestB,
            TestC,
            TestD,
            TestE,
            TestF,
        }

        private Random mRandom;
        private TestEnum[] mEnumValues;
        private DbCommand mCommand;

        private static void Main(string[] args)
        {
            Program program = new Program();
            program.Run();
        }

        private Program()
        {
            mRandom = new Random(DateTime.Now.Millisecond);
            mEnumValues = (TestEnum[])Enum.GetValues(typeof(TestEnum));

            DbProviderFactory factory = DbProviderFactories.GetFactory(@"Devart.Data.PostgreSql");
            DbConnection connection = factory.CreateConnection();
            connection.ConnectionString = @"Host=localhost;Database=testdb;User Id=testuser;Password=secret;Protocol=2;Unicode=true;";
            connection.Open();

            mCommand = connection.CreateCommand();
            mCommand.CommandText = @"testfunction";
            mCommand.CommandType = CommandType.StoredProcedure;

            AddParameter(mCommand, @"f1", DbType.Int32);
            AddParameter(mCommand, @"f2", DbType.String);
            AddParameter(mCommand, @"f3", DbType.Boolean);
            AddParameter(mCommand, @"f4", DbType.DateTime);

            mCommand.Prepare(); // This statement causes the application to leak memory!
        }

        private void Run()
        {
            long previous = -1;
            while (true)
            {
                mCommand.Parameters[@"f1"].Value = mRandom.Next(int.MinValue, int.MaxValue);
                mCommand.Parameters[@"f2"].Value = mEnumValues[mRandom.Next(mEnumValues.Length - 1)].ToString();
                mCommand.Parameters[@"f3"].Value = (mRandom.Next(1) > 0);
                mCommand.Parameters[@"f4"].Value = DateTime.Now;
                long current = (long)mCommand.ExecuteScalar();

                Debug.Assert(current > previous);
                previous = current;

                Thread.Sleep(50);
            }
        }

        private static void AddParameter(DbCommand command, string name, DbType type)
        {
            DbParameter parameter = command.CreateParameter();
            parameter.ParameterName = name;
            parameter.DbType = type;
            command.Parameters.Add(parameter);
        }
    }
}
The database table and function are defined like this:

Code: Select all

CREATE SEQUENCE testsequence INCREMENT 1 START 1;

CREATE TABLE testtable
(
  id bigint NOT NULL DEFAULT nextval('testsequence'),
  field1 integer,
  field2 character varying(100) NOT NULL,
  field3 boolean NOT NULL,
  field4 timestamp without time zone,
  CONSTRAINT testprimarykey PRIMARY KEY (id)
);

CREATE OR REPLACE FUNCTION testfunction(f1 integer, f2 character varying, f3 boolean, f4 timestamp without time zone)
  RETURNS bigint AS
$$
DECLARE
  res bigint;
BEGIN
  INSERT INTO testtable(id,field1,field2,field3,field4) VALUES(DEFAULT,f1,f2,f3,f4) RETURNING id INTO STRICT res;
  RETURN res;
END;
$$
  LANGUAGE plpgsql VOLATILE;
When I run the above application the memory consumption keeps on ramping up. When I comment out the mCommand.Prepare(); statement the memory consumption seems stable.

What I also noticed is that when I change the code to use protocol version 3, the problem is not there (even when the Prepare() is in place)

To me this seems like a bug.

Regards,
Ruud

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Fri 17 Dec 2010 15:31

Thank you for your report, we have reproduced the issue. We will investigate it and inform you about the results here.

bozr
Posts: 17
Joined: Mon 21 Jun 2010 12:39

Post by bozr » Fri 18 Feb 2011 16:15

Two months have passed in the mean time, any update on this issue?

Thanks a lot,
Ruud

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Mon 21 Feb 2011 13:32

We are working on the issue, but cannot provide any timeframe at the moment. We will post here as soon as any new information is available.

bozr
Posts: 17
Joined: Mon 21 Jun 2010 12:39

Post by bozr » Tue 22 Mar 2011 09:20

In the mean time I changed my application to use a protocol v3 connection instead, so the memory issue is gone now.

Just curious however: will protocol v2 connections receive future support from devart?

Thanks,
Ruud

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Wed 23 Mar 2011 12:46

We have fixed the memory leak on protocol 2.0. The fix will be available in the nearest build, which we plan to release in several days. We will post here when this build is published.

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Thu 24 Mar 2011 14:40

We have released the new 5.10.126 build of dotConnect for PostgreSQL where this issue is fixed. The new build can be downloaded from
http://www.devart.com/dotconnect/postgr ... nload.html
(the trial version) or from Registered Users' Area (for users with active subscription only):
http://secure.devart.com/

For more information about the fixes and improvements available in dotConnect for PostgreSQL 5.10.126, please refer to
http://www.devart.com/forums/viewtopic.php?t=20586

Post Reply