При работе с конфигурацией 1С:Управление нашей фирмой (УНФ) разработчики часто сталкиваются с необъяснимым замедлением работы интерфейса. Одной из наиболее выраженных проблем является длительное открытие формы документа Заказ покупателя. Проведя замер производительности, можно обнаружить аномальное количество вызовов процедуры ОбработкаПолученияПредставления в модуле менеджера документа Событие. В некоторых случаях количество вызовов достигает 10–12 тысяч раз за одно открытие формы, что парализует работу пользователя. В данной статье мы разберем причины этой "событийной дичи" и найдем способы программного и интерактивного решения проблемы.
Разберем ситуацию подробно. Процедура ОбработкаПолученияПредставления вызывается платформой каждый раз, когда системе необходимо отобразить строковое представление ссылки. Это происходит не только при выводе данных в список, но и при подготовке интерфейсных элементов. Основная причина массовых вызовов при открытии Заказа покупателя кроется в Командном интерфейсе формы, а именно в панели навигации.
В типовых решениях, таких как УНФ, в форме заказа предусмотрены переходы к связанным объектам: событиям, задачам, файлам. Если для этих команд включено свойство Автовидимость, платформа при открытии формы пытается определить, нужно ли выделять пункты меню (например, делать шрифт жирным при наличии записей) или отображать количество связанных документов. Для этого инициализируются динамические списки. Если отбор по ведущему документу (в нашем случае по ссылке на текущий заказ) по какой-то причине не применяется мгновенно на уровне ядра платформы, система начинает считывать представления для всех доступных записей в таблице События, чтобы подготовить интерфейс.
Проанализируем также влияние кода. Если в запросе динамического списка или в коде используется обращение к полю .Представление или функции Представление(Ссылка), это гарантированно триггерит событие в модуле менеджера. При наличии тысяч записей в базе данных даже пустая процедура ОбработкаПолученияПредставления создает колоссальную нагрузку из-за постоянного переключения контекста между сервером приложений и базой данных.
Самый простой и быстрый способ победить проблему — изменить настройки командного интерфейса непосредственно в редакторе формы. Рассмотрим шаги, которые необходимо выполнить:
ЗаказПокупателя (или любого другого документа, который тормозит при открытии).Событие.Этот метод позволяет "успокоить" платформу: она перестанет пытаться инициализировать список событий в фоновом режиме до того момента, пока пользователь явно не кликнет по соответствующей команде в панели навигации.
Зачастую ручная правка каждой формы в конфигурации (особенно если их десятки) нецелесообразна. В таком случае мы можем прибегнуть к программному управлению видимостью элементов командного интерфейса. Выясним, как это сделать правильно, так как прямого свойства Автовидимость в программном интерфейсе формы нет.
Доступ к настройкам осуществляется через коллекцию КомандныйИнтерфейс. Нам необходимо внести изменения в процедуру ПриСозданииНаСервере. Рассмотрим пример кода:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Программное отключение видимости перехода к событиям
// Находим команду перехода в навигационной панели
Для Каждого ЭлементИнтерфейса Из КомандныйИнтерфейс.Навигация Цикл
Если Найти(ЭлементИнтерфейса.Имя, "Событие") > 0 Тогда
ЭлементИнтерфейса.Видимость = Ложь;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Обратите внимание, что использование КомандныйИнтерфейс.Навигация позволяет управлять именно теми ссылками, которые находятся в верхней части формы или в панели "Перейти". Отключение видимости на этапе создания формы предотвращает избыточное обращение платформы к базе данных для формирования представлений связанных объектов.
Если мы не можем полностью отключить отображение событий (например, они нужны в других списках), необходимо проанализировать содержимое самой процедуры ОбработкаПолученияПредставления в модуле менеджера документа Событие. Посмотрим на типичную ошибку и способ ее исправления.
Неоптимальный код:
Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка)
// Обращение через точку к данным ссылки вызывает неявный запрос к БД!
Если ЗначениеЗаполнено(Данные.Ссылка) Тогда
Представление = "Событие: " + Данные.ТипСобытия + " от " + Формат(Данные.Дата, "ДЛФ=D");
СтандартнаяОбработка = Ложь;
КонецЕсли;
КонецПроцедуры
Проанализируем ситуацию: если в структуру Данные не переданы поля ТипСобытия и Дата, платформа выполнит отдельный SQL-запрос для каждой из 12 000 записей. Чтобы этого избежать, всегда проверяйте наличие полей в структуре Данные. Если полей нет, лучше позволить платформе сформировать стандартное представление, не нагружая систему.
Рекомендуемый подход:
Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка)
// Проверяем, переданы ли нужные поля в структуру, чтобы избежать запросов
Если Данные.Свойство("ТипСобытия") И Данные.Свойство("Дата") Тогда
Представление = СтрШаблон("Событие %1 от %2", Данные.ТипСобытия, Формат(Данные.Дата, "ДЛФ=D"));
СтандартнаяОбработка = Ложь;
КонецЕсли;
// Если полей нет, СтандартнаяОбработка остается Истина,
// и платформа возьмет данные из кэша или стандартных полей.
КонецПроцедуры
Выясним, какие еще факторы могут влиять на производительность. Во-первых, это RLS (Record Level Security). Если в базе включено ограничение доступа на уровне записей для документа Событие, то при каждом формировании представления платформа обязана проверить права. Умножьте сложность запроса RLS на 12 000 вызовов, и вы получите причину "зависания" формы на 30–40 секунд. Если полные права решают проблему — копайте в сторону оптимизации шаблонов RLS.
Во-вторых, стоит учитывать баги конкретных релизов платформы 8.3. В версиях ветки 8.3.18 и выше иногда наблюдается некорректное поведение динамических списков в панелях навигации, когда они игнорируют параметры выбора до момента первой активации. Обновление на актуальный релиз (например, 8.3.22+) часто помогает снизить остроту проблемы, но не заменяет грамотную настройку видимости командного интерфейса.
Подведем итог: для победы над "событийной дичью" в УНФ необходимо комбинировать отключение Автовидимости в командном интерфейсе формы и оптимизацию кода в ОбработкаПолученияПредставления. Использование программного метода управления КомандныйИнтерфейс.Навигация является наиболее универсальным решением для тиражных конфигураций.