Влияет ли очистка табличного документа на скорость работы регламентного задания в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке регламентных заданий, выполняющих выгрузку отчетов во внешние файлы (например, в форматы Excel), программисты часто сталкиваются с вопросами оптимизации производительности. Типичный сценарий: фоновое задание в цикле формирует один и тот же отчет с разными параметрами, выгружает результат в ТабличныйДокумент и сохраняет его на диск. В этой статье мы подробно разберем, влияет ли очистка или пересоздание табличного документа между итерациями на скорость работы фонового процесса, как сервер 1С:Предприятия управляет памятью и какие лучшие практики помогут избежать зависания рабочих процессов.

Как рабочие процессы 1С работают с оперативной памятью

Прежде чем перейти к практическим тестам и коду, проанализируем внутреннее устройство платформы 1С:Предприятие. Все фоновые и регламентные задания выполняются на стороне сервера в контексте рабочих процессов rphost. Управление памятью в платформе базируется на механизме подсчета ссылок на объекты:

  1. Когда в коде создается новый объект (например, с помощью конструкции ТабДок = Новый ТабличныйДокумент), операционная система выделяет под него область в адресном пространстве процесса rphost.
  2. Каждая переменная, указывающая на этот объект, увеличивает счетчик ссылок на него.
  3. Как только переменная выходит из области видимости (например, при завершении работы процедуры) или ей присваивается другое значение, счетчик ссылок уменьшается.
  4. Когда счетчик ссылок становится равным нулю, объект помечается как готовый к уничтожению, и встроенный сборщик мусора платформы должен освободить выделенную под него память.

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

Что произойдет, если не очищать табличный документ между отчетами?

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

Вариант А: Перезапись переменной (правильный подход)

Если на каждой итерации цикла вы принудительно инициализируете переменную заново:


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

В этом случае при выполнении строки ТабДок = Новый ТабличныйДокумент; старая ссылка на предыдущий табличный документ заменяется новой. Предыдущий документ уничтожается. С точки зрения производительности этот вариант оптимален, так как каждый раз мы работаем с чистым объектом, а старый своевременно удаляется из памяти.

Вариант Б: Использование метода Очистить() без пересоздания

Иногда разработчики предпочитают использовать метод Очистить() для существующего объекта:


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

Метод Очистить() удаляет области, ячейки, рисунки и форматирование из табличного документа. Однако сам объект в памяти сохраняется. Разберем подводные камни этого подхода: если первый отчет был огромным (сотни тысяч строк со сложным оформлением), метод Очистить() освободит ячейки, но внутренние структуры данных самого объекта ТабличныйДокумент могут остаться фрагментированными. При последующих итерациях такой объект может работать медленнее, чем абсолютно новый.

Вариант В: Накопление данных (критическая ошибка)

Если разработчик забывает переинициализировать переменную и не вызывает метод очистки, а просто продолжает выводить данные в один и тот же объект:


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

В этом сценарии каждый последующий отчет будет дописываться в конец предыдущего. Это приведет к лавинообразному росту объема табличного документа. Память процесса rphost будет стремительно заполняться. Как только физическая память сервера закончится, операционная система начнет использовать виртуальную память (свопинг на жесткий диск), что снизит скорость работы регламентного задания в десятки и сотни раз. Более того, при превышении лимитов памяти кластера 1С, процесс rphost может быть принудительно перезапущен сервером, что приведет к аварийному завершению задания.

Сравнение методов очистки памяти: практические рекомендации

Выясним, как правильно и максимально быстро освобождать ресурсы при последовательной генерации файлов. Рассмотрим три основных инструмента управления жизненным циклом объекта ТабличныйДокумент:

  1. Явное присвоение значения Неопределено

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

    
    ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
    ТабДок = Неопределено; // Память освобождается незамедлительно
    

    Этот способ является наиболее надежным, так как мы принудительно разрываем связь переменной с объектом в памяти до начала следующей ресурсоемкой операции.

  2. Использование локальных процедур

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

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

    Поскольку переменная ТабДок является локальной для процедуры СформироватьИСохранитьОтчет, при выходе из нее счетчик ссылок гарантированно уменьшается до нуля, и память очищается платформой без необходимости ручного вмешательства разработчика.

  3. Выбор формата сохранения (XLS vs XLSX)

    Скорость работы регламентного задания также напрямую зависит от формата, в который выгружается документ. Платформа выполняет сложную конвертацию внутреннего представления документа (MXL) в структуру Excel:

    • XLS (Excel 97-2003): Устаревший двоичный формат. Имеет жесткое ограничение в 65 536 строк. Конвертация в этот формат требует значительных вычислительных ресурсов процессора и памяти.
    • XLSX (Excel 2007 и старше): Современный формат на базе архивированного XML. Платформа 1С оптимизирована под работу с XLSX, конвертация в него происходит гораздо быстрее, а потребление оперативной памяти при этом существенно ниже.

Резюме

Подведем итоги нашего анализа. Влияет ли очистка табличного документа на скорость выполнения фонового процесса? Да, влияет самым прямым образом. Чтобы регламентные задания не приводили к утечкам памяти на сервере и выполнялись с максимальной скоростью, следуйте простым правилам:

← На главную