Исключение из-за нехватки памяти после определенного времени выполнения, но частные байты приложения 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 следующих модулей (в зависимости от конкретного параметра сеанса) занимает все больше и больше места (с совместимым соотношением примерно через неделю на компьютере не хватает памяти):
- sqlceqp35
- MSVCR120
Учитывая текущие результаты, я планирую следующие тесты:
- обновить версию nhibernate
- пытаясь дополнительно проанализировать текущую конфигурацию nhibernate sessionhelper
- создание пустого консольного приложения без пользовательского интерфейса 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;
}