Неоптимальная работа метода ЗаполнитьЗначенияСвойств

06.06.24

База данных - HighLoad оптимизация

Метод очень медленно работает, когда параметр приемник содержит намного меньше свойств, чем источник.

Недавно коллега обнаружил медленную работу ЗаполнитьЗначенияСвойств, это было значительным узким местом в прайс-листе конфигурации УХ. Сначала удивился - не поверил. Оказалось в приемнике 5 полей, а в источнике > 100, ожидал что метод анализирует где меньше свойств и выбирает алгоритм обхода, но нет, судя по всему всегда обходится источник.

 

Анализ медленной работы

Для проверки сделал код, выполняющийся в цикле 10000 раз, который в первом варианте заполняет структуру с 5 свойствами по структуре, с 500 свойствами выполнилось за 325 мс и во втором варианте, наоборот, 35 мс. На мой взгляд разница некритическая, но видимо, когда источник или приемник имеют другие типы, разница становится намного значительнее (в УХ источник и приемник были типа СтрокаДерева).

 
 Код проверки гипотезы

 

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

 

Другие функции по этой проблеме

Эта же проблема может проявляться и в другом коде, использующем ЗаполнитьЗначенияСвойств

Например: Функция ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта... (из БСП), достаточно интересно реализована надо растянуть статью :), поэтому приведу код ниже

Функция ЕстьРеквизитИлиСвойствоОбъекта(Объект, ИмяРеквизита) Экспорт
	
	КлючУникальности   = Новый УникальныйИдентификатор;
	СтруктураРеквизита = Новый Структура(ИмяРеквизита, КлючУникальности);
	ЗаполнитьЗначенияСвойств(СтруктураРеквизита, Объект);
	
	Возврат СтруктураРеквизита[ИмяРеквизита] <> КлючУникальности;
	
КонецФункции

 

Вывод

Думаю, кидаться собственными силами исправлять это проблему не стоит, а вот знать нужно.

 

К размышлению

Сейчас метод выглядит так:
ЗаполнитьЗначенияСвойств(<Приемник>, <Источник>, <СписокСвойств>, <ИсключаяСвойства>)

Трудно представить необходимость сценария, когда используются оба параметра СписокСвойств и ИсключаяСвойства одновременно.

Возможно, было бы здорово иметь две функции:

ЗаполнитьЗначенияСвойств(<Приемник>, <Источник>, <СписокСвойств>)

ЗаполнитьЗначенияСвойствСИсключениями(<Приемник>, <Источник>, <ИсключаяСвойства>)

 

p.s.

Данную статью можно считать рекомендациями к анализу, реализации фирмой 1С (можно спасти не одно дерево). Последняя платформа на которой проверил 8.3.24.

Платформа 1С Оптимизация

См. также

Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы

HighLoad оптимизация Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Анализ простого плана запроса. Оптимизация нагрузки на ЦП сервера СУБД используя типовые индексы.

13.03.2024    4039    spyke    28    

47

Быстродействие типовой 1С

HighLoad оптимизация Программист Платформа 1С v8.3 Бесплатно (free)

Оказывается, в типовых конфигурациях 1С есть, что улучшить!

13.03.2024    6196    vasilev2015    19    

39

Анализируем SQL сервер глазами 1С-ника

HighLoad оптимизация Инструменты администратора БД Системный администратор Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Обработка для простого и удобного анализа настроек, нагрузки и проблем с SQL сервером с упором на использование оного для 1С. Анализ текущих запросов на sql, ожиданий, конвертация запроса в 1С и рекомендации, где может тормозить.

1 стартмани

15.02.2024    9495    192    ZAOSTG    74    

105

Переход на Clickhouse для анализа метрик

HighLoad оптимизация Системный администратор Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Принимать, хранить и анализировать показания счетчиков (метрики) в базе 1С? Почему бы нет? Но это решение быстро привело к проблемам с производительностью при попытках построить какую-то более-менее сложную аналитику. Переход на PostgresSQL только временно решил проблему, т.к. количество записей уже исчислялось десятками миллионов и что-то сложное вычислить на таких объемах за разумное время становилось все сложнее. Кое-что уже практически невозможно. А что будет с производительностью через пару лет - представить страшно. Надо что-то предпринимать! В этой статье поделюсь своим первым опытом применения СУБД Clickhouse от Яндекс. Как работает, что может, как на нее планирую (если планирую) переходить, сравнение скорости работы, оценка производительности через пару лет, пример работы из 1С. Все это приправлено текстами запросов, кодом, алгоритмами выполненных действий и преподнесено вам для ознакомления в этой статье.

1 стартмани

24.01.2024    4081    glassman    17    

39

Удаление строк из таблицы значений различными способами с замером производительности

HighLoad оптимизация Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Встал вопрос: как быстро удалить строки из ТЗ? Рассмотрел пять вариантов реализации этой задачи. Сравнил их друг с другом на разных объёмах данных с разным процентом удаляемых строк. Также сравнил с выгрузкой с отбором по структуре.

09.01.2024    8199    doom2good    49    

67

Опыт оптимизации 1С на PostgreSQL

HighLoad оптимизация Системный администратор Программист Бесплатно (free)

При переводе типовой конфигурации 1C ERP/УТ/КА на PostgreSQL придется вложить ресурсы в доработку и оптимизацию запросов. Расскажем, на что обратить внимание при потерях производительности и какие инструменты/подходы помогут расследовать проблемы после перехода.

20.11.2023    10615    ivanov660    6    

78

ТОП проблем/задач у владельцев КОРП лицензий 1С на основе опыта РКЛ

HighLoad оптимизация Бесплатно (free)

Казалось бы, КОРП-системы должны быть устойчивы, быстры и надёжны. Но, работая в рамках РКЛ, мы видим немного другую картину. Об основных болевых точках КОРП-систем и подходах к их решению пойдет речь в статье.

15.11.2023    5808    a.doroshkevich    20    

73
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. artbear 1555 06.06.24 18:49 Сейчас в теме
(0)
Для проверки сделал код, выполняющийся в цикле 10000 раз, который в первом варианте заполняет структуру с 5 свойствами по структуре, с 500 свойствами выполнилось за 325 мс и во втором варианте, наоборот, 35 мс.


непонятно, что за второй вариант.
расшифруй его.
2. KroVladS 34 06.06.24 19:26 Сейчас в теме
(1)ну ёпт
Второй вариант заполняет структуру с 500 свойствами по структуре, с 5 свойствами
Evg-Lylyk; frkbvfnjh; +2 Ответить
6. Xershi 1496 07.06.24 08:24 Сейчас в теме
(2) нужно было указать что источник содержит 1000 колонок, а приемник 1 вариант 5 и второй вариант 500 колонок. Тогда было бы понятно о чем писали.
13. RustIG 1675 07.06.24 09:53 Сейчас в теме
(2) мы все давно уже поняли :)
ему ненавязчиво подсказывают , как
надо растянуть статью :),

;)
3. PerlAmutor 129 06.06.24 22:45 Сейчас в теме
Давно заметил эту особенность. Обычно заполнение параметра <ИсключаяСвойства> помогает ускорить.
5. Xershi 1496 07.06.24 08:22 Сейчас в теме
(3) обычно эту функцию используют на 90% однородные сущности и чтобы нивелировать разницу. Когда количество колонок огромное, разработчику нужно позаботиться о корретном заполнении, а не бездумном использовании.
Всегда слышал, что функция не бесплатная, наконец написали почему так.
shard; user1822636; SerVer1C; SP2000; +4 Ответить
8. ixijixi 1823 07.06.24 08:49 Сейчас в теме
Ее можно достаточно просто оптимизировать, дополнив явным указанием имени свойства, которое нужно заполнить.
Нельзя ее оптимизировать, т.к. мы заранее не знаем, есть свойство или его нет. При указании несуществующего свойства получим ошибку "Недопустимое значение параметра (параметр номер '3') (Поле объекта не обнаружено)"
Прикрепленные файлы:
kalyaka; ivnik; awk; SemandCheb; user1822636; artbear; RustIG; Evg-Lylyk; +8 Ответить
21. RustIG 1675 07.06.24 10:50 Сейчас в теме
(8) а если засунуть в Попытку Исключение с явным указанием имени поля?
будет быстрее? будет надежнее?
24. ixijixi 1823 07.06.24 11:04 Сейчас в теме
(21)
Попытку
В общем случае не рекомендуется перехватывать исключения
https://its.1c.ru/db/v8std/content/499/hdoc
26. RustIG 1675 07.06.24 11:45 Сейчас в теме
(24) да, понятно, да и в целом, можно тогда по той логике сразу проверять
Попытка
Объект.ИмяРеквизита = Неопределено
Исключение

- без всяких вызовов доп. процедур ЗаполнитьЗначенияСвойств()
30. ixijixi 1823 07.06.24 12:26 Сейчас в теме
57. kalyaka 1082 11.06.24 10:51 Сейчас в теме
(21) Использовать исключения нужно в случаях когда действительно что-то пошло не так. Если же использовать их для проверки в нормальном исполнении кода, то при отслеживании ошибок (логирование) или при отладке будет возникать множество исключений, которые не являются исключительными случаями :)
58. RustIG 1675 11.06.24 12:03 Сейчас в теме
4. vadim1980 131 07.06.24 06:57 Сейчас в теме
Странно, что при упоминании неоптимальности функции ЕстьРеквизитИлиСвойствоОбъекта вы не упомянули о неоптимальнсти использования объекта типа УникальныйИдентификатор в качестве sentinel-object. Гораздо оптимальной использовать вместо него Массив. Разница будет в 4 раза
RustIG; dhurricane; dsdred; +3 2 Ответить
12. webester 26 07.06.24 09:45 Сейчас в теме
(4)
Гораздо оптимальной использовать вместо него Массив. Разница будет в 4 раза

Простите, можно для слоупоков? sentinel-object это (судя по гуглу) объект указывающий на пустое значение? Или я чего-то не понял? Можно как то развернуть каким боком здесь уникальный идентификатор?
19. dhurricane 07.06.24 10:21 Сейчас в теме
(4) Отличная идея, спасибо! Да, подойдет здесь вообще любой объект, сравнение с которым осуществляется по ссылке, т.е. это может быть и любая другая коллекция встроенного языка, запрос, объект и т.д. (если мы не берем в расчет контекст исполнения).
22. RustIG 1675 07.06.24 10:52 Сейчас в теме
(4) до этой мысли надо еще дойти... она не на поверхности .... понять ее можно только если попробовать изучить код, и попробовать оптимизировать свое...
Прикрепленные файлы:
27. RustIG 1675 07.06.24 11:47 Сейчас в теме
(4) в значении может быть пустой массив,
но имя свойства может не совпадать - например в формате джейсон

поэтому проверять на пустой массив неправильно
29. vadim1980 131 07.06.24 12:06 Сейчас в теме
(27) Новый Массив <> Новый Массив
34. RustIG 1675 07.06.24 14:06 Сейчас в теме
(29) хорошо, а если, наоборот, свойство содержит пустой массив. Тогда ваш способ вернет Ложь - поля такого нет. А оно есть и содержит пустой массив.
43. vadim1980 131 07.06.24 16:47 Сейчас в теме
(34) просто замените в данной функции "Новый УникальныйИдентификатор" на "Новый Массив" и убедитесь что все работает, только в разы быстрее
44. RustIG 1675 07.06.24 19:22 Сейчас в теме
7. user1559729 07.06.24 08:34 Сейчас в теме
Возможно, было бы здорово иметь две функции

Вероятно, в контексте вашего предложения лучше иметь 1 функцию ЗаполнитьЗначенияСвойств(<Приемник>, <Источник>, <СписокСвойств>, <ИсключаяСвойства>), где ИсключаяСвойства - Булево.
bulpi; SanchoD; SerVer1C; +3 Ответить
10. YA_418728146 537 07.06.24 09:37 Сейчас в теме
(7) ФлагиВПараметрахМетодаЗло(Истина, Ложь, Истина)
pavlov_dv; Evg-Lylyk; +2 Ответить
31. TeMochkiN 07.06.24 12:32 Сейчас в теме
(10) почему? это какой-то стандарт?
55. user623969_dusa 10.06.24 13:30 Сейчас в теме
(31) удобнее читать код только и всего
ФлагиВПараметрахМетодаЗло(Истина, Ложь, Истина)

ВыполнитьПечать = Истина;
ОтправитьНаПочту = Ложь;
ВообщеЕслиФлаговМногоТоСкорееВсегоФункцияРазбиваетсяНаНескол­ькоНезависимыхДействийАНастройкиПередаютсяВСтруктуреЭтоРеком­ендацияДаже1СНеТолькоХорошийТонВПрограммировании = Истина;
ФлагиВПараметрахМетодаЗло(ВыполнитьПечать, ОтправитьНаПочту, ВообщеЕслиФлаговМногоТоСкорееВсегоФункцияРазбиваетсяНаНескол­ькоНезависимыхДействийАНастройкиПередаютсяВСтруктуреЭтоРеком­ендацияДаже1СНеТолькоХорошийТонВПрограммировании)
9. Evg-Lylyk 4713 07.06.24 09:35 Сейчас в теме
11. tormozit 7176 07.06.24 09:43 Сейчас в теме
Кстати компания 1С всегда на связи по адресу v8@1c.ru
25. artbear 1555 07.06.24 11:35 Сейчас в теме
(11) Ага, я лично написал сегодня 3 предложения на доработку обоих методов
1 - ускорить сам метод
2 - убрать проверку наличия реквизитов для 4х параметра ИсключаемыеСвойства
3 - улучшить метод БСП ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта

Предлагаю и остальным написать в 1С, чтобы исправили.

Исправление 1 и 2 достаточно простые
но Исправление 3 может быть не принято

перешлю текст своих предложений в чат Инфостарт и офиц.чат Сообщества 1С
Dementor; dsdred; +2 Ответить
28. SerVer1C 781 07.06.24 12:05 Сейчас в теме
(25) Было бы здорово, если 1с сделала бы метод для получения списка существующих свойств у объекта.
Dementor; RustIG; +2 Ответить
35. qwinter 680 07.06.24 15:04 Сейчас в теме
(28) Так методы существуют. Просто ими не пользуются)
36. SerVer1C 781 07.06.24 15:10 Сейчас в теме
(35) Думаю, что такие методы есть только у вас и у президента.
37. qwinter 680 07.06.24 15:17 Сейчас в теме
(36) Для какого объекта 1с вы не знаете как посмотреть свойства?
38. SerVer1C 781 07.06.24 15:19 Сейчас в теме
39. qwinter 680 07.06.24 15:26 Сейчас в теме
(38) Для половины свойств есть метаданные, для другой можно обойти свойства в цикле получив список... Но 1сники не знают как получить список свойств... Что же с этим делать?
40. artbear 1555 07.06.24 15:30 Сейчас в теме
(39) вникните в сущность проблемы - нет УНИВЕРСАЛЬНОГО способа получить все свойства любого объекта.
приходится писать костыли, учитывать наличие разных типов и т.д.

наличие этой возможности было бы полезным для разных задач.
простой глобальный метод аналогично ТипЗнч
Dementor; +1 Ответить
49. qwinter 680 08.06.24 15:46 Сейчас в теме
(40) Нет, это вам стоит вникнуть в сущность проблемы. Нет бесплатного кода, вынесение функции в фреймворк 1сного кода не сделает код быстрее. Наоборот только расплодит костыли, потому что когда вы изначально не знаете типы данных что придут в функции мягко говоря не нормально. Вот это костыль, прям костылище!!! И делать костыль для людей плодящих костыли ненормально изначально.
41. SerVer1C 781 07.06.24 15:40 Сейчас в теме
(39) Далеко не для всех объектов таким образом можно получить свойства. А была бы платформенная функция, типа "СвойстваОбъекта(Объект)", то не пришлось бы городить в БСП функцию ЕстьРеквизитИлиСвойствоОбъекта(Объект, ИмяРеквизита) с мутным содержимым.
51. RustIG 1675 08.06.24 15:54 Сейчас в теме
(41)лучше на уровне менеджера объектов, Справочники.Контрагенты.Свойства()
starik-2005; +1 Ответить
52. RustIG 1675 08.06.24 15:56 Сейчас в теме
(41)есть реквизит - я проверяю своей функцией объект. Метаданные(). Реквизиты. Найти(имяреквизита)
- универсальной стараюсь не пользоваться
48. RustIG 1675 08.06.24 15:37 Сейчас в теме
(28) я тоже об этом думал, поддерживаю. Глубоко мыслите, сударь
54. s22 19 10.06.24 08:46 Сейчас в теме
(25) у меня было предложение сделать метод

Зап...(Источник, приемник, "иполе1:пполе1,иполе2:пполе2,иполе3:пполе3")

И
Зап....(Источник, приемник, соответствие)
Где в соответствии имена поля приемника(ключ) и источника(значение)
14. SanchoD 310 07.06.24 09:59 Сейчас в теме
"... когда параметр источник содержит намного меньше свойств, чем приёмник ..."
не бьется с:
"... не поверил, в приемнике 5 полей, а в источнике > 100 ..."
15. Evg-Lylyk 4713 07.06.24 10:07 Сейчас в теме
(14) не поверил что ЗаполнитьЗначенияСвойств является узким местом
ожидал что метод анализирует, где меньше свойств, и выбирает алгоритм обхода
17. SanchoD 310 07.06.24 10:11 Сейчас в теме
(15) в первом предложении источник содержит намного меньше свойств, чем приемник. а во-втором источник > 100, т.е. источник наоборот содержит намного больше свойств, чем приемник.
23. RustIG 1675 07.06.24 10:57 Сейчас в теме
(15) в БП 3.0 примерно 1000 мест, где вызывается неоптимальная функция

вот и ответ, почему базы на управляемых формах так медленно работают и потребляют так много ресурсов (память, ЦП) - птичка клюет по семечку....
Прикрепленные файлы:
45. PerlAmutor 129 08.06.24 06:09 Сейчас в теме
(23) Тут опять пытаются оптимизировать программный код, которого могло бы и не быть. То, что нужно оптимизировать это да, но в реальности надо реализовывать код на более высоком уровне атомарности операций - не циклы использовать, а Загрузить()/Выгрузить() и т.д. Оперировать в коде не строками и объектами, а набором строк и объектов. К сожалению, из-за ограничений платформы например нельзя сделать операцию UPDATE, скажем для одного реквизита конкретного типа документа одновременно с установкой условия выборки. Приходится вызывать ПолучитьОбъект() в цикле. Вместо этого можно было бы сделать МенеджерНабораОбъектов, который бы возвращался в качестве РезультатаЗапроса и сразу возвращал НаборОбъектов по аналогии с набором записей. А у НабораОбъектов сделать метод УстановитьСвойства(), который лишь помещает "намерение" в класс. Реальную установку свойства делать при вызове Записать() с вызовом обработчиков/подписок для каждого объекта. Ну и управление транзакциями туда вкорячить, открывать отдельно для каждого или общая, реакция на возникшее исключение - продолжать/прерывать. Можно было бы сделать итератор, что то типа "Пока МенеджерНабораОбъектов.Записать().Следующий()", чтобы выполнять дополнительные действия после записи каждого объекта.
shard; RustIG; +2 Ответить
16. RustIG 1675 07.06.24 10:08 Сейчас в теме
(0) видимо, надо оптимизировать код так, как на рисунке - согласно синтаксис-помощнику.

А так, спасибо за статью и разбор - неочевидное вероятное вокруг нас :)
Прикрепленные файлы:
18. Evg-Lylyk 4713 07.06.24 10:13 Сейчас в теме
20. RustIG 1675 07.06.24 10:26 Сейчас в теме
(0) посмотрел код - и убрал циклы - скрин прикладываю

заполнение в цикле надо переделать - поскольку счетчик из цикла не используется в процедуре ЗаполнитьЗначенияСвойств.... Хотя, если счетчик эмулирует работу базы в обычном режиме - 1000 раз вызывается каждую минуту, тогда наглядно видно, как теряется эффективность кода...

но в целом идея была понятна еще до разбора кода...
Прикрепленные файлы:
32. PowerBoy 3377 07.06.24 12:54 Сейчас в теме
(20) Для структур тогда можно более универсально написать так:
Прикрепленные файлы:
33. artbear 1555 07.06.24 13:56 Сейчас в теме
(32) СтрСоединить из цикла убери )
SerVer1C; +1 Ответить
42. sultbec 10 07.06.24 16:13 Сейчас в теме
Как то раз у меня две одинаковые ТЧ не получилось добавить одну в другую методом заполнить значения свойств. Причину не нашел, переписал все поля в код.
46. Onwardv 65 08.06.24 07:47 Сейчас в теме
ЗаполнитьЗначенияСвойств() - Потенциальная проблема. Стараюсь не использовать в коде совсем.
Поди найди в коде, почему изменилось поведение объекта, который не меняли.
А, оказывается, в источнике появилось новое свойство, значение которого теперь затирает с таким же именем свойство в приемнике, которое раньше вело себя прилично и внезапно не менялось.
47. vadim1980 131 08.06.24 09:41 Сейчас в теме
Разве тема является каким-то откровением? Это всего лишь следствие того, что имена свойств в структурах (как и имена колонок таблицы значений) не хешируются (в отличие от соответствия). Но это никогда не было секретом, а вот предложить 1С сделать корректную работу процедуры ЗаполнитьЗначенияСвойств с соответствиями стоит
50. RustIG 1675 08.06.24 15:51 Сейчас в теме
(47)судя по обсуждению, получился неплохой мозговой штурм. ИИ стоит в сторонке, отдыхает
53. user1880116 09.06.24 22:19 Сейчас в теме
Если у вас в объектах по 500 свойств, то работа метода заполнения - это, пожалуй, меньшая из ваших проблем.
56. RocKeR_13 1338 10.06.24 13:58 Сейчас в теме
Трудно представить необходимость сценария, когда используются оба параметра СписокСвойств и ИсключаяСвойства одновременно.

Так они совместно и не применяются)

Описание:
Копирует значения свойств <Источника> в свойства <Приемника>. Сопоставление производится по именам свойств:
Если указаны копируемые свойства, то в заполнении участвуют только они, параметр <ИсключаяСвойства> игнорируется.
Если список свойств не задан (<СписокСвойств> имеет значение Неопределено) и задан параметр <ИсключаяСвойства>, то выполняется копирование значений всех свойств, исключая перечисленные в списке. Если свойство из списка исключаемых отсутствует в <Источнике> или <Приемнике>, то будет сгенерирована ошибка времени выполнения.
Evg-Lylyk; kalyaka; +2 Ответить
Оставьте свое сообщение