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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 03.02.2022, 20:32   #1  
Masel is offline
Masel
Участник
 
39 / 537 (18) +++++++
Регистрация: 19.09.2007
Я тут в очередной раз занимался оптимизацией разноски розничных продаж и наткнулся еще на пару возможных улучшений.
1. Метод writeTaxAmount_W, который тут ранее оптимизировали вызывает в цикле метод CustVendInvoiceTrans.initFromTaxWorkTrans_RU(). Там выполняется неиндексируемый запрос к злосчастной темповухе TmpTaxWorkTrans. Единственный селективный фильтр там это номер лота InventTransId, но индекса по нему нету. Получается примерно такая трассировка
Нажмите на изображение для увеличения
Название: trace.jpg
Просмотров: 34
Размер:	109.0 Кб
ID:	13298
В общем нужно добавить индекс и плюс пришлось еще поменять немного код на поиске.
X++:
    if (SysCountryRegionCode::isLegalEntityInCountryRegion([#isoRU]))
    {
        //+ sergey.m 03.02.2022 FRE_20421639_001
        if (!_sourceRecId)
        {
            select taxWorkTrans index hint InventTransIdx
                where taxWorkTrans.SourceTableId == _sourceTableId       &&
                      taxWorkTrans.InventTransId == _inventTransId       &&
                      taxWorkTrans.TaxDirection  != TaxDirection::UseTax &&
                      taxWorkTrans.TaxOrigin     != TaxOrigin::TaxReversed;
        }
        else
        {
        //- sergey.m 03.02.2022 FRE_20421639_001
            select taxWorkTrans
                where taxWorkTrans.SourceTableId  == _sourceTableId             &&
                      ((_sourceRecId &&
                        taxWorkTrans.SourceRecId == _sourceRecId) ||
                       (! _sourceRecId &&
                        taxWorkTrans.InventTransId == _inventTransId))          &&
                      taxWorkTrans.TaxDirection       != TaxDirection::UseTax   &&
                      taxWorkTrans.TaxOrigin          != TaxOrigin::TaxReversed;
        }
Хинт на inMemory срабатывает. Без него у меня улучшений не было. Не знаю как тут аксапта выбирает какой индекс использовать, думаю хватает первый попавшийся по совпадению поля.

2. В классе Tax метод lineTaxAmount. В начале метода проверяется что в таблице есть записи немного экзотическим методом, считая их количество. Я поменял так, хотя можно было наверное вообще убрать запрос, меня пока и так устраивает.
X++:
    if (this.taxParameters().TaxSpecifyLine)
    {
    if (this.taxParameters().TaxSpecifyLine)
    {
        //+ sergey.m 03.02.2022 FRE_20421639_001
        //select count(RecId) from taxWorkTrans;
        select firstOnly RecId from taxWorkTrans;
        //- sergey.m 03.02.2022 FRE_20421639_001

        if (taxWorkTrans.RecId > 0 && !this.useSubLedgerJournalLines())
        {
            // Posting out of TmpTaxWorkTrans
Еще тормозит российская корреспонденция фин. проводок. Так не хочется глубоко погружаться в это. Никто не правил случаем? Я там кое-что правил, но вот этот кошмар остался. Без единового вызова субд.

Нажмите на изображение для увеличения
Название: trace1.jpg
Просмотров: 34
Размер:	107.8 Кб
ID:	13299
За это сообщение автора поблагодарили: trud (10), Logger (5).
Старый 03.02.2022, 21:03   #2  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,882 / 3148 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от Masel Посмотреть сообщение
Еще тормозит российская корреспонденция фин. проводок. Так не хочется глубоко погружаться в это. Никто не правил случаем? Я там кое-что правил, но вот этот кошмар остался. Без единового вызова субд.
Для какой версии ?
Я для 2009-й кое что правил - некие частные случаи с накладными расходами.
Там проблема из-за нелинейной зависимости от числа строк при разноске. (где то на форуме была тема)

Где возможно -
1. отключали корреспонденцию.
2. для больших документов (более 300 строк) вместо одной накладной делали кучку накладных по 40 строк. тем самым линеаризовали зависимость времени разноски от числа строк. - у нас были компании для управленческого учета где число накладных было неважно, главное итоговые показатели. Вот там такое было применимо.
Старый 03.02.2022, 21:22   #3  
Masel is offline
Masel
Участник
 
39 / 537 (18) +++++++
Регистрация: 19.09.2007
Цитата:
Сообщение от Logger Посмотреть сообщение
Для какой версии ?
2012 R2. Подозреваю что существенно не поменялось с 2009. В CIL то оно еще сносно работает, но все равно бы хотелось оптимизировать. Там явно неэффективные эти пробеги по map бесконечные.
Старый 03.02.2022, 22:12   #4  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,882 / 3148 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от Masel Посмотреть сообщение
В CIL то оно еще сносно работает, но все равно бы хотелось оптимизировать. Там явно неэффективные эти пробеги по map бесконечные.
В CIL быстрее за счет двух вещей
1. JIT (ну и в целом CIL шустрее чем p-code)
2. Асинхронный сборщик мусора.
Старый 03.02.2022, 22:42   #5  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,882 / 3148 (112) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от Masel Посмотреть сообщение
Там явно неэффективные эти пробеги по map бесконечные.
Да!
Да!

Это прямо бросается в глаза. Перебор всего мапа со сравнением со значением на каждом шаге. Очень неэффективный поиск значения сделан. Видимо автор закладывался на то что раз операция в памяти то все будет быстро. Как бы не так! Там слишком много элементов в мапе на большом числе строк документа получается.
Поскольку там не голый мап а класс обертка, то у меня была идея сделать в нем некий вспомогательный второй мап, который будет индексом к основному мапу и позволит не перебирать все элементы первого мапа для поиска значений. Но руки не дошли.
Старый 04.02.2022, 08:51   #6  
SRF is offline
SRF
Участник
MCBMSS
Axapta Retail User
 
365 / 542 (19) +++++++
Регистрация: 08.08.2007
Записей в блоге: 1
Цитата:
Сообщение от Masel Посмотреть сообщение
Я тут в очередной раз занимался оптимизацией разноски розничных продаж и наткнулся еще на пару возможных улучшений.
1. Метод writeTaxAmount_W, который тут ранее оптимизировали вызывает в цикле метод CustVendInvoiceTrans.initFromTaxWorkTrans_RU(). Там выполняется неиндексируемый запрос к злосчастной темповухе TmpTaxWorkTrans. Единственный селективный фильтр там это номер лота InventTransId, но индекса по нему нету. Получается примерно такая трассировка
На уровне идеи (не факт конечно, что будет быстрее) - можно же вообще убрать запрос в этом месте к темповой табличке для RU функциональности(наверное и в общем случае можно, но будет чуть сложнее), я может конечно что то забываю или не учитываю, но идея такая :

- на одну строку накладной одна запись в TmpTaxWorkTrans для RU, связь по номеру лота (по логике можно хранить и несколько записей, но кажется в этом случае особого профита по сравнению с индексом не будет)

- получается можно до цикла по строкам получить map - ключ inventTransId, значение запись TmpTaxWorkTrans(в методе который собственно и формирует всю TmpTaxWorkTrans, т.е. дополнительных проходов не потребуется).

- в цикле из мапа получать запись TmpTaxWorkTrans и ее отдавать в метод уже (в самом методе и чуть ниже придется поменять код, так что обрабатывать запись, а не курсор, но это не кажется сложным).
__________________
Sergey Nefedov
Старый 04.02.2022, 11:28   #7  
Masel is offline
Masel
Участник
 
39 / 537 (18) +++++++
Регистрация: 19.09.2007
Цитата:
Сообщение от SRF Посмотреть сообщение
На уровне идеи (не факт конечно, что будет быстрее) - можно же вообще убрать запрос в этом месте к темповой табличке для RU функциональности(наверное и в общем случае можно, но будет чуть сложнее), я может конечно что то забываю или не учитываю, но идея такая :

- на одну строку накладной одна запись в TmpTaxWorkTrans для RU, связь по номеру лота (по логике можно хранить и несколько записей, но кажется в этом случае особого профита по сравнению с индексом не будет)

- получается можно до цикла по строкам получить map - ключ inventTransId, значение запись TmpTaxWorkTrans(в методе который собственно и формирует всю TmpTaxWorkTrans, т.е. дополнительных проходов не потребуется).

- в цикле из мапа получать запись TmpTaxWorkTrans и ее отдавать в метод уже (в самом методе и чуть ниже придется поменять код, так что обрабатывать запись, а не курсор, но это не кажется сложным).
Не факт что там одна запись, индексов уникальных нет и выбирется курсор без firstonly, внутри они его фетчат, делают next TmpTaxWorkTrans. Поэтому придется делать map InventTransId -> Set(Types::record) и потом внутри логику менять, чтобы он заместо фетча бегал по Set. Это можно сделать, но в моем сценарии нет смысла, т.к. индексированный поиск отрабатывает меньше милисекунды.
Старый 27.05.2022, 11:05   #8  
DarkSpirit22 is offline
DarkSpirit22
Участник
Аватар для DarkSpirit22
 
13 / 76 (3) ++++
Регистрация: 07.11.2013
Адрес: СПб
Цитата:
Сообщение от Masel Посмотреть сообщение
Я тут в очередной раз занимался оптимизацией разноски розничных продаж и наткнулся еще на пару возможных улучшений.

<...>

2. В классе Tax метод lineTaxAmount. В начале метода проверяется что в таблице есть записи немного экзотическим методом, считая их количество. Я поменял так, хотя можно было наверное вообще убрать запрос, меня пока и так устраивает.
X++:
    if (this.taxParameters().TaxSpecifyLine)
    {
    if (this.taxParameters().TaxSpecifyLine)
    {
        //+ sergey.m 03.02.2022 FRE_20421639_001
        //select count(RecId) from taxWorkTrans;
        select firstOnly RecId from taxWorkTrans;
        //- sergey.m 03.02.2022 FRE_20421639_001

        if (taxWorkTrans.RecId > 0 && !this.useSubLedgerJournalLines())
        {
            // Posting out of TmpTaxWorkTrans
Нашел еще одно место, где наличие записей через select count делается:
\Classes\TaxPost\saveAndPost

X++:
public void saveAndPost(LedgerPostingController _ledgerPostingController, SelectableDataArea _companyToPost = curext())
{
    this.initLedgerPosting(_ledgerPostingController);

    //+ Abramov_ 27.05.2022 TSK0000280_08
    //select count(RecId) from taxWorkTrans;
    select firstonly RecId from taxWorkTrans;
    //- Abramov_ 27.05.2022 TSK0000280_08

    if (taxWorkTrans.RecId > 0 && !this.useSubLedgerJournalLines())
Еще маленькая оптимизация:
При создании строк накладной покупки в PurchInvoiceJournalCreate.createJournalLine() поле vendInvoiceTrans.LineAmount рассчитывается без учета экземпляра класса Tax, который был рассчитан на предыдущем шаге (в PurchInvoiceJournalCreate.initTotals()).

Т.е. в initTotals мы формируем кэш проводок TaxUncommitted, и, если не передать Tax, мы делаем лишние запросы к тому же TaxUncommitted.

X++:
    //+ Abramov_ 27.05.2022 TSK0000280_08
    //vendInvoiceTrans.LineAmount     = vendInvoiceInfoLine.lineAmountExclTax(vendInvoiceJour.InvoiceDate);
    vendInvoiceTrans.LineAmount     = vendInvoiceInfoLine.lineAmountExclTax(vendInvoiceJour.InvoiceDate, this.parmTax());    
    //- Abramov_ 27.05.2022 TSK0000280_08
Еще мы решили в таблицах TmpTaxWorkTrans и TaxUncommitted установить св-во SaveContents = NO полям, которые относятся к функциональности других стран (напр. _IN, _BR). Их оказалось довольно много, TmpTaxWorkTrans "похудел" на треть.

Еще мы провели эксперимент с переводом TmpTaxWorkTrans в TempDB (и обновлением существующей функциональности соответственно). Пришли к выводу, что без существенного рефакторинга кода от версии TmpTaxWorkTrans в TempDB толку нет, т.к. производительность расчета налогов упала ровно в два раза.

Последний раз редактировалось DarkSpirit22; 27.05.2022 в 11:29.
За это сообщение автора поблагодарили: Logger (5).
Теги
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, время: 07:54.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.