AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 29.11.2011, 16:01   #1  
Vadik is offline
Vadik
Модератор
Аватар для Vadik
Лучший по профессии 2017
Лучший по профессии 2015
 
3,631 / 1849 (69) ++++++++
Регистрация: 18.11.2002
Адрес: гражданин Москвы
Цитата:
Сообщение от someOne Посмотреть сообщение
Мммда... С 2005 года - могли бы десять раз поправить уже. Мне казалось что люди из команды разработчиков Аксапта читают этот форум... Жаль. Может теперь заметят ?
единственный способ это исправить - зарегистрировать соответствующий запрос в поддержке
__________________
-ТСЯ или -ТЬСЯ ?
За это сообщение автора поблагодарили: Logger (1).
Старый 29.11.2011, 17:31   #2  
Zabr is offline
Zabr
Участник
Axapta Retail User
 
1,201 / 345 (14) ++++++
Регистрация: 26.06.2002
Адрес: Москва
Вставлю свои 5 копеек про таблицу TaxTrans без индекса и крайне тормозной расчет "Налога 1099" : Загрузка строк Purchase order
За это сообщение автора поблагодарили: Logger (3), someOne (3).
Старый 29.11.2011, 15:50   #3  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,882 / 3148 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от Wamr Посмотреть сообщение
Гыгы.
Я изобрел велосипед

А вы, случаем, свою находку тогда в 2005-м не регали в MS ?
Старый 29.11.2011, 15:15   #4  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
вы не горячитесь оптимизировать.

tmptaxWorkTrans содержит не только рассчитанные системой данные, но и введенные пользователем суммы с коррекциями (коррекции копеек).

к сожалению, этот момент очень запутан и плохо продуман в Аксапте.
Изменяя функционал tmptaxWorkTrans можно загубить возможность коррекции копеек в налогах.
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: Logger (3).
Старый 29.11.2011, 15:34   #5  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,882 / 3148 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от mazzy Посмотреть сообщение
вы не горячитесь оптимизировать.
...
Изменяя функционал tmptaxWorkTrans можно загубить возможность коррекции копеек в налогах.
Спасибо за предупреждение.
Вроде бы не должно сломаться. Я проверил тот код, который изменял. Работает идентично. Я ведь не меняю сам расчет. Указанный код работает в самом конце обработки, после расчета всех налогов и учета всех коррекций - он просто прописывает суммы в строки документов. Я поправил не расчет, а именно перенос итоговых сумм налогов в строки.

Последний раз редактировалось Logger; 29.11.2011 в 15:37.
Старый 29.11.2011, 15:41   #6  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,882 / 3148 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Походил по ссылкам, наткнулся на
http://forum.mazzy.ru/index.php?showtopic=1790

Розничные продажи - как раз получают описанные проблемы, потому что там строк в документах дофига (счет идет на тысячи), и проблема не только в индексах и БД, а в кривом коде, который зря грузит сервер приложений.

Последний раз редактировалось Logger; 29.11.2011 в 15:52.
Старый 03.02.2022, 22:10   #7  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,882 / 3148 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
а, так вот пример
Оптимизация класса Tax

ну можно что-то аналогичное сделать.

Вообще код сложный. Стремно что-то менять.
Может разноску в ГК разбить на куски - сгруппировать по N строк. Уйдут нелинейные эффекты.
Я думаю так в итоге проще будет и безопаснее. Меньше вероятности что-то сломать. Обновления проще поднять.

Про нелинейность:
Как линейное время превращается в Windows в O(n²)
Старый 03.02.2022, 22:43   #8  
EVGL is offline
EVGL
Banned
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
 
4,445 / 3001 (0) ++++++++++
Регистрация: 09.07.2002
Адрес: Parndorf, AT
Бессмысленное занятие. В D365 все уходит в microservice с закрытым кодом, а для индийского GST они в Москве все давно перекроили на решение систем линейных уравнений, кажется.

https://docs.microsoft.com/en-us/dyn...ion-service-ga

П.с. говорит автор. Моя работа
Думаю, вы правы. На этапе merge я, кажется, проверял соответствие ряда характеристик LedgerVoucherTransObject, как то: счет ГК, аналитики, тип проводки, сторона дебет/кредит. Наверное, из них можно было собрать hash key. Тогда (2002) такого pattern не было.

Последний раз редактировалось EVGL; 03.02.2022 в 22:51.
За это сообщение автора поблагодарили: Logger (3).
Старый 03.02.2022, 23:00   #9  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,882 / 3148 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от EVGL Посмотреть сообщение
Бессмысленное занятие.
Бессмысленное, если в ближайшем будущем планировать переход на 365ю.
Старый 08.02.2022, 09:07   #10  
Masel is offline
Masel
Участник
 
39 / 537 (18) +++++++
Регистрация: 19.09.2007
Оптимизировал все таки корреспонденцию. Тестовый пример заказ на 2770 строк. В CIL выигрыш в абсолютном выражении не большой: время сократилось с 1,5 минут до 18 секунд. А в p-code c 20 минут до 1 мин 35сек. Медленно работало объединение списков ссылок на проводки TaxTrans при суммировании проводок ГК в корреспонденции. Это делалось поэлементно, переделал на контейнеры.
Вложения
Тип файла: xpo Class_LedgerBondMergeablesGeneralJour_RU.xpo (14.6 Кб, 63 просмотров)
За это сообщение автора поблагодарили: mazzy (10), Logger (10).
Старый 08.02.2022, 13:30   #11  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,882 / 3148 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от Masel Посмотреть сообщение
Оптимизировал все таки корреспонденцию...
А можете выложить некастомизированную, стандартную версию класса для вашей версии приложения ?
Думаю это поможет тем кто захочет портировать на 2009-ю версию.

Плюс с R3 тоже есть незначительные отличия.
Старый 08.02.2022, 13:59   #12  
Masel is offline
Masel
Участник
 
39 / 537 (18) +++++++
Регистрация: 19.09.2007
Исходная с R2 во вложении.
Вложения
Тип файла: xpo Class_LedgerBondMergeablesGeneralJour_RU.xpo (9.3 Кб, 61 просмотров)
Старый 08.02.2022, 19:29   #13  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Masel Посмотреть сообщение
Оптимизировал все таки корреспонденцию. Тестовый пример заказ на 2770 строк. В CIL выигрыш в абсолютном выражении не большой: время сократилось с 1,5 минут до 18 секунд. А в p-code c 20 минут до 1 мин 35сек. Медленно работало объединение списков ссылок на проводки TaxTrans при суммировании проводок ГК в корреспонденции. Это делалось поэлементно, переделал на контейнеры.
1.
Спасибо!

2.
Для длинных коллекций в Аксапте вместо контейнеров лучше использовать List.
Контейнер только в 2012 и только в CIL реализован на базе System.Array
в младших версиях и в p-code контейнер реализован на базе строки.

3.
смотрите что сейчас у вас получается.
3.1. вы получаете коллекцию taxTransactionRelationshipCollection
3.2. эта коллекция по сути дела является Map(Key:RecId, Value:Set{Enum})
3.3. вы перекладываете этот map в 4 ваших контейнера (кстати, enum'ов больше, чем 4)
3.4. а в методе taxTransactionRelationshipCollection() вы перекладываете ваши контейнеры в новую коллекцию taxTransactionRelationshipCollection.

вопрос: а зачем вообще нужна эта перекладка из мапы в контейнер и наоборот?
добавьте метод merge в класс LedgerPostingOneToManyCollection и пользуйтесь доступом непосредственно к методам мапы и множества - insert, lookup, in, add. Получится и проще для понимания и быстрее.

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

Если уж решились оптимизировать - используйте временную таблицу.
тогда сложение двух коллекций будет реализовано оператором insert_recordset.

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

------------------------------------
Скорее всего, классы LedgerPostingOneToManyCollection и LedgerBondMergeablesGeneralJour_RU реализовывали разные люди.
И русские скорее всего не могли вставиться в LedgerPostingOneToManyCollection по огранизационным причинам.
Но вы то можете.

Обратите внимание насколько код в 2012 НЕ использует возможности таблиц и возможности СУБД. Бегут как чёрт от ладана. Всякую херню в памяти делают, лишь бы не таблицы.
Но вы то не такие. Правда?
------------------------------------

и... фу, какие душные названия в ax2012.
Миниатюры
Нажмите на изображение для увеличения
Название: ax01.PNG
Просмотров: 63
Размер:	109.9 Кб
ID:	13310   Нажмите на изображение для увеличения
Название: ax02.PNG
Просмотров: 69
Размер:	96.4 Кб
ID:	13311  

Изображения
 
__________________
полезное на axForum, github, vk, coub.

Последний раз редактировалось mazzy; 08.02.2022 в 19:41.
Старый 08.02.2022, 20:58   #14  
Masel is offline
Masel
Участник
 
39 / 537 (18) +++++++
Регистрация: 19.09.2007
Цитата:
Сообщение от mazzy Посмотреть сообщение
Для длинных коллекций в Аксапте вместо контейнеров лучше использовать List.
Контейнер только в 2012 и только в CIL реализован на базе System.Array
в младших версиях и в p-code контейнер реализован на базе строки.
List здесь не подходит, потому что его нельзя быстро клонировать. pack/unpack вызывает ту же многократную вставку. Я это проверял.

Цитата:
Сообщение от mazzy Посмотреть сообщение
3.3. вы перекладываете этот map в 4 ваших контейнера (кстати, enum'ов больше, чем 4)
На R2 в енуме 4 значения. У вас их больше либо потому, что R3, либо потому, что добавлено на USR слое.


Вы в принципе не совсем понимаете в чем затыки по производительности в этом месте (может в ваших сценариях их просто нет). У нас есть большое количество кусочков проводок ГК по налогам, образованные каждой строкой заказа на продажу. Дальше упрощая система бежит по этим кусочкам и прибавляет их к первой проводке, получается как бы нарастающий итог. В моем случае все эти проводки сворачиваются в итоге всего в 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);
То есть она создает абсолютно новую структуру данных и переваливает потом все элементы в цикле по одному. В пером параметре _first куча элементов, во втором немного. Здесь идеально бы работало просто

X++:
this.addCollections(_first, _second);
return _first;
Но тогда вы измените taxTransactionRelationshipCollection на которую ссылаются из других мест. Там есть целый класс, который еще раз ссылается на все эти свойства и хранит их ID. В целом по коду кажется что после суммирования старый экземпляр LedgerBondMergeablesGeneralJour_RU уже использоваться не будет, но я так делать не решился.

Далее встает вопрос, как переделать так, чтобы оставить такой подход - два элемента скопировать в первый, но сделать это быстро. Нужно что-то типа _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).
Старый 08.02.2022, 23:53   #15  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от Masel Посмотреть сообщение
На R2 в енуме 4 значения. У вас их больше либо потому, что R3, либо потому, что добавлено на USR слое.
R3

Цитата:
Сообщение от Masel Посмотреть сообщение
Вы в принципе не совсем понимаете в чем затыки по производительности в этом месте


Цитата:
Сообщение от Masel Посмотреть сообщение
У нас есть большое количество кусочков проводок ГК по налогам, образованные каждой строкой заказа на продажу.
угу. "кусочки" в английской аксапте называются movements.
по-русски, их можно называть "движения".

Цитата:
Сообщение от Masel Посмотреть сообщение
То есть она создает абсолютно новую структуру данных и переваливает потом все элементы в цикле по одному. В пером параметре _first куча элементов, во втором немного.
Угу.

Цитата:
Сообщение от Masel Посмотреть сообщение
Здесь идеально бы работало просто

X++:
this.addCollections(_first, _second);
return _first;
Но тогда вы измените taxTransactionRelationshipCollection на которую ссылаются из других мест.
Угу-угу.

Цитата:
Сообщение от Masel Посмотреть сообщение
В целом по коду кажется что после суммирования старый экземпляр LedgerBondMergeablesGeneralJour_RU уже использоваться не будет, но я так делать не решился.
угу-угу-угу.
авторы россикского класса вот тоже побоялись.

Цитата:
Сообщение от Masel Посмотреть сообщение
Далее встает вопрос, как переделать так, чтобы оставить такой подход - два элемента скопировать в первый, но сделать это быстро.

Нужно что-то типа _first.Clone(). Но такого метода ни у Map, ни у Set нету. pack/unpack не решают задачу.
tmpTable.setTmpData(fromTmpTable);



по поводу pack/unpack создал отдельную тему
List/Set/Map/Array: deep clone через pack/create в классических Аксаптах


Цитата:
Сообщение от Masel Посмотреть сообщение
В качестве решения предлагается изменить структуру хранения так, чтобы дублирование выполнялось командой container1 = container2, это работает быстро. А для того, чтобы изменить интерфейс работы с классом модифицировать taxTransactionRelationshipCollection метод, чтобы он выдавал данные в привичном виде, собирая из контейнеров результат.
да, это я понял.
и огромное вам спаибо за предложенное решение.

но решить можно еще лучше.

прежде всего, потому что у вас нет организационных ограничений. В Майкрософте каждый объект АОТ приписан к определенной команде. И разработчик другой команды не имеет права менять чужой объект без согласования. Поэтому разработчики Московской команды часто вынуждены делать странные решения сбоку, вместо того, чтобы просто расширить функционал другого объекта АОТ.

У вас таких ограничений нет - вы можете менять любой класс, любую таблицу, любой объект АОТ.
Очень многие странности в Аксапте можно решить просто перенеся функционал в другой класс.
Вот такая вот организация труда у них там в Майкрософте.

Подумайте - а что если бы метод merge существовал прямо в классе с идиотским назвнием LedgerPostingOneToManyCollection?

Цитата:
Сообщение от Masel Посмотреть сообщение
По поводу идеи с таблицей. Будет тормозить еще больше я думаю, хотя не пробовал. В CIL точно больше.
Подумайте
Подумайте не только об этом месте.

Ведь по сути, данное место просто окрашивает движения разными enum-признаками. Рано или поздно эти признаки надо будет как-то связать с исходными движениями.

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

Похоже, что беда в том, что данный код класса с идиотским названием делал человек, который не знает ни аксапту, ни СУБД. Причем, этот код прошел ревью. Т.е. либо это был team lead, который может впендюрить код без ревью, либо вся команда была уровня "не знаю ни аксапту, ни СУБД". И я даже не знаю какой вариант хуже...

Цитата:
Сообщение от Masel Посмотреть сообщение
Вместо 4 контейнеров можно было сделать один, который бы хранил и RecId и enum.
а можно map как в исходном классе с идиотским названием LedgerPostingOneToManyCollection

Цитата:
Сообщение от Masel Посмотреть сообщение
Можно еще как-то по другому делать, например я думал использовать структуры .Net.
это только для CIL.
между p-code и .net слишком дорогой маршаллинг.

Цитата:
Сообщение от Masel Посмотреть сообщение
Или, возможно если оставить эти пробеги в циклах по Map, но просто убрать Set, то этого будет достаточно (заменить Map recId -> Set, на более простую структуру данных).
угу. таблицу, например

Цитата:
Сообщение от Masel Посмотреть сообщение
Но меня просто устраивает этот вариант, я его замерил, если знаете как лучше, то сделайте, только проверьте результат по времени работы.
Если устраивает, то нет вопросов, конечно.

Огромное спасибо за предложенное решение.
__________________
полезное на axForum, github, vk, coub.

Последний раз редактировалось mazzy; 09.02.2022 в 00:10.
Старый 09.02.2022, 11:51   #16  
Masel is offline
Masel
Участник
 
39 / 537 (18) +++++++
Регистрация: 19.09.2007
Цитата:
Сообщение от mazzy Посмотреть сообщение
tmpTable.setTmpData(fromTmpTable);
Это не дублирование, вы просто получите вторую ссылку на тот же экземпляр таблицы.

Цитата:
Сообщение от mazzy Посмотреть сообщение
Подумайте - а что если бы метод merge существовал прямо в классе с идиотским назвнием LedgerPostingOneToManyCollection
Я если честно не понимаю просто эту идею, что это даст.
За это сообщение автора поблагодарили: S.Kuskov (5).
Старый 09.02.2022, 21:31   #17  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,657 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Common.setTmpData() создает новый экземпляр при передаче между клиентом и сервером. А если на одной стороне, то проще вставку сделать. Таблица же...


X++:
    TmpFrmVirtual tmp1, tmp2;
    
    tmp1.clear();
    tmp1.ItemId = 'item1';
    tmp1.insert();
    
    
    insert_recordset tmp2 (ItemId) 
        select ItemId from tmp1;

    tmp2.clear();
    tmp2.ItemId = 'item2';
    tmp2.insert();    


    select count(RecId) from tmp1;
    info(strFmt("tmp1 = %1", tmp1.recId));    

    select count(RecId) from tmp2;
    info(strFmt("tmp2 = %1", tmp2.recId));
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
За это сообщение автора поблагодарили: mazzy (10), DarkSpirit22 (1).
Теги
faq, tax, налоги, оптимизация, производительность

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Вызов метода базового класса Eldar9x DAX: Программирование 15 22.03.2008 19:10
jerry-dynamics: tax codes Blog bot DAX Blogs 0 16.06.2007 11:20
Вызов класса из другого класса Protey DAX: Программирование 9 26.02.2007 11:01
передача курсора в два класса kitty DAX: Программирование 3 09.08.2006 13:21
Запустить метод класса loka DAX: Программирование 2 13.03.2006 15:40

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 15:15.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.