При выполнении обмена данными или переносе большого массива информации с помощью правил конвертации («Конвертация данных 2.0») разработчики и администраторы 1С часто сталкиваются с аварийным завершением работы программы и системной ошибкой: «Недостаточно памяти». При этом физической оперативной памяти на сервере или рабочей станции может быть более чем достаточно. Разберем детально, почему это происходит и какими способами можно полностью решить данную проблему.
Проанализируем технические предпосылки переполнения памяти в процессе формирования файла выгрузки:
1cv8.exe или рабочему процессу сервера) по умолчанию доступно не более 2 ГБ виртуального адресного пространства. С учетом неизбежной фрагментации памяти процесс аварийно завершается уже при достижении порога потребления в 1.5–1.7 ГБ, даже если на машине установлено 64 или 128 ГБ RAM.Самый прямой и надежный способ снять барьер в 2 ГБ — использовать 64-разрядную версию платформы 1С:Предприятие. Рассмотрим этот подход:
editbin /LARGEADDRESSAWARE 1cv8.exe
А для 32-разрядных версий операционной системы Windows расширение пользовательского адресного пространства до 3 ГБ выполняется через командную строку администратора:
bcdedit /set IncreaseUserVa 3072
Выясним причину чрезмерного расхода памяти в самих алгоритмах правил конвертации (КД 2.0) и разберем способы их оптимизации:
Ссылка.ПолучитьОбъект(). Получение объекта целиком помещает все его реквизиты и табличные части в кэш сеанса. Используйте прямые запросы к нужным полям.Параметры или локальных переменных формируются вспомогательные таблицы значений, их необходимо принудительно занулять сразу после использования:
Параметры.ТаблицаЦен = Неопределено;
ПромежуточнаяВыборка = Неопределено;
Если изменить правила или конфигурацию платформы нельзя, применим методику дробления выгрузки:
Рассмотрим пример создания собственной быстрой выгрузки без накопления массивов объектов в памяти. Потоковая запись с помощью объекта ЗаписьXML сразу сбрасывает данные на диск:
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\Exchange\ExportData.xml", "UTF-8");
Запись.ЗаписатьОбъявлениеXML();
Запись.ЗаписатьНачалоЭлемента("Данные");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Ссылка,
| Номер,
| Дата,
| СуммаДокумента
|ИЗ
| Документ.РеализацияТоваровУслуг
|ГДЕ
| Дата МЕЖДУ &ДатаНачала И &ДатаОкончания";
Запрос.УстановитьПараметр("ДатаНачала", НачалоПериода);
Запрос.УстановитьПараметр("ДатаОкончания", КонецПериода);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Запись.ЗаписатьНачалоЭлемента("Документ");
Запись.ЗаписатьАтрибут("Номер", Строка(Выборка.Номер));
Запись.ЗаписатьАтрибут("Дата", Формат(Выборка.Дата, "ДФ=yyyy-MM-ddTHH:mm:ss"));
Запись.ЗаписатьАтрибут("Сумма", XMLСтрока(Выборка.СуммаДокумента));
Запись.ЗаписатьКонецЭлемента();
КонецЦикла;
Запись.ЗаписатьКонецЭлемента(); // Данные
Запись.Закрыть();
Такой подход обеспечивает минимальное потребление оперативной памяти (в пределах нескольких десятков мегабайт) вне зависимости от размера исходной информационной базы и количества выгружаемых документов.