#std725

Оптимизация использования оперативной памяти

Методическая рекомендация

Не проектируйте решение из предположения о неограниченной оперативной памяти.

1.

Неэффективное использование памяти в многопользовательских системах быстро снижает стабильность работы.

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

2.

При потенциально неограниченных выборках из ИБ получайте данные порциями фиксированного размера.

Неправильно

Результат запроса целиком загружается в память:

Запрос = Новый Запрос;
Запрос.Текст =
    "ВЫБРАТЬ
    |   Номенклатура.Ссылка,
    |   Номенклатура.Наименование,
    |   Номенклатура.ВидНоменклатуры
    |ИЗ
    |   Справочник.Номенклатура КАК Номенклатура";

// Выгрузка всего справочника в таблицу значений
Номенклатура = Запрос.Выполнить().Выгрузить();
Для Каждого ПозицияНоменклатуры Из Номенклатура Цикл
    // Обработка элемента справочника
КонецЦикла;

Неправильно

Неверно полагаться, что Выбрать() всегда решает проблему объема:

Запрос = Новый Запрос;
Запрос.Текст =
    "ВЫБРАТЬ
    |   Номенклатура.Ссылка,
    |   Номенклатура.Наименование,
    |   Номенклатура.ВидНоменклатуры
    |ИЗ
    |   Справочник.Номенклатура КАК Номенклатура";

РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    // Обработка элемента выборки
КонецЦикла;

Правильно

Используйте искусственное ограничение порции, например ПЕРВЫЕ 1000:

Пока Истина Цикл

    Запрос = Новый Запрос;
    Запрос.Текст =
        "ВЫБРАТЬ ПЕРВЫЕ 1000
        |   Номенклатура.Ссылка,
        |   Номенклатура.Наименование,
        |   Номенклатура.ВидНоменклатуры
        |ИЗ
        |   Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |   <условие выборки необработанных записей>";

    РезультатЗапроса = Запрос.Выполнить();
    Если РезультатЗапроса.Пустой() Тогда
        Прервать;
    КонецЕсли;

    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
        // Обработка элемента выборки
    КонецЦикла;

КонецЦикла;

Правильно

Допустим поэлементный обход через Выбрать объекта метаданных:

Выборка = Справочники.Номенклатура.Выбрать(..., Отбор);
Пока Выборка.Следующий() Цикл
    // Обработка элемента выборки
КонецЦикла;

В этом случае платформа получает данные порциями фиксированного размера.

Примечание

В 32-битной версии платформы при нехватке памяти большие результаты могут временно выгружаться на диск, что дополнительно снижает производительность.

3.

Не обрабатывайте большие XML/HTML/текстовые файлы объектами, которые загружают файл целиком в память:

  • ТекстовыйДокумент;
  • ДокументDOM;
  • ДокументHTML;
  • целиковая загрузка больших XDTO-пакетов.

Исключение: когда нужен произвольный доступ к конкретным частям документа.

Для экономного расхода памяти используйте потоковые объекты:

  • ЧтениеXML, ЧтениеТекста;
  • ЗаписьXML, ЗаписьТекста.

Для XDTO читайте файл последовательно через ЧтениеXML, а отдельные фрагменты десериализуйте фабрикой XDTO.

4.

Избегайте утечек памяти из-за циклических ссылок.

Неправильно

Упрощенный пример циклической ссылки:

Данные = Новый Структура;
Данные.Вставить("Ключ", Данные);

Правильно

Разрывайте ссылку, когда объект больше не нужен:

Данные.Ключ = Неопределено;

Для выявления утечек используйте технологический журнал, добавив в logcfg.xml элемент <leaks>.

См. также:

5.

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

См. также
Источник

https://its.1c.ru/db/v8std#content:725