Почему долго открывается список документов в 1С:ERP и как оптимизировать тысячи вызовов процедур общего назначения

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

При работе с крупными конфигурациями, такими как 1С:ERP Управление предприятием 2, программисты часто сталкиваются с проблемой резкого падения производительности при выполнении тривиальных действий. Одной из самых распространенных ситуаций является длительное (до нескольких минут) открытие динамического списка, например, «Документы продажи (все)». При анализе замера производительности выясняется, что система выполняет десятки тысяч раз одну и ту же функцию в общем модуле ОбщегоНазначения. Рассмотрим подробнее, почему это происходит и как исправить ситуацию.

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

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

  1. Ограничение доступа на уровне записей (RLS): Это основной фактор. Когда у пользователя неполные права, система при отрисовке каждой строки динамического списка обязана проверить права доступа. Если список содержит разнородные данные (заказы, реализации, возвраты), проверка инициирует обращение к метаданным для каждого типа объекта в каждой видимой строке.
  2. Вычисляемые поля и условное оформление: Если в динамическом списке настроено оформление, зависящее от программных функций, или добавлены колонки, данные в которых вычисляются «на лету», количество вызовов будет расти пропорционально количеству записей в выборке.
  3. Поддержка национальных языков (мультиязычность): В ERP механизмы локализации могут запрашивать переводы представлений типов объектов метаданных. При отсутствии кэширования эти запросы повторяются циклично.

Разберем по шагам решение: использование кэширования в расширении

Самым эффективным способом борьбы с «лишними» вызовами без изменения логики типовой конфигурации является использование механизма повторного использования возвращаемых значений. Если функция при одинаковых входящих параметрах всегда возвращает один и тот же результат (как в случае с метаданными), нет смысла выполнять её код тысячи раз. Посмотрим, как реализовать это через расширение.

Шаг 1. Создание модуля в расширении. Создадим в расширении новый общий модуль, например, _прПовторноеИспользование. В свойствах модуля установим флаг «Повторное использование возвращаемых значений» в положение «На время сеанса».

Шаг 2. Перенос логики вызова. Вместо того чтобы править типовой код напрямую, мы создаем в этом модуле функцию-обертку, которая будет вызывать целевую тяжелую процедуру.


// В новом модуле расширения с включенным повторным использованием
Функция ПолучитьИдентификаторМетаданных(ИмяОбъекта) Экспорт
    // Вызываем оригинальную тяжелую функцию из типового модуля
    Возврат ОбщегоНазначения.ИдентификаторОбъектаМетаданных(ИмяОбъекта);
КонецФункции

Шаг 3. Внедрение через перехват. С помощью механизма &Вместо в расширении перехватываем вызов функции в исходном модуле ОбщегоНазначения и перенаправляем его в наш кэширующий модуль.


&Вместо("ИдентификаторОбъектаМетаданных")
Функция _прИдентификаторОбъектаМетаданных(Параметр)
    // Система сначала заглянет в кэш нашего модуля
    // Если для данного 'Параметр' результат уже есть, тело функции не выполнится
    Возврат _прПовторноеИспользование.ПолучитьИдентификаторМетаданных(Параметр);
КонецФункции

Проанализируем ситуацию после внедрения: теперь при 37 000 обращений реальный код поиска по метаданным выполнится ровно столько раз, сколько уникальных типов объектов встретилось в списке (обычно не более пары десятков). Остальные 36 980 вызовов вернут значение мгновенно из оперативной памяти.

Почему у разных пользователей разная скорость работы?

Важно понять, почему у одного пользователя может быть 150 вызовов, а у другого — 36 000. Рассмотрим факторы, влияющие на это:

Рекомендации по поиску «узких мест»

Чтобы точно определить, откуда идет вызов, не нужно просматривать стек вызовов 36 000 раз вручную. Используйте следующие приемы:

  1. Группировка в замере производительности: Используйте стандартный инструмент «Замер производительности» в конфигураторе. После замера отсортируйте таблицу по колонке «Количество вызовов». Найдя проблемную строку, нажмите правую кнопку мыши и выберите «Перейти к стеку вызовов».
  2. Точка останова с условием: Если вы хотите поймать момент массового вызова, установите точку останова в проблемной функции. В свойствах точки останова пропишите условие. Например, создайте глобальную переменную-счетчик и прерывайте выполнение только когда счетчик превысит 1000.
  3. Анализ динамического списка: Проверьте запрос динамического списка. Иногда в тексте запроса используются конструкции, которые заставляют платформу выполнять дополнительные неоптимальные действия при получении данных (например, обращение через точку к реквизитам неопределенного типа).

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

← На главную