|
![]() |
#1 |
Участник
|
Цитата:
Цитата:
Вы в принципе не совсем понимаете в чем затыки по производительности в этом месте (может в ваших сценариях их просто нет). У нас есть большое количество кусочков проводок ГК по налогам, образованные каждой строкой заказа на продажу. Дальше упрощая система бежит по этим кусочкам и прибавляет их к первой проводке, получается как бы нарастающий итог. В моем случае все эти проводки сворачиваются в итоге всего в 2 проводки по налогам, вроде на продажи и возвраты (точно не разбирался, вторая с минусом). Кроме суммирования самих полей проводки еще объединяются ссылки на taxTrans, это recid. Поэтому типичная ситуация, когда к проводке, у которой уже 7000 ссылок прибавляется одна по которой 1 ссылка. Система это делает следующим образом: X++: #define.IgnoreDuplicates(true) LedgerPostingOneToManyCollection ret = LedgerPostingOneToManyCollection::construct( Types::Int64, // use this instead of RecId for perf Types::Enum, #IgnoreDuplicates); this.addCollections(ret, _first); this.addCollections(ret, _second); X++: this.addCollections(_first, _second);
return _first; Далее встает вопрос, как переделать так, чтобы оставить такой подход - два элемента скопировать в первый, но сделать это быстро. Нужно что-то типа _first.Clone(). Но такого метода ни у Map, ни у Set нету. pack/unpack не решают задачу. В качестве решения предлагается изменить структуру хранения так, чтобы дублирование выполнялось командой container1 = container2, это работает быстро. А для того, чтобы изменить интерфейс работы с классом модифицировать taxTransactionRelationshipCollection метод, чтобы он выдавал данные в привичном виде, собирая из контейнеров результат. Сценарий работы с этим классом такой. 1) Вначале экземпляры создаются по каждой микропроводке по строке заказа методом initFromLedgerVoucherTransObject 2) Все многократно мерджится, используется метод merge, вызывается много раз 3) По просуммированным проводкам вызывается 1 раз метод taxTransactionRelationshipCollection по каждой проводке. У меня проводки 2, соответственно вызывается он по налогам 2 раза. Поэтому оптимизируем вызовы merge. По поводу идеи с таблицей. Будет тормозить еще больше я думаю, хотя не пробовал. В CIL точно больше. Вместо 4 контейнеров можно было сделать один, который бы хранил и RecId и enum. Но он был бы в 2 раза больше. У меня в примере например значение енума Offset всегда, соответственно только 1 полный контейнер. Можно еще как-то по другому делать, например я думал использовать структуры .Net. Или, возможно если оставить эти пробеги в циклах по Map, но просто убрать Set, то этого будет достаточно (заменить Map recId -> Set, на более простую структуру данных). Но меня просто устраивает этот вариант, я его замерил, если знаете как лучше, то сделайте, только проверьте результат по времени работы. Последний раз редактировалось Masel; 08.02.2022 в 21:35. |
|
|
За это сообщение автора поблагодарили: mazzy (10). |
![]() |
#2 |
Участник
|
Цитата:
![]() Цитата:
![]() Цитата:
по-русски, их можно называть "движения". Цитата:
Цитата:
Цитата:
авторы россикского класса вот тоже побоялись. Цитата:
![]() по поводу pack/unpack создал отдельную тему List/Set/Map/Array: deep clone через pack/create в классических Аксаптах Цитата:
Сообщение от Masel
![]() В качестве решения предлагается изменить структуру хранения так, чтобы дублирование выполнялось командой container1 = container2, это работает быстро. А для того, чтобы изменить интерфейс работы с классом модифицировать taxTransactionRelationshipCollection метод, чтобы он выдавал данные в привичном виде, собирая из контейнеров результат.
![]() и огромное вам спаибо за предложенное решение. но решить можно еще лучше. прежде всего, потому что у вас нет организационных ограничений. В Майкрософте каждый объект АОТ приписан к определенной команде. И разработчик другой команды не имеет права менять чужой объект без согласования. Поэтому разработчики Московской команды часто вынуждены делать странные решения сбоку, вместо того, чтобы просто расширить функционал другого объекта АОТ. У вас таких ограничений нет - вы можете менять любой класс, любую таблицу, любой объект АОТ. Очень многие странности в Аксапте можно решить просто перенеся функционал в другой класс. Вот такая вот организация труда у них там в Майкрософте. Подумайте - а что если бы метод merge существовал прямо в классе с идиотским назвнием LedgerPostingOneToManyCollection? Цитата:
![]() Подумайте не только об этом месте. Ведь по сути, данное место просто окрашивает движения разными enum-признаками. Рано или поздно эти признаки надо будет как-то связать с исходными движениями. Поскольку сейчас признаки хранятся в коллекции, то надо будет снова делать цикл по одному и искать исходные движения по одному. А можно было бы сделать select-join со временной таблицей ![]() Похоже, что беда в том, что данный код класса с идиотским названием делал человек, который не знает ни аксапту, ни СУБД. Причем, этот код прошел ревью. Т.е. либо это был team lead, который может впендюрить код без ревью, либо вся команда была уровня "не знаю ни аксапту, ни СУБД". И я даже не знаю какой вариант хуже... Цитата:
![]() Цитата:
между p-code и .net слишком дорогой маршаллинг. Цитата:
![]() Цитата:
Огромное спасибо за предложенное решение. Последний раз редактировалось mazzy; 09.02.2022 в 00:10. |
|
![]() |
#3 |
Участник
|
Это не дублирование, вы просто получите вторую ссылку на тот же экземпляр таблицы.
Я если честно не понимаю просто эту идею, что это даст. |
|
|
За это сообщение автора поблагодарили: S.Kuskov (5). |
![]() |
#4 |
Участник
|
Цитата:
![]() доступ к приватной переменной map и возможность напрямую использовать методы этого map, вместо публичного интерфейса. В общем, я понял. Спасибо, что предложили решение, которое реально увеличивает производительность. |
|
![]() |
#5 |
Участник
|
Да нет, вроде не ошибаюсь. Такой джоб у меня выдает 2 записи и в 2012 и в d365. Два курсора по одной таблице. Вставляете в любой, получаете записи в обоих курсорах.
X++: TmpFrmVirtual tmp1, tmp2; tmp1.clear(); tmp1.ItemId = 'item1'; tmp1.insert(); tmp2.setTmpData(tmp1); tmp2.clear(); tmp2.ItemId = 'item2'; tmp2.insert(); select count(RecId) from tmp1; info(strFmt("%1", tmp1.recId)); |
|
|
За это сообщение автора поблагодарили: mazzy (10). |
Теги |
faq, tax, налоги, оптимизация, производительность |
|
![]() |
||||
Тема | Ответов | |||
Вызов метода базового класса | 15 | |||
jerry-dynamics: tax codes | 0 | |||
Вызов класса из другого класса | 9 | |||
передача курсора в два класса | 3 | |||
Запустить метод класса | 2 |
|