2

We've an application which writes records in a SQL Server CE (version 3.5) / (MySQL 5.7.11 community) database table [depending on the configuration] through the use of NHibernate (version 3.1.0.4000).

The method which performs the save to the database table has the following structure, so everything should be disposed correctly

using (ISession session = SessionHelper.GetSession())
using (ITransaction txn = session.BeginTransaction())
{
    session.Save(entity);
    txn.Commit();
}

After about a week of heavy work (where several hundred thousands records have been written) the application stops working and throws an out of memory error.

Then:

  • With SQL Server CE the database gets corrupted and needs to be manually repaired
  • With MySQL the mysqld daemon is terminated and it needs to be restarted

We've been monitoring the application memory usage through ANTS Memory Profiler (with SQL CE configuration), but, to our surprise, the application "private bytes" doesn't seem to increase at all - this is reported both by ANTS and by the RESOURCE MANAGER.

Still, when the application is forced close (after such error shows up) the "physical memory usage" in the task manager falls from about 80% right down to 20-30%, and I'm again able to start other processes without getting another out of memory exception.

Doing some research, I've found this:

What is private bytes, virtual bytes, working set?

I quote the last part about private bytes:

Private Bytes are a reasonable approximation of the amount of memory your executable is using and can be used to help narrow down a list of potential candidates for a memory leak; if you see the number growing and growing constantly and endlessly, you would want to check that process for a leak. This cannot, however, prove that there is or is not a leak.

Considering the rest of the linked topic, for what I understand, "private bytes" may or may not contain the memory allocated by linked unmanaged dlls, so:

I configured ANTS to also report information about unmanaged memory (Unmanaged memory breakdown by module section) and I've noticed that one of the 2 following modules (depending on a specific sessionfactory setting) take up more and more space (with a ratio that's compatible with the computer running out of memory in about a week):

  1. sqlceqp35
  2. MSVCR120

Given the current results, I'm planning the following tests:

  1. update nhibernate version
  2. trying to further analyze current nhibernate sessionhelper configuration
  3. creating an empty console application without WPF user interface (yes, this application uses WPF) where I put more and more code until I'm able to reproduce the issue

Any suggestion?

EDIT 30/06/2016:

Here's the session factory initialization:

SESSION FACTORY: (the custom driver is to avoid trucation after 4000 chars)

factory = Fluently.Configure()
                        .Database(MsSqlCeConfiguration.Standard.ConnectionString(connString)
                            .ShowSql()
                            .MaxFetchDepth(3)
                            .Driver<MySqlServerCeDriver>())     // FIX truncation 4000 chars
                        .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly()))
                        .ProxyFactoryFactory<NHibernate.ByteCode.LinFu.ProxyFactoryFactory>()
                        .ExposeConfiguration(c =>
                        {
                            c.SetProperty("cache.provider_class", "NHibernate.Cache.HashtableCacheProvider");
                            c.SetProperty("cache.use_query_cache", "true");
                            c.SetProperty("command_timeout", "120");
                        })
                        .BuildSessionFactory();

    public class MySqlServerCeDriver : SqlServerCeDriver
    {
        protected override void InitializeParameter(
            IDbDataParameter dbParam,
            string name,
            SqlType sqlType)
        {
            base.InitializeParameter(dbParam, name, sqlType);

            if (sqlType is StringClobSqlType)
            {
                var parameter = (SqlCeParameter)dbParam;
                parameter.SqlDbType = SqlDbType.NText;
            }
        }
    }

EDIT 07/07/2016

As requested, the GetSession() does the following:

public static ISession GetSession()
        {
            ISession session = factory.OpenSession();
            session.FlushMode = FlushMode.Commit;

            return session;
        }
Community
  • 1
  • 1
Carlo Arnaboldi
  • 363
  • 2
  • 15
  • You are probably leaking system resources somewhere. Can't help without code. Related : http://stackoverflow.com/q/32357314/327083 – J... Jun 28 '16 at 15:54
  • Out of Memory doesnt always literally mean allocated memory. It often means handles, User or GDI objects have been exhausted. For it to work 100s of thousands of times, I'd **guess** it *may be* something conditional. – Ňɏssa Pøngjǣrdenlarp Jun 28 '16 at 16:04
  • @Plutonix Not necessarily conditional - could be a cumulative small leak. – J... Jun 28 '16 at 16:06
  • @Plutonix It doesn't seem to be something conditional, since I've modified the source code so that it always behave in the same manner: at each iteration the same entity is saved again and again through the code quoted above (ITransaction .. etc) – Carlo Arnaboldi Jun 30 '16 at 09:14
  • @J... I added the sessionfactory initialization code, maybe that can help. If you think you may need other parts of the code just let me know. – Carlo Arnaboldi Jun 30 '16 at 09:28
  • and what SessionHelper.GetSession() does under the hood? – Chizh Jun 30 '16 at 09:30
  • @Chizh it does this: ISession session = factory.OpenSession(); session.FlushMode = FlushMode.Commit; return session; – Carlo Arnaboldi Jul 07 '16 at 10:56
  • and is factory static field? maybe it keeps all cached stuff. more: Why is NHibernate.Cache.HashtableCacheProvider not intended for production use? http://stackoverflow.com/a/4298483/225389 – Chizh Jul 07 '16 at 13:04
  • @Chizh thanks for the kind reply. We're investigating on the setting NHibernate.Cache.HashtableCacheProvider which as you stated shouldn't be used in production. Removing that setting doesn't seem to have any effect on the memory leak but we're still investingating on that. I'll update this topic as soon as I have more information available – Carlo Arnaboldi Aug 02 '16 at 16:13

0 Answers0