Исключение из-за нехватки памяти после определенного времени выполнения, но частные байты приложения C# не увеличиваются

У нас есть приложение, которое записывает записи в таблицу базы данных SQL Server CE (версия 3.5) / (сообщество MySQL 5.7.11) [в зависимости от конфигурации] с помощью NHibernate (версия 3.1.0.4000).

Метод, который выполняет сохранение в таблицу базы данных, имеет следующую структуру, поэтому все должно быть правильно расположено

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

Примерно через неделю тяжелой работы (где было записано несколько сотен тысяч записей) приложение перестает работать и выдает ошибку нехватки памяти.

Затем:

  • С SQL Server CE база данных повреждена и требует ручного ремонта
  • С MySQL демон mysqld завершается и его нужно перезапустить

Мы отслеживали использование памяти приложения через ANTS Memory Profiler (с конфигурацией SQL CE), но, к нашему удивлению, "частные байты" приложения, похоже, не увеличиваются вообще - об этом сообщают как ANTS, так и РЕСУРСНЫЙ МЕНЕДЖЕР.

Тем не менее, когда приложение принудительно закрывается (после появления такой ошибки) "использование физической памяти" в диспетчере задач падает примерно с 80% до 20-30%, и я снова могу запускать другие процессы, не получая еще одно исключение из памяти.

Делая некоторые исследования, я нашел это:

Что такое частные байты, виртуальные байты, рабочий набор?

Я процитирую последнюю часть о частных байтах:

Частные байты являются разумным приближением к объему памяти, используемому вашим исполняемым файлом, и могут использоваться, чтобы сузить список потенциальных кандидатов на утечку памяти; если вы видите, что число постоянно растет и растет, вы можете проверить этот процесс на утечку. Это, однако, не может доказать, что есть или нет утечка.

Рассматривая остальную часть связанной темы, насколько я понимаю, "частные байты" могут содержать или не содержать память, выделенную связанными неуправляемыми библиотеками, поэтому:

Я настроил ANTS, чтобы он также сообщал информацию о неуправляемой памяти (разбивка неуправляемой памяти по разделам модулей), и я заметил, что один из 2 следующих модулей (в зависимости от конкретного параметра сеанса) занимает все больше и больше места (с совместимым соотношением примерно через неделю на компьютере не хватает памяти):

  1. sqlceqp35
  2. MSVCR120

Учитывая текущие результаты, я планирую следующие тесты:

  1. обновить версию nhibernate
  2. пытаясь дополнительно проанализировать текущую конфигурацию nhibernate sessionhelper
  3. создание пустого консольного приложения без пользовательского интерфейса WPF (да, это приложение использует WPF), куда я помещаю все больше и больше кода, пока не смогу воспроизвести проблему

Любое предложение?

РЕДАКТИРОВАТЬ 30/06/2016:

Вот инициализация фабрики сеанса:

ФАБРИКА СЕССИИ: (пользовательский водитель должен избегать перемирия после 4000 символов)

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;
            }
        }
    }

РЕДАКТИРОВАТЬ 07/07/2016

В соответствии с запросом GetSession() выполняет следующие действия:

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

            return session;
        }

0 ответов

Другие вопросы по тегам