При оптимизации и администрировании крупных информационных баз часто возникает задача выявления наиболее "тяжелых" отчетов. Для этого разработчики пытаются зафиксировать время начала и окончания генерации отчета, чтобы впоследствии записать эти данные в специальный регистр сведений для анализа. Однако стандартные попытки сделать это "в лоб" через модуль объекта отчета часто приводят к тому, что записанное время начала и окончания совпадает до секунды, хотя сам отчет формируется несколько минут. Давайте подробно разберем, почему так происходит, и рассмотрим правильные архитектурные подходы к решению этой задачи.
Рассмотрим типичную ошибку, которую допускают разработчики при попытке замерить время. В модуле объекта отчета задействуется предопределенная процедура ПриКомпоновкеРезультата. Внутри нее перед началом выполнения основного алгоритма фиксируется время старта, а в конце процедуры — время завершения.
Проблема кроется в логике работы самой платформы 1С:Предприятие. По умолчанию параметр процедуры СтандартнаяОбработка равен Истина. Это означает, что процедура ПриКомпоновкеРезультата служит лишь для предварительной настройки компоновщика (установки параметров, отборов, структуры вариантов) перед тем, как платформа сама запустит реальный процесс построения.
Когда управление находится внутри этой процедуры, реальные запросы к базе данных СУБД еще не выполняются, данные не извлекаются и не выводятся в результирующий табличный документ. Платформа выполняет код настройки параметров за миллисекунды, фиксирует "время окончания" в коде разработчика, выходит из процедуры и только после этого начинает ресурсоемкий процесс генерации макета, выполнения запросов и вывода областей. Таким образом, замеряется лишь время инициализации параметров, а не само формирование отчета.
Для того чтобы зафиксировать честное время выполнения всех запросов и вывода данных, нам необходимо полностью взять процесс компоновки под свой контроль. Для этого мы установим параметр СтандартнаяОбработка в значение Ложь и выполним все этапы генерации отчета вручную.
Давайте разберем по шагам, как переписать процедуру ПриКомпоновкеРезультата для программного замера реального времени формирования:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Перехватываем управление у платформы
СтандартнаяОбработка = Ложь;
// Выполняем предварительные настройки параметров и отборов (код автора)
ткУправлениеВыводомИнформацииСервер.УстановитьДатыЗапретаВОтчете(КомпоновщикНастроек);
Параметр = НастройкаПараметра("ПоказыватьПродажи");
Если Параметр <> Неопределено Тогда
Параметр.Использование = Истина;
КонецЕсли;
// ... Здесь выполняются остальные настройки параметров компоновщика ...
// Фиксируем начало реального процесса формирования
ЗаписьРС = ОтразитьНачалоИспользованиеОтчета();
ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
// ЭТАП 1: Инициализация макета компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(
СхемаКомпоновкиДанных,
КомпоновщикНастроек.ПолучитьНастройки(),
ДанныеРасшифровки
);
// ЭТАП 2: Создание и инициализация процессора компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);
// ЭТАП 3: Вывод результата в табличный документ
// Очищаем документ-результат перед выводом
ДокументРезультат.Очистить();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
// Именно этот метод выполняет запросы к СУБД и производит расчеты. Он занимает 99% времени.
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
// Фиксируем точное время окончания формирования
ВремяОкончания = ТекущаяУниверсальнаяДатаВМиллисекундах();
// Рассчитываем точную длительность в секундах (с учетом миллисекунд для высокой точности)
ДлительностьСекунд = (ВремяОкончания - ВремяНачала) / 1000;
// Записываем финальные результаты в наш регистр сведений
ОтразитьОкончаниеИспользованиеОтчета(ЗаписьРС, ДлительностьСекунд);
КонецПроцедуры
Вспомогательные процедуры записи в регистр сведений при этом примут следующий вид:
Функция ОтразитьНачалоИспользованиеОтчета()
Запись = РегистрыСведений.ИспользованиеОтчетов.СоздатьМенеджерЗаписи();
Запись.Период = ТекущаяДатаСеанса();
Запись.ДатаНачалаФормирования = ТекущаяДатаСеанса();
Запись.Отчет = ЭтотОбъект.Метаданные().Имя;
Если ЭтотОбъект.СхемаКомпоновкиДанных.ВариантыНастроек.Количество() > 0 Тогда
Запись.ВариантОтчета = ЭтотОбъект.СхемаКомпоновкиДанных.ВариантыНастроек[0].Представление;
КонецЕсли;
Запись.Пользователь = ПараметрыСеанса.ТекущийПользователь;
Возврат Запись;
КонецФункции
Процедура ОтразитьОкончаниеИспользованиеОтчета(Запись, ДлительностьСекунд)
Запись.ДатаОкончанияФормирования = ТекущаяДатаСеанса();
// Добавляем в структуру регистра новый ресурс "Длительность" (Число)
Запись.Длительность = ДлительностьСекунд;
Запись.Записать(Ложь);
КонецПроцедуры
Благодаря использованию функции ТекущаяУниверсальнаяДатаВМиллисекундах() мы можем зафиксировать время работы алгоритма с точностью до тысячных долей секунды. Это особенно полезно для анализа быстродействия отчетов на небольших тестовых базах данных.
Если ваша конфигурация разработана на основе БСП (Библиотека Стандартных Подсистем), писать собственный код для замеров времени и создавать новые регистры сведений не требуется. В составе БСП уже есть мощный готовый инструмент, работающий по международному стандарту APDEX.
Давайте проанализируем, как использовать данный механизм:
ФормированиеОтчета.[ИмяОтчета] (например, ФормированиеОтчета.Продажи). В качестве целевого времени укажите желаемый порог быстродействия (например, 5 или 10 секунд).
// Фиксируем начало замера ключевой операции
ВремяНачала = ОценкаПроизводительностиКлиентСервер.НачатьЗамерВремени();
// ... Здесь выполняется логика формирования отчета ...
// Фиксируем окончание замера и записываем данные в системный регистр БСП
ОценкаПроизводительностиКлиентСервер.ЗакончитьЗамерВремени("ФормированиеОтчета.Продажи", ВремяНачала);
Все результаты замеров автоматически записываются в системный регистр сведений ЗамерыВремени. На основе накопленных данных администраторы и аналитики могут строить стандартные отчеты по оценке производительности системы, отслеживая динамику быстродействия конфигурации в разрезе дней, часов и конкретных пользователей.
В современных конфигурациях 1С формирование тяжелых отчетов практически всегда выполняется в фоновом режиме на сервере приложений. Это делается для того, чтобы интерфейс пользователя не "зависал" во время длительных расчетов.
Мы можем использовать эту особенность платформы для сбора статистики без внесения изменений в код самих отчетов. Для этого достаточно настроить периодический мониторинг фоновых заданий:
При выборе метода замера длительности формирования отчетов руководствуйтесь следующими правилами: