Почему контекстный вызов с динамическим списком тормозит и как это оптимизировать

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

Разберем распространенную ситуацию в управляемом приложении 1С: при выполнении контекстного вызова серверной процедуры пользователь сталкивается со значительной задержкой (например, в несколько секунд). При этом замер производительности показывает, что задержка происходит на вызове сервера, однако внутри самой серверной процедуры ни одна строчка BSL-кода не занимает существенного времени — везде отображается около 0% времени выполнения.

Проанализируем причины такого поведения платформы 1С и рассмотрим по шагам методы оптимизации, которые позволяют полностью устранить эту проблему.

Выясним причину: почему замер производительности показывает 0%

Штатный инструмент замера производительности 1С фиксирует только время работы кода на встроенном языке (BSL). Однако при динамическом изменении свойства ТекстЗапроса или параметров динамического списка основные временные затраты происходят вне BSL-кода:

  1. Пересборка схемы компоновки данных платформой на уровне ядра (C++): когда в коде происходит присвоение нового значения свойству ТекстЗапроса, платформа аннулирует внутренний кэш и схему динамического списка. Парсинг нового текста, проверка синтаксиса, определение ключевых полей и построение структуры данных происходят во внутреннем коде платформы. В замере BSL этот процесс выглядит как отсутствие нагрузки по строкам.
  2. Сброс динамического считывания и выборка данных: если в новом тексте запроса изменяются соединения или теряются явные ключевые поля, платформа вынуждена сбросить режим порционной загрузки данных. При возврате управления на клиент элемент управления на форме инициирует повторное считывание данных из СУБД для отображения первой порции строк, что создает ощутимую задержку.
  3. Избыточная передача контекста формы: контекстный вызов (&НаСервере) передает на сервер и обратно на клиент весь контекст формы, включая текущие структуры данных и реквизиты. Если контекст велик, расходы на сериализацию и десериализацию данных также вносят свой вклад в задержку.

Способ 1. Перенос установки отборов и параметров на клиент с использованием БСП

Если цель контекстного вызова заключалась лишь в фильтрации данных списка по датам или другим условиям, правильным решением будет отказаться от вызова сервера. Библиотека Стандартных Подсистем (БСП) предоставляет механизмы для установки параметров и отборов динамического списка прямо на клиенте.

Рассмотрим пример кода, в котором отбор по периоду устанавливается на клиенте без обращения к серверу:


// Установка отбора по началу и концу периода на клиенте через БСП
КомпоновкаДанныхКлиентСервер.ДобавитьОтбор(
    Список.Отбор, 
    "ДатаПлатежа", 
    Неделя.ДатаНачала, 
    ВидСравненияКомпоновкиДанных.БольшеИлиРавно
);

КомпоновкаДанныхКлиентСервер.ДобавитьОтбор(
    Список.Отбор, 
    "ДатаПлатежа", 
    Неделя.ДатаОкончания, 
    ВидСравненияКомпоновкиДанных.МеньшеИлиРавно,
    ,
    ,
    Ложь
);

Установка отборов через методы КомпоновкаДанныхКлиентСервер или работу с КомпоновщикНастроек непосредственно на клиенте позволяет избежать вызова сервера, сохраняя структуру динамического списка и не выгружая кэш схемы.

Способ 2. Использование синтаксиса расширения языка запросов для СКД

В случаях, когда условия выборки должны быть гибкими, не следует переписывать свойство ТекстЗапроса полностью. Любое изменение текста запроса ведет к полному сбросу скомпилированной схемы динамического списка.

Посмотрим, как правильно заложить необязательные условия прямо в текст запроса с помощью фигурных скобок СКД:


ВЫБРАТЬ
    Документ.Ссылка КАК Ссылка,
    Документ.Дата КАК Дата,
    Документ.СуммаДокумента КАК СуммаДокумента
ИЗ
    Документ.Оплата КАК Документ
{ГДЕ
    Документ.Дата >= &ДатаНачала,
    Документ.Дата <= &ДатаОкончания}

При таком подходе текст запроса динамического списка остается неизменным. Платформа 1С самостоятельно подключает или отключает секцию ГДЕ при установке соответствующего параметра или отбора, не пересобирая схему с нуля.

Способ 3. Перевод серверных процедур в режим &НаСервереБезКонтекста

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

  1. Создаем внеконтекстную функцию с директивой &НаСервереБезКонтекста.
  2. Передаем в нее только минимально необходимые исходные данные (без передачи всей формы).
  3. Возвращаем на клиент структуру с рассчитанными значениями.
  4. Применяем полученные значения к параметрам или отборам динамического списка на клиенте.

Рассмотрим пример реализации такого подхода:


&НаКлиенте
Процедура ОбновитьДинамическийСписок()
    
    // Получаем необходимые расчетные данные с сервера без передачи контекста формы
    ПараметрыПериода = ПолучитьРассчитанныйПериодНаСервере(Объект.Организация);
    
    // Устанавливаем параметры списка на клиенте
    КомпоновкаДанныхКлиентСервер.УстановитьПараметр(
        Список, 
        "НачалоПериода", 
        ПараметрыПериода.ДатаНачала
    );
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьРассчитанныйПериодНаСервере(Знач Организация)
    
    Результат = Новый Структура("ДатаНачала", НачалоДня(ТекущаяДата()));
    // Выполнение серверной логики...
    Возврат Результат;
    
КонецФункция

Рекомендации по настройке динамического списка

Проанализируем основные правила работы с динамическими списками, соблюдение которых предотвращает проседания производительности:

← На главную