В данной статье будут рассмотрены базовые возможности подсистемы "Оценка производительности" в библиотеке стандартных подсистем.

В материале статьи я приведу два примера использования "оценки производительности" - для обычных "линейных операций" и для "длительных операций" (фоновых). Данную тему считаю интересной для оценки возможностей ваших систем. Сам довольно часто использую данных функционал.

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

Создание новой ключевой операции, встраивание ее в объект оценки произодительности.

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

&НаСервере
Процедура ПодготовкаМассиваКлючевыхОперацийСервер()
	
	КлючевыеОперации = Новый Массив();
	
	КлючеваяОперация1 = Новый Структура("ИмяКлючевойОперации, ЦелевоеВремя");
	КлючеваяОперация1.ИмяКлючевойОперации = "ТестоваяКлючеваяОперация1";
	КлючеваяОперация1.ЦелевоеВремя = 1;	
	
	КлючеваяОперация2 = Новый Структура("ИмяКлючевойОперации, ЦелевоеВремя");
	КлючеваяОперация2.ИмяКлючевойОперации = "ТестоваяКлючеваяОперация2";
	КлючеваяОперация2.ЦелевоеВремя = 1;	

	
	КлючевыеОперации.Добавить(КлючеваяОперация1);
	КлючевыеОперации.Добавить(КлючеваяОперация2);

	// Записи в справочник "Ключевые операции"
	ОценкаПроизводительности.СоздатьКлючевыеОперации(КлючевыеОперации);
	
	
КонецПроцедуры	

В результате, в справочнике ключевых операций появляется запись о ней:

Далее, напишем код, который будет "ловить эту операцию" в обработке проведения документа. Исходный код обработки проведения пусть выглядит вот так:

Процедура ОбработкаПроведения(Отказ, РежимПроведения)
	
	СформироватьДвиженияПоМестамХранения();
	
	СформироватьБухгалтерскиеДвижения();
	
КонецПроцедуры

Теперь, "обернем" этот код в "Оценку производительности":

Процедура ОбработкаПроведения(Отказ, РежимПроведения)
	
    ВремяНачалаЗамера = ОценкаПроизводительности.НачатьЗамерВремени();

	СформироватьДвиженияПоМестамХранения();
	
	СформироватьБухгалтерскиеДвижения();

    ОценкаПроизводительности.ЗакончитьЗамерВремени("ТестоваяКлючеваяОперация1",ВремяНачалаЗамера,Товары.Количество(), "Вес по табличной части ""Товары""");

	
КонецПроцедуры

для пояснения - что такое функция НачатьЗамерВремени():

// Возвращаемое значение:
//  Число - число длиной 14 символов, время UTC начала с точностью до миллисекунд.

Функция НачатьЗамерВремени() Экспорт
	
	ВремяНачала = 0;
	
	Если ОценкаПроизводительностиВызовСервераПовтИсп.ВыполнятьЗамерыПроизводительности() Тогда
		ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
	КонецЕсли;
	
	Возврат ВремяНачала;
	
КонецФункции

а Товары.Количество() - это "вес замера", в данном случае количество записей в таблице "Товары" моего документа.

Запускаем код (проводим документ) и получаем вот такой результат (см рис.2) - запись о выполнении операции проведения "ТестоваяКлючеваяОперация1" в регистре "Замеры":

В комментарии дана информация по выполнению, в том числе версия платформы. Моя операция выполнилась за 0.02 сек. "Вес замера", равный 4 - это количество товаров в моей табличной части.

Далее, сделав несколько подобных замеров "проведений", я попробую оценить расчетный APDEX (индекс производительности операции или приложения).

На данном простом примере - "операции проведения", расчетный APDEХ у меня получился близким к отличному 0.929. (отличный >= 0.95).

Вот так можно оценивать скорость выполнения кода, оптимизировать его по данному индексу производительности APDEX.

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

Оценка производительности длительной операции

В этой части я попробую по-шагово объяснить использование функционала оценки производительности в длительных операциях.

Для начала создаем кнопку, на которую "вешаем" событие запуска длительной операции:

&НаКлиенте
Процедура ВыполнитьДействие(Команда)
	ФоновоеЗадание = ВыполнитьНаСервереДЛ();
	
	НастройкиОжидания  = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
	Обработчик = Новый ОписаниеОповещения("ПослеВыполнениеДействия", ЭтотОбъект);
	ДлительныеОперацииКлиент.ОжидатьЗавершение(ФоновоеЗадание, Обработчик, НастройкиОжидания);
	
КонецПроцедуры

Далее, опишем функцию ВыполнитьНаСервереДЛ()

&НаСервере
Функция НачатьВыполнениеНаСервереДЛ()
	
	
	ПараметрыПроцедуры = Новый Структура;
	ПараметрыПроцедуры.Вставить("Параметр1", 1);
		
	ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
	ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = 'Замер'");
	
	Возврат ДлительныеОперации.ВыполнитьВФоне("ВыполнитьДействиеДлительныйЗамер", 
		ПараметрыПроцедуры, ПараметрыВыполнения);
	
КонецФункции

Описываем функцию ВыполнитьДействиеДлительныйЗамер() (располагаем ее в общем модуле, например)

Процедура ВыполнитьДействие(Параметры, АдресРезультата) Экспорт
	
	ОписаниеЗамера = ОценкаПроизводительности.НачатьЗамерДлительнойОперации("ТестоваяКлючеваяОперация2");

НачатьТранзакцию();

//......

Попытка
		Для СчетчикКонтрагента = 1 По КоличествоКонтрагентов Цикл
			КонтрагентОбъект = Справочники._ДемоКонтрагенты.СоздатьЭлемент();
			
			КонтрагентОбъект.Наименование = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НаименованиеКонтрагента, Формат(СчетчикКонтрагента, "ЧГ="));
			КонтрагентОбъект.Записать();
			ОценкаПроизводительности.ЗафиксироватьЗамерДлительнойОперации(ОписаниеЗамера, 1, "ЗаписьКонтрагента");
			МассивОбъектов.Добавить(КонтрагентОбъект.Ссылка);
			Для СчетчикСчета = 1 По КоличествоБанковскихСчетовКонтрагента Цикл			
				СчетОбъект = Справочники._ДемоБанковскиеСчета.СоздатьЭлемент();
				СчетОбъект.Владелец = КонтрагентОбъект.Ссылка;
				СчетОбъект.Наименование = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НаименованиеСчета, Формат(СчетчикКонтрагента, "ЧГ="));
				СчетОбъект.Записать();                       
				ОценкаПроизводительности.ЗафиксироватьЗамерДлительнойОперации(ОписаниеЗамера, 1, "ЗаписьБанковскогоСчета");
			КонецЦикла;
		КонецЦикла;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
	КонецПопытки;
		
	Если УдалитьСозданные Тогда
		ТаблицаКонтрагентов = Новый ТаблицаЗначений;
		ТаблицаКонтрагентов.Колонки.Добавить("Контрагент", Новый ОписаниеТипов("СправочникСсылка._ДемоКонтрагенты"));
		ТаблицаКонтрагентов.ЗагрузитьКолонку(МассивОбъектов, "Контрагент");
		НачатьТранзакцию();
		Попытка
			Блокировка = Новый БлокировкаДанных;
			ЭлементБлокировки = Блокировка.Добавить("Справочник._ДемоКонтрагенты");
			ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
			ЭлементБлокировки.ИсточникДанных = ТаблицаКонтрагентов;
			ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Ссылка", "Контрагент");
			Блокировка.Заблокировать();
			Для Каждого Элемент Из МассивОбъектов Цикл
				ЭлементОбъект = Элемент.ПолучитьОбъект();
				ЭлементОбъект.Удалить();
			КонецЦикла;	
			ЗафиксироватьТранзакцию();
		Исключение
			ОтменитьТранзакцию();
		КонецПопытки;
	КонецЕсли;



//......

ЗафиксироватьТранзакцию();

    ОценкаПроизводительности.ЗакончитьЗамерДлительнойОперации(ОписаниеЗамера, МассивОбъектов.Количество(), "Тесовая кличевая операция 2");


КонецПроцедуры

В данной функции я "обернул код" в НачатьЗамерДлительнойОперации и ЗакончитьЗамерДлительнойОперации. Далее, все идентично, как с "обычным" замером.

Как видите, здесь подход точно такой же. Кому интересна информация о длительных операциях - можете посмотреть у меня в статьях - пару лет назад, я достаточно подробно разбирал этот материал и приводил примеры.

Теперь, перейдем к заключению этой статьи и сделаем выводы.

Заключение и выводы

В статье был рассмотрен основной базовый функционал типовых конфигураций - модулей  "Оценка производительности" БСП. Было приведено два практических примера использования этой подсистемы - использование замеров и замеров длительных операций. Как я отмечал ранее, типовые процедуры и функции в примерах уже "готовы" - ничего не нужно придумывать - нужно взять и использовать.

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

Комментарии (2)


  1. vis_inet
    22.12.2022 12:32

    Скажите, откуда берётся "целевое время", что оно означает ?


    1. Ivanko63rus
      22.12.2022 17:50

      Целевое время указывается человеком. Например заказчик говорит что операция должна выполняться не дольше 0,5 сек или это может быть прописано в ТЗ по проекту.

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