У нас есть приложение, которое записывает записи в таблицу базы данных 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%, и я снова могу запускать другие процессы, не получая еще одно исключение нехватки памяти.
Проведя некоторые исследования, я нашел это:
Что такое частные байты, виртуальные байты, рабочий набор?< /а>
Я цитирую последнюю часть о приватных байтах:
Частные байты — это разумное приближение объема памяти, используемого вашим исполняемым файлом, и его можно использовать, чтобы помочь сузить список потенциальных кандидатов на утечку памяти; если вы видите, что число растет и растет постоянно и бесконечно, вы захотите проверить этот процесс на утечку. Однако это не может доказать наличие или отсутствие утечки.
Учитывая остальную часть связанной темы, насколько я понимаю, «частные байты» могут содержать или не содержать память, выделенную связанными неуправляемыми dll, поэтому:
Я настроил ANTS так, чтобы он также сообщал информацию о неуправляемой памяти (разбивка неуправляемой памяти по разделам модулей) и заметил, что один из двух следующих модулей (в зависимости от конкретной настройки sessionfactory) занимает все больше и больше места (соотношение, совместимое с тем, что память компьютера заканчивается примерно через неделю):
- sqlceqp35
- MSVCR120
Учитывая текущие результаты, я планирую следующие тесты:
- обновить версию nhibernate
- попытка дальнейшего анализа текущей конфигурации nhibernate sessionhelper
- создание пустого консольного приложения без пользовательского интерфейса WPF (да, это приложение использует WPF), куда я добавляю все больше и больше кода, пока не смогу воспроизвести проблему
Любое предложение?
РЕДАКТИРОВАТЬ 30.06.2016:
Вот инициализация фабрики сеансов:
SESSION FACTORY: (специальный драйвер позволяет избежать ошибок после 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;
}