Для тех, кто не понимает, как можно сравнивать «Коннектор для 1С:Шины» и «Регистры сведений», лучше для начала прочитать вот эти две статьи:
Поинтегрируем: сервисы интеграции – новый стандарт или просто коннектор?
Сервисы интеграции без Шины и интеграции
После того, как я написал статьи про «Сервисы интеграции» и опубликовал инструменты по работе с ними, хотел двигаться дальше по плану, но коллеги стали задавать вопросы. Один из вопросов не смог оставить без внимания, так как самому стало интересно узнать на него ответ:
Спасибо за вопрос Cmapnep.
Замер сделал, единственное, я не стал в регистрах имитировать хранение данных в виде двоичных данных и потока. В регистрах будет просто структура параметров, повторяющая структуру «сообщения сервисов интеграции» и тело сообщения.
Приступим
Для начала создаем чистую как слезу младенца конфигурацию. Добавляем в нее «Сервис интеграции» с именем «ДляЗамера» и создадим канал «СообщенияДляЗамера» на отправку:
Это будет подопытный №1.
Далее создаем «Регистр сведений» с именем «СообщенияДляЗамера» и максимально повторяем структуру канала и «сообщения сервисов интеграции»:
Где:
Измерения:
Идентификатор – УникальныйИдентификатор
Ресурсы:
Позиция – Число(10)
ДатаУстаревания – Дата и время
ШапкаСообщения – ХранилищеЗначения – тут мы будем хранить структуру свойств и параметров.
ТелоСообщения – ХранилищеЗначения – тут мы будем хранить тело сообщения
Это будет подопытный №2.
Давайте посмотрим, что у нас получилось в СУБД
По-моему, вышло неплохо, даже Борис Георгиевич не отличит:
Где:
InfoRg53 – Регистр сведений «СообщенияДляЗамера»
IntegChannelOutQueue50 – Канал «СообщенияДляЗамера»
Добавим обработки в нашу конфигурацию.
Нам понадобится обработка «Сообщения сервисов интеграции» и создадим обработку, с помощью которой будем запускать замеры «Замер регистров сведений и сервисов интеграции»:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ЧислоПотоков = 1;
КоличествоЗаписей = 1;
ТипЗамера = Элементы.ТипЗамера.СписокВыбора[0].Значение;
ТекущийРазмерТела = 0;
КонецПроцедуры
&НаКлиенте
Процедура ТелоСообщенияПриИзменении(Элемент)
ТекущийРазмерТела = ТелоСообщенияПриИзмененииНаСервере(ТелоСообщения);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ТелоСообщенияПриИзмененииНаСервере(ТелоСообщения)
Буфер = ПолучитьБуферДвоичныхДанныхИзСтроки(ТелоСообщения);
//Получает размер двоичных данных в байтах.
Возврат Буфер.Размер;
КонецФункции
&НаКлиенте
Процедура НачатьЗамер(Команда)
НачатьЗамерНаСервере();
КонецПроцедуры
&НаСервере
Процедура НачатьЗамерНаСервере()
Если ЧислоПотоков < 1 Тогда
ЧислоПотоков = 1;
КонецЕсли;
Если КоличествоЗаписей < 1 Тогда
КоличествоЗаписей = 1;
КонецЕсли;
СтруктураВходныхПараметров = Новый Структура;
СтруктураВходныхПараметров.Вставить("ДатаУстаревания", ТекущаяДатаСеанса() + 60 * 86400);
СтруктураВходныхПараметров.Вставить("КодОтправителя", "ЗамерРегистровСведенийИСервисовИнтеграции");
СтруктураВходныхПараметров.Вставить("ТелоСообщения", ТелоСообщения);
СтруктураВходныхПараметров.Вставить("РазмерСообщения", ТекущийРазмерТела);
СтруктураВходныхПараметров.Вставить("ТипСообщения", ТипЗамера);
// объем порции данных для обработки каждым потоком
РазмерПорции = Цел(КоличествоЗаписей / ЧислоПотоков);
Для НомерПотока = 1 По ЧислоПотоков Цикл
СтруктураВходныхПараметров.Вставить("КодПолучателя", ТипЗамера+"_Поток"+НомерПотока);
Если НомерПотока = ЧислоПотоков Тогда
// если это последний поток, то посылаем все оставшиеся данные
РазмерПорции = КоличествоЗаписей - (ЧислоПотоков * РазмерПорции) + РазмерПорции;
КонецЕсли;
СтруктураВходныхПараметров.Вставить("КоличествоЗаписей", РазмерПорции);
// определяем массив параметров для процедуры
НаборПараметров = Новый Массив;
НаборПараметров.Добавить(СтруктураВходныхПараметров);
ФоновыеЗадания.Выполнить("ФоновоеВыполнение.ЗаписатьСообщения"+ТипЗамера, НаборПараметров);
КонецЦикла;
КонецПроцедуры
Примечание:
У нас будет три типа замера.
1 Сервис интеграции – запись в канал сервиса интеграции
2 РС набор записей – запись в регистр сведений при помощи набора данных.
3 РС менеджер записи – запись в регистр сведений при помощи менеджера записи.
Еще нам понадобится хранилище результатов для замеров. Вообще логично было создать регистр сведений, но я решил сделать «сервис интеграции» и для замеров. Это просто моя прихоть, не больше того 😉
Остается создать модуль, для фоновых заданий, в котором будут проходить сами замеры.
Назовем модуль «ФоновоеВыполнение»:
// Процедура - Записать сообщения в регистр сведений при помощи Менеджера записи
//
// Параметры:
// СтруктураВходныхПараметров - Структура - Содержится вся необходимая для замера информация
//
Процедура ЗаписатьСообщенияРСМенеджерЗаписи(СтруктураВходныхПараметров) Экспорт
ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
КоличествоЗаписей = СтруктураВходныхПараметров.КоличествоЗаписей;
Для счетчик = 1 По КоличествоЗаписей Цикл
// Так же как и в сообщениях сервисов интеграции считаем УИ уникальным
ТекИдентификатор = Новый УникальныйИдентификатор;
МенеджерЗаписи = РегистрыСведений.СообщенияДляЗамера.СоздатьМенеджерЗаписи();
// Записываем тело сообщения
МенеджерЗаписи.ТелоСообщения = Новый ХранилищеЗначения(СтруктураВходныхПараметров.ТелоСообщения);
// Изображаем структуру на подобии Сообщения сервисов интеграции
МенеджерЗаписи.Идентификатор = ТекИдентификатор;
МенеджерЗаписи.ДатаУстаревания = СтруктураВходныхПараметров.ДатаУстаревания;
МенеджерЗаписи.Позиция = счетчик;
// Заполняем свойства сообщения
ШапкаСообщения = Новый Структура;
ШапкаСообщения.Вставить("ДатаОтправки", ТекущаяДатаСеанса());
ШапкаСообщения.Вставить("ДатаУстаревания", СтруктураВходныхПараметров.ДатаУстаревания);
ШапкаСообщения.Вставить("Идентификатор", ТекИдентификатор);
ШапкаСообщения.Вставить("КодОтправителя", СтруктураВходныхПараметров.КодОтправителя);
ШапкаСообщения.Вставить("КодПолучателя", СтруктураВходныхПараметров.КодПолучателя);
// Заполняем свойство Параметры сообщения
Параметры = Новый Структура("ТипСообщения", СтруктураВходныхПараметров.ТипСообщения);
Параметры.Вставить("РазмерСообщения", СтруктураВходныхПараметров.РазмерСообщения);
ШапкаСообщения.Вставить("Параметры", Параметры);
// Помещаем структуру свойств
МенеджерЗаписи.ШапкаСообщения = Новый ХранилищеЗначения(ШапкаСообщения);
// Сохраняем сообщение в регистре
МенеджерЗаписи.Записать();
КонецЦикла;
Длительность = ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачала;
СоздатьСообщениеОЗамере(СтруктураВходныхПараметров, Длительность);
КонецПроцедуры
// Процедура - Записать сообщения в регистр сведений при помощи Набора записи
//
// Параметры:
// СтруктураВходныхПараметров - Структура - Содержится вся необходимая для замера информация
//
Процедура ЗаписатьСообщенияРСНаборЗаписей(СтруктураВходныхПараметров) Экспорт
ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
КоличествоЗаписей = СтруктураВходныхПараметров.КоличествоЗаписей;
Для счетчик = 1 По КоличествоЗаписей Цикл
// Так же как и в сообщениях сервисов интеграции считаем УИ уникальным
ТекИдентификатор = Новый УникальныйИдентификатор;
НаборЗаписей = РегистрыСведений.СообщенияДляЗамера.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Идентификатор.Установить(ТекИдентификатор);
НоваяЗапись = НаборЗаписей.Добавить();
// Записываем тело сообщения
НоваяЗапись.ТелоСообщения = Новый ХранилищеЗначения(СтруктураВходныхПараметров.ТелоСообщения);
// Изображаем структуру на подобии Сообщения сервисов интеграции
НоваяЗапись.Идентификатор = ТекИдентификатор;
НоваяЗапись.ДатаУстаревания = СтруктураВходныхПараметров.ДатаУстаревания;
НоваяЗапись.Позиция = счетчик;
// Заполняем свойства сообщения
ШапкаСообщения = Новый Структура;
ШапкаСообщения.Вставить("ДатаОтправки", ТекущаяДатаСеанса());
ШапкаСообщения.Вставить("ДатаУстаревания", СтруктураВходныхПараметров.ДатаУстаревания);
ШапкаСообщения.Вставить("Идентификатор", ТекИдентификатор);
ШапкаСообщения.Вставить("КодОтправителя", СтруктураВходныхПараметров.КодОтправителя);
ШапкаСообщения.Вставить("КодПолучателя", СтруктураВходныхПараметров.КодПолучателя);
// Заполняем свойство Параметры сообщения
Параметры = Новый Структура("ТипСообщения", СтруктураВходныхПараметров.ТипСообщения);
Параметры.Вставить("РазмерСообщения", СтруктураВходныхПараметров.РазмерСообщения);
ШапкаСообщения.Вставить("Параметры", Параметры);
// Помещаем структуру свойств
НоваяЗапись.ШапкаСообщения = Новый ХранилищеЗначения(ШапкаСообщения);
// Сохраняем сообщение в регистре
НаборЗаписей.Записать();
КонецЦикла;
Длительность = ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачала;
СоздатьСообщениеОЗамере(СтруктураВходныхПараметров, Длительность);
КонецПроцедуры
// Процедура - Записать сообщения в регистр сведений при помощи Сообщения сервисов интеграции
//
// Параметры:
// СтруктураВходныхПараметров - Структура - Содержится вся необходимая для замера информация
//
Процедура ЗаписатьСообщенияСервисИнтеграции(СтруктураВходныхПараметров) Экспорт
ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
КоличествоЗаписей = СтруктураВходныхПараметров.КоличествоЗаписей;
Для счетчик = 1 По КоличествоЗаписей Цикл
НовоеСообщение = СервисыИнтеграции.ДляЗамера.СоздатьСообщение(СтруктураВходныхПараметров.ДатаУстаревания);
// Записываем тело сообщения
Буфер = ПолучитьБуферДвоичныхДанныхИзСтроки(СтруктураВходныхПараметров.ТелоСообщения);
Тело = НовоеСообщение.ПолучитьТелоКакПоток();
Тело.Записать(Буфер, 0, Буфер.Размер);
Тело.Закрыть();
// Заполняем свойства сообщения
НовоеСообщение.КодОтправителя = СтруктураВходныхПараметров.КодОтправителя;
НовоеСообщение.КодПолучателя = СтруктураВходныхПараметров.КодПолучателя;
// Заполняем свойство Параметры сообщения
НовоеСообщение.Параметры.Вставить("ТипСообщения", СтруктураВходныхПараметров.ТипСообщения);
НовоеСообщение.Параметры.Вставить("РазмерСообщения", Буфер.Размер);
// Сохраняем сообщение в канале
СервисыИнтеграции.ДляЗамера.СообщенияДляЗамера.ОтправитьСообщение(НовоеСообщение);
КонецЦикла;
Длительность = ТекущаяУниверсальнаяДатаВМиллисекундах() - ВремяНачала;
СоздатьСообщениеОЗамере(СтруктураВходныхПараметров, Длительность);
КонецПроцедуры
// Процедура - Создать сообщение о замере
//
// Параметры:
// СтруктураВходныхПараметров - Структура - Содержится вся необходимая для замера информация
// Длительность - Число - Результат замера в миллисекундах
//
Процедура СоздатьСообщениеОЗамере(СтруктураВходныхПараметров, Длительность)
НовоеСообщение = СервисыИнтеграции.СлужебноеХранилище.СоздатьСообщение(СтруктураВходныхПараметров.ДатаУстаревания);
Буфер = ПолучитьБуферДвоичныхДанныхИзСтроки(СтруктураВходныхПараметров.ТелоСообщения);
Тело = НовоеСообщение.ПолучитьТелоКакПоток();
Тело.Записать(Буфер, 0, Буфер.Размер);
Тело.Закрыть();
НовоеСообщение.КодОтправителя = СтруктураВходныхПараметров.КодОтправителя;
НовоеСообщение.КодПолучателя = СтруктураВходныхПараметров.КодПолучателя;
НовоеСообщение.Параметры.Вставить("ТипСообщения", СтруктураВходныхПараметров.ТипСообщения);
НовоеСообщение.Параметры.Вставить("Длительность", Длительность);
НовоеСообщение.Параметры.Вставить("РазмерСообщения",Буфер.Размер);
СервисыИнтеграции.СлужебноеХранилище.РезультатыЗамеров.ОтправитьСообщение(НовоеСообщение);
КонецПроцедуры
Создаем подсистему «Замеры», добавляем в ее состав все созданные ранее объекты:
Заходим в клиента и активируем «сервисы интеграции» без настроек.
Я буду использовать обработку «Настройка сервисов интеграции»:
Перед замерами я проверил, что во всех трех случаях операции записи занимают примерно один и тот же процент времени от выполнения кода замера.
1 Сервисы интеграции сохраняют сообщение так:
СервисыИнтеграции.ДляЗамера.СообщенияДляЗамера.ОтправитьСообщение(НовоеСообщение);
Эта операция заняла 86,24% от всего времени при замере.
2 Запись в регистр сведений через менеджер записи:
МенеджерЗаписи.Записать();
Эта операция заняла 85,70% от всего времени при замере.
3 Запись в регистр сведений через набор записи:
НаборЗаписей.Записать();
Эта операция заняла 86% от всего времени при замере.
Как видите, все операции записи данных занимают примерно равный процент выполнения всего кода.
Начинаем замерять
*Все данные в таблицах будут выведены в миллисекундах.
*Каждый замер будет проводиться три раза. Среднее из трех замеров будем считать за результат
*Будем создавать по 10000 сообщений на каждый замер
*Будем делать замеры в один, два и четыре потока
*Будем делать замеры без тела, с телом 1 кб и телом 10кб
Замер с пустым телом сообщения в один поток:
|
Замер 1 |
Замер 2 |
Замер 3 |
Среднее |
Место |
Сервис интеграции |
40079 |
43599 |
44401 |
42693 |
1 |
РС набор записей |
54049 |
55376 |
48210 |
52545 |
3 |
РС менеджер записи |
48878 |
49086 |
56296 |
51420 |
2 |
Сервисы интеграции показали себя лучше регистров, запись прошла примерно на 17-19% быстрее.
Замер с пустым телом сообщения в два потока:
|
Замер 1 |
Замер 2 |
Замер 3 |
Среднее |
Место |
|||
Поток1 |
Поток2 |
Поток1 |
Поток2 |
Поток1 |
Поток2 |
|||
Сервис интеграции |
22524 |
22515 |
22614 |
22606 |
22232 |
22222 |
22452 |
1 |
РС набор записей |
28926 |
28925 |
28401 |
28418 |
26940 |
26931 |
28090 |
2 |
РС менеджер записи |
28921 |
28939 |
27777 |
27783 |
29184 |
29178 |
28630 |
3 |
В два потока получили сильный прирост по записи, примерно в 2 раза быстрее, чем в один поток. Сервисы интеграции показали себя быстрее регистров примерно на 20-22%.
Замер с пустым телом сообщения в четыре потока:
|
Замер 1 |
Замер 2 |
Замер 3 |
Среднее |
Место |
|||||||||
Птк1 |
Птк2 |
Птк3 |
Птк4 |
Птк1 |
Птк2 |
Птк3 |
Птк4 |
Птк1 |
Птк2 |
Птк3 |
Птк4 |
|||
Сервис интеграции |
13414 |
13453 |
13453 |
13462 |
12771 |
12782 |
12797 |
12823 |
13077 |
13032 |
13076 |
13150 |
13108 |
1 |
РС набор записей |
15915 |
15951 |
15957 |
15918 |
15935 |
15958 |
15953 |
15958 |
15506 |
15433 |
15453 |
15453 |
15783 |
3 |
РС менеджер записи |
15745 |
15782 |
15814 |
15820 |
15095 |
15100 |
15108 |
15198 |
15294 |
15373 |
15385 |
15280 |
15416 |
2 |
В четыре потока получили сильный прирост по записи, более чем в 3 раза быстрее, чем в один поток, сервисы интеграции показали себя быстрее регистров примерно на 15-17%.
Замер с телом содержащим сообщение 1024 байт в один поток:
|
Замер 1 |
Замер 2 |
Замер 3 |
Среднее |
Место |
Сервис интеграции |
42337 |
41789 |
41862 |
41996 |
1 |
РС набор записей |
52045 |
54855 |
49505 |
52135 |
3 |
РС менеджер записи |
53777 |
50024 |
52400 |
52067 |
2 |
Сервисы интеграции показали себя лучше регистров, запись прошла примерно на 19% быстрее. Я сравнил в SQL тело сообщения у регистров и сообщения сервисов интеграций, они практически совпали за исключением трех небольших фрагментов.
Замер с телом, содержащим сообщение 1024 байт в два потока:
|
Замер 1 |
Замер 2 |
Замер 3 |
Среднее |
Место |
|||
Поток1 |
Поток2 |
Поток1 |
Поток2 |
Поток1 |
Поток2 |
|||
Сервис интеграции |
24934 |
24939 |
23742 |
23742 |
23752 |
23764 |
24146 |
1 |
РС набор записей |
28960 |
28977 |
29067 |
29090 |
32072 |
32081 |
30041 |
3 |
РС менеджер записи |
28900 |
28912 |
29572 |
29572 |
27370 |
27383 |
28618 |
2 |
Сервисы интеграции показали себя лучше регистров, запись прошла примерно на 16-20% быстрее.
Замер с телом, содержащим сообщение 1024 байт в четыре потока:
|
Замер 1 |
Замер 2 |
Замер 3 |
Среднее |
Место |
|||||||||
Птк1 |
Птк2 |
Птк3 |
Птк4 |
Птк1 |
Птк2 |
Птк3 |
Птк4 |
Птк1 |
Птк2 |
Птк3 |
Птк4 |
|||
Сервис интеграции |
13672 |
13692 |
13714 |
13718 |
12651 |
12680 |
12813 |
12873 |
12603 |
12624 |
12653 |
12732 |
13035 |
1 |
РС набор записей |
14618 |
14704 |
14717 |
14749 |
15533 |
15554 |
15567 |
15637 |
15160 |
15183 |
15225 |
15270 |
15160 |
2 |
РС менеджер записи |
15748 |
15762 |
15762 |
15845 |
16305 |
16310 |
16347 |
16353 |
15406 |
15438 |
15516 |
15518 |
15859 |
3 |
В четыре потока получили сильный прирост по записи, более чем в 3 раза быстрее, чем в один поток, сервисы интеграции показали себя быстрее регистров примерно на 14-18%.
Замер с телом, содержащим сообщение 10240 байт в один поток:
|
Замер 1 |
Замер 2 |
Замер 3 |
Среднее |
Место |
Сервис интеграции |
47235 |
46038 |
46477 |
46583 |
1 |
РС набор записей |
52156 |
53904 |
49940 |
52000 |
2 |
РС менеджер записи |
51683 |
56499 |
57946 |
55376 |
3 |
Сервисы интеграции показали себя лучше регистров, запись прошла примерно на 11-16% быстрее. По сравнению с телом 1024 байт сообщения сохранялись примерно на 10% дольше.
Замер с телом, содержащим сообщение 10240 байт в два потока:
|
Замер 1 |
Замер 2 |
Замер 3 |
Среднее |
Место |
|||
Поток1 |
Поток2 |
Поток1 |
Поток2 |
Поток1 |
Поток2 |
|||
Сервис интеграции |
25421 |
25453 |
25020 |
25027 |
28363 |
28370 |
26276 |
1 |
РС набор записей |
28780 |
28801 |
30554 |
30584 |
34809 |
34815 |
31391 |
3 |
РС менеджер записи |
29048 |
29050 |
29101 |
29114 |
29925 |
29923 |
29360 |
2 |
Сервисы интеграции показали себя лучше регистров, запись прошла примерно на 11-16% быстрее.
Замер с телом, содержащим сообщение 1024 байт в четыре потока:
|
Замер 1 |
Замер 2 |
Замер 3 |
Среднее |
Место |
|||||||||
Птк1 |
Птк2 |
Птк3 |
Птк4 |
Птк1 |
Птк2 |
Птк3 |
Птк4 |
Птк1 |
Птк2 |
Птк3 |
Птк4 |
|||
Сервис интеграции |
15300 |
15435 |
15505 |
15555 |
14176 |
14200 |
14190 |
14191 |
13660 |
13661 |
13696 |
13707 |
14440 |
1 |
РС набор записей |
16128 |
16167 |
16160 |
16170 |
16058 |
16085 |
16072 |
16082 |
16284 |
16291 |
16297 |
16296 |
16174 |
3 |
РС менеджер записи |
15899 |
15947 |
15960 |
16028 |
15677 |
15702 |
15703 |
15709 |
15555 |
15563 |
15577 |
15578 |
15742 |
2 |
В четыре потока получили сильный прирост по записи, более чем в 3 раза быстрее, чем в один поток, сервисы интеграции показали себя быстрее регистров примерно на 8-11%.
Итоги
Исходя из тех замеров, что я провел, можно сказать, что механизм по подготовке сообщений к отправке на «Сообщениях сервисов интеграции» является быстрее, чем то же самое делать на регистрах, при этом он имеет как достоинства, так и недостатки.
Если вы до сих пор его не использовали, присмотритесь к нему.
Конфигурацию, которую скидал для замеров, прикладываю, чтобы вы и сами могли поэкспериментировать.
Демонстрация замера:
На этом статью завершаю.
Всем желаю профессионального роста и интересных задач!
Полезные ссылки:
Три инструмента для сервисов интеграции – Бесплатные инструменты по работе с сервисами интеграции.
PAPI-tools – Проект на GitHub содержащий исходники обработок, которые будут первоначально выкладываться в данном проекте, а в будущем перетекать в подсистему PAPI (релиз подсистемы запланирован на 19.05.2024)
Поинтегрируем: сервисы интеграции – новый стандарт или просто коннектор? – Статья описывает механизм «Сервисы интеграции» изнутри и снаружи
Сервисы интеграции без Шины и интеграции – Статья показывает пример по использованию сервисов интеграции и сообщений сервисов интеграции с «ПоказатьОповещениеПользователя»