Что не так с методом ЗаполнитьЗначенияСвойств

18.07.24

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

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

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

 

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

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

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

 

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

 

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

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

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

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

 

Вывод

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

 

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

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

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

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

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

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

 

p.s.

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

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

См. также

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

Обсудим поиск и разбор причин длительных серверных вызовов CALL, SCALL.

24.06.2024    5609    ivanov660    12    

56

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

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

13.03.2024    5370    spyke    28    

49

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

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

13.03.2024    7940    vasilev2015    20    

42

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

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

2 стартмани

15.02.2024    12909    259    ZAOSTG    84    

115

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

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

1 стартмани

24.01.2024    6036    glassman    19    

42

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

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

09.01.2024    15757    doom2good    49    

71

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

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

20.11.2023    14139    ivanov660    7    

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


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

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

- без всяких вызовов доп. процедур ЗаполнитьЗначенияСвойств()
30. ixijixi 1939 07.06.24 12:26 Сейчас в теме
57. kalyaka 1112 11.06.24 10:51 Сейчас в теме
(21) Использовать исключения нужно в случаях когда действительно что-то пошло не так. Если же использовать их для проверки в нормальном исполнении кода, то при отслеживании ошибок (логирование) или при отладке будет возникать множество исключений, которые не являются исключительными случаями :)
58. RustIG 1830 11.06.24 12:03 Сейчас в теме
4. vadim1980 125 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 1830 07.06.24 10:52 Сейчас в теме
(4) до этой мысли надо еще дойти... она не на поверхности .... понять ее можно только если попробовать изучить код, и попробовать оптимизировать свое...
Прикрепленные файлы:
27. RustIG 1830 07.06.24 11:47 Сейчас в теме
(4) в значении может быть пустой массив,
но имя свойства может не совпадать - например в формате джейсон

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

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

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

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

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

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

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

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

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

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

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

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

но в целом идея была понятна еще до разбора кода...
Прикрепленные файлы:
32. PowerBoy 3420 07.06.24 12:54 Сейчас в теме
(20) Для структур тогда можно более универсально написать так:
Прикрепленные файлы:
33. artbear 1565 07.06.24 13:56 Сейчас в теме
(32) СтрСоединить из цикла убери )
tormozit; SerVer1C; +2 Ответить
62. sashocq 193 15.07.24 09:31 Сейчас в теме
(33) А меня вот раздражает, что для некоторых платформенных функций где, казалось бы, напрашивается коллекция в параметрах (типа ЗаполнитьЗначенияСвойств(Приемник, Источник, ИменаСвойств)) платформа требует именно строку и не принимает массив :-/
Ну зачем мне делать конкатенацию строк, чтобы потом эта функция её парсила!?
alk; Evg-Lylyk; +2 Ответить
42. sultbec 10 07.06.24 16:13 Сейчас в теме
Как то раз у меня две одинаковые ТЧ не получилось добавить одну в другую методом заполнить значения свойств. Причину не нашел, переписал все поля в код.
46. Onwardv 66 08.06.24 07:47 Сейчас в теме
ЗаполнитьЗначенияСвойств() - Потенциальная проблема. Стараюсь не использовать в коде совсем.
Поди найди в коде, почему изменилось поведение объекта, который не меняли.
А, оказывается, в источнике появилось новое свойство, значение которого теперь затирает с таким же именем свойство в приемнике, которое раньше вело себя прилично и внезапно не менялось.
milanse; RustIG; +2 Ответить
47. vadim1980 125 08.06.24 09:41 Сейчас в теме
Разве тема является каким-то откровением? Это всего лишь следствие того, что имена свойств в структурах (как и имена колонок таблицы значений) не хешируются (в отличие от соответствия). Но это никогда не было секретом, а вот предложить 1С сделать корректную работу процедуры ЗаполнитьЗначенияСвойств с соответствиями стоит
50. RustIG 1830 08.06.24 15:51 Сейчас в теме
(47)судя по обсуждению, получился неплохой мозговой штурм. ИИ стоит в сторонке, отдыхает
53. user1880116 09.06.24 22:19 Сейчас в теме
Если у вас в объектах по 500 свойств, то работа метода заполнения - это, пожалуй, меньшая из ваших проблем.
mikukrnet; sashocq; ZOMI; +3 1 Ответить
56. RocKeR_13 1376 10.06.24 13:58 Сейчас в теме
Трудно представить необходимость сценария, когда используются оба параметра СписокСвойств и ИсключаяСвойства одновременно.

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

Описание:
Копирует значения свойств <Источника> в свойства <Приемника>. Сопоставление производится по именам свойств:
Если указаны копируемые свойства, то в заполнении участвуют только они, параметр <ИсключаяСвойства> игнорируется.
Если список свойств не задан (<СписокСвойств> имеет значение Неопределено) и задан параметр <ИсключаяСвойства>, то выполняется копирование значений всех свойств, исключая перечисленные в списке. Если свойство из списка исключаемых отсутствует в <Источнике> или <Приемнике>, то будет сгенерирована ошибка времени выполнения.
alk; 0x00; Evg-Lylyk; kalyaka; +4 Ответить
59. nafa 661 16.06.24 23:51 Сейчас в теме
На эту тему на партнерском форуме 2 месяца назад был выложен подробный тест (номер темы 2182505, ссылки нет, т.к. нужна авторизация). Основная тема не то, что где-то медленнее, а то что медленнее обхода свойств в цикле программным кодом. И не только, когда "большой источник -> маленький приемник".
Здесь результаты, кому нужен сам тест - обращайтесь к Вашему партнеру. Фирма 1С знает о проблеме.
Прикрепленные файлы:
8.3.25.1185.xlsx
brr; artbear; +2 Ответить
60. artbear 1565 18.06.24 10:45 Сейчас в теме
(59) отличный анализ, большое спасибо!
61. пользователь 25.06.24 20:23
Сообщение было скрыто модератором.
...
Оставьте свое сообщение