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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 19.01.2017, 13:18   #1  
kashperuk is offline
kashperuk
Senior SDE, Dynamics AX
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,350 / 2048 (77) +++++++++
Регистрация: 30.05.2004
Адрес: Копенгаген, Дания
Помогите найти: Сравнение производительности различных операндов при конкатенации строк
Я почему-то уверен, что когда-то писал небольшой проектик, который сравнивал производительность и память требуемую для выполнения конкатенации строк различными способами:

1)
s1 = 'string';
s1 += s2;
s1 += s3;

2)

s1 = 'string';
s1 = s1 + s2 + s3;

3)

s1 = 'string';
s1 = strFmt('%1%2%3', s1, s2, s3);


Может кто найдет или создаст заново?
Очень хочется посмотреть, что стоит использовать в АХ 7

Спасибо
Старый 19.01.2017, 13:56   #2  
fed is offline
fed
Moderator
Ex AND Project
Соотечественники
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
2,176 / 3995 (138) ++++++++++
Регистрация: 13.03.2002
Адрес: Hüfingen,DE
Учитывая ситуацию с продажами 7ки, данное сравнение представляется мне несколько бессмысленным. С равным успехом можно про FoxPro статью написать или про GNU Ada...
За это сообщение автора поблагодарили: Diman (1), ax_mct (0).
Старый 19.01.2017, 14:12   #3  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
2,916 / 1540 (57) ++++++++
Регистрация: 12.10.2004
Цитата:
Сообщение от kashperuk Посмотреть сообщение
Может кто найдет или создаст заново?
Очень хочется посмотреть, что стоит использовать в АХ 7
К сожалению нет под рукой.
Мне еще попадалось в коде когда много текста добавлялось к строке при помощи класса TextBuffer. Многократно добавлялись кусочки текста вызовом TextBuffer.AppendText(). Может включить в тест и такой способ ?

Последний раз редактировалось Logger; 19.01.2017 в 14:17.
Старый 19.01.2017, 14:40   #4  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
2,916 / 1540 (57) ++++++++
Регистрация: 12.10.2004
Мне кажется что быстрее всего будет способ 1
Но ведь это совсем копейки.
Чтобы что-то заметить надо блок кода с добавкой либо в цикле прокрутить либо завести десятки тысяч переменных которые и складывать.

Хотя любые копейки в определенных условиях могут привести к тормозам
Тормозит создание буфера.
Старый 19.01.2017, 15:19   #5  
kashperuk is offline
kashperuk
Senior SDE, Dynamics AX
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,350 / 2048 (77) +++++++++
Регистрация: 30.05.2004
Адрес: Копенгаген, Дания
Вот что получилось у меня, на основании конкатенации 5 строк 20 тыщ раз

6.3.
Название: 6.3.jpg
Просмотров: 568

Размер: 34.2 Кб

7.0
Название: 7.jpg
Просмотров: 552

Размер: 20.5 Кб


В 6.3 разница была в 250!! раз
В 7.0 разницы практически нет, с небольшим преимуществом операнда +
За это сообщение автора поблагодарили: mazzy (2), alex55 (1).
Старый 19.01.2017, 15:38   #6  
kashperuk is offline
kashperuk
Senior SDE, Dynamics AX
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,350 / 2048 (77) +++++++++
Регистрация: 30.05.2004
Адрес: Копенгаген, Дания
Если в 6.3 ранить в IL, то видим картину похожую на 7

Название: 6.3IL.png
Просмотров: 545

Размер: 59.1 Кб



Похоже что теперь += создает новую строку каждый раз.
За это сообщение автора поблагодарили: mazzy (2), Logger (10).
Старый 19.01.2017, 15:54   #7  
user_ax is offline
user_ax
Участник
Аватар для user_ax
 
558 / 33 (3) +++
Регистрация: 07.10.2012
Адрес: ZP
Полезные тесты, благодарю вас за них, Иван!
Старый 19.01.2017, 16:20   #8  
ax_mct is offline
ax_mct
Участник
Аватар для ax_mct
 
1,720 / 556 (22) +++++++
Регистрация: 10.10.2005
Адрес: PHP
В .NET на больших массивах самое эффективное использовать StringBuilder.
Вполне логично предположить что TextBuffer его полный аналог, а с компиляцией в IL возможно что по сути тот же IL код. То есть рекомендации ниже должны подходить и для TextBuffer.

Цитата:
Определённо используйте StringBuilder, когда вы конкатенируете строки в нетривиальном цикле, и особенно, когда вы не знаете (на момент компиляции), сколько именно итераций будет произведено. К примеру, чтение содержимого текстового файла путём считывания по одному символу внутри одной итерации в цикле, и конкатенация этого символа через оператор += предположительно «убьёт» ваше приложение в плане производительности.

Определённо используйте оператор +=, если вы можете указать все необходимые для конкатенации строки в одном утверждении. Если вам нужно конкатенировать массив строк, используйте явный вызов String.Concat, а если между этими строками нужен разделитель — используйте String.Join.
Статья 2013 года, но StringBuilder вполне себе живой и сейчас.
https://habrahabr.ru/post/166701/

P.S. Кстати интересно стоимость вызова и использования System.Text.StringBuilder вместо TextBuffer. Если это ничего не стоит когда в IL, то может лучше сразу .NET использовать?

Последний раз редактировалось ax_mct; 19.01.2017 в 16:27.
За это сообщение автора поблагодарили: mazzy (2), Logger (3), Товарищ ♂uatr (1).
Старый 19.01.2017, 16:27   #9  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
2,916 / 1540 (57) ++++++++
Регистрация: 12.10.2004
Цитата:
Сообщение от kashperuk Посмотреть сообщение
Если в 6.3 ранить в IL, то видим картину похожую на 7
Похоже что теперь += создает новую строку каждый раз.
Я думаю что с переходом на 7.0 ничего принципиально не изменилось. Там ведь только CIL. Поэтому и сравнивать надо 7.0 с IL под 6.3

А вот то что в 6.3 операция += работает медленнее под CIL чем p-code это очень неприятно. Может можно это пофиксить ? Наверняка можно создать более оптимальный код без создания новой строчки. Тем более что оператор += используется очень часто. Так глядишь в некоторых задачах p-code обгонит CIL.

Последний раз редактировалось Logger; 19.01.2017 в 16:33.
Старый 19.01.2017, 16:31   #10  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
2,916 / 1540 (57) ++++++++
Регистрация: 12.10.2004
Цитата:
Сообщение от ax_mct Посмотреть сообщение
Если это ничего не стоит когда в IL, то может лучше сразу .NET использовать?
Мне тоже кажется что так лучше было бы. Я вообще думал что TextBuffer не покажет таких цифр производительности. Думал он вообще реализован как не IL объект и будут накладные расходы на вызов между IL кодом и обычным неуправляемым кодом.
Старый 19.01.2017, 16:34   #11  
online
mazzy
Administrator
Аватар для mazzy
Most Valuable Professional
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
28,759 / 3627 (178) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
скорее дело не в IL, а в сборщике мусора.

поддерживаю про StringBuilder.
Старый 19.01.2017, 17:24   #12  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
2,916 / 1540 (57) ++++++++
Регистрация: 12.10.2004
Цитата:
Сообщение от mazzy Посмотреть сообщение
скорее дело не в IL, а в сборщике мусора.
поддерживаю про StringBuilder.
Возможно и так. Но если новая строчка не создавалась бы, как указал Иван, то все было бы ок. Негде сборщику было бы затормозить процесс.
Старый 19.01.2017, 18:04   #13  
Diman is offline
Diman
Участник
Сотрудники Microsoft Dynamics
 
166 / 35 (2) +++
Регистрация: 27.06.2003
Адрес: Москва
Цитата:
Сообщение от mazzy Посмотреть сообщение
скорее дело не в IL, а в сборщике мусора.

поддерживаю про StringBuilder.
Поддерживаю про сборщик мусора, а также добавлю, что причиной служит то, что строки в .Net есть константа, и каждая итерация сильно нагружает память и в итоге она быстро заканчивается, запускается GC, который память освобождает и упаковывает. А вот переход на StringBuilder оправдан при большом кол-ве итераций изменений. Если посмотреть исходники StringBuilder, то там используетеся не тип string a char[], и память выделяется небольшими порциями.
Я вот все хочу сравнить производительность разных коллекций,все руки не доходят.
__________________
Sapere aude
За это сообщение автора поблагодарили: Logger (3).
Старый 19.01.2017, 18:57   #14  
ax_mct is offline
ax_mct
Участник
Аватар для ax_mct
 
1,720 / 556 (22) +++++++
Регистрация: 10.10.2005
Адрес: PHP
Цитата:
Сообщение от Logger Посмотреть сообщение
Мне тоже кажется что так лучше было бы. Я вообще думал что TextBuffer не покажет таких цифр производительности. Думал он вообще реализован как не IL объект и будут накладные расходы на вызов между IL кодом и обычным неуправляемым кодом.
Кстати я абсолютно без понятия что там с TextBuffer случается в IL.
Это хороший пойнт насчет того что что-то может и не переводиться в IL. Ни в чем нельзя быть уверенным

Надо бы порыть насчет того что остается P-кодом при полной компиляции в CIL.
И понять в этом контексте стоимость использования .NET обьектов в X++ коде.

Последний раз редактировалось ax_mct; 19.01.2017 в 19:12.
Старый 19.01.2017, 19:16   #15  
ax_mct is offline
ax_mct
Участник
Аватар для ax_mct
 
1,720 / 556 (22) +++++++
Регистрация: 10.10.2005
Адрес: PHP
Из книги Inside Microsoft Dynamics AX 2012 R3 - Page 142.
NET interop
When running X++ code as CIL, all conversion and marshaling between the runtimes are avoided.

При этом же
Mastering Microsoft Dynamics AX 2012 R3 Programming - Page 402
The form-level logic still uses p-code...

То есть использование того же StringBuilder на клиентской стороне - возможно противопоказано так как возникнут накладные расходы. А вот в серверном коде с компиляцией в CIL - скорее всего показано.

Есть ли в 7ке "клиентский" X++ код - этого я не знаю
Старый 19.01.2017, 20:10   #16  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
2,916 / 1540 (57) ++++++++
Регистрация: 12.10.2004
Цитата:
Сообщение от Diman Посмотреть сообщение
Поддерживаю про сборщик мусора, а также добавлю, что причиной служит то, что строки в .Net есть константа, и каждая итерация сильно нагружает память и в итоге она быстро заканчивается, запускается GC, который память освобождает и упаковывает. ...
Да, вы правы.
Вряд ли поэтому удастся сделать быстрый += в CIL.
Получается, что как ни изворачивайся, а сложно теперь писать код одинаково быстрый и в p-code и в CIL. Ну если только TextBuffer или StringBuilder задействовать. Код по виду будет ближе к .Net а рекомендация BP использовать += вместо a=a+b теперь протухла.
Старый 19.01.2017, 20:35   #17  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
2,916 / 1540 (57) ++++++++
Регистрация: 12.10.2004
Цитата:
Сообщение от ax_mct Посмотреть сообщение
Кстати я абсолютно без понятия что там с TextBuffer случается в IL.
Это хороший пойнт насчет того что что-то может и не переводиться в IL. Ни в чем нельзя быть уверенным
Да вот же mfp явно обо всем рассказал применительно к 2012 R3 :
https://blogs.msdn.microsoft.com/mfp...-to-the-metal/

А в комментариях в ответ на претензию
Цитата:
The T-Shirt lies. There is no such thing as fast X++ code. Please make X++ a full blown CLR language ASAP. Otherwise we are all doomed (a partner).
раскрыл что случается с классами ядра:
Цитата:
Thanks for the feedback alibertism, Your comment nicely demonstrates the core problem this post is trying to qualify. In my examples above all X++ code is running in CLR – the problem is not with the language.

Even if X++ was a full blown CLR language you would still face these problems. What we need to fix is not "just" the language and compiler – but all the libraries you are using when writing X++ code. In AX 2012 the majority of these are written in C++. To avoid the interop overhead we need to replace these with CLR implementations. This includes everything under System Documentation in the AOT, i.e >100 built-in functions, > 500 classes and the entire data access stack.

Solving all this – and more is in the works for the next major release of AX – code named "Rainier".
Правда так и осталось тайной, как же обстоят дела с 7.0 Переписали они ядро на .Net или пока оставили как было.

Именно поэтому я и сомневался в том, что скорость вызова TextBuffer будет высокой. Думал что он остался на неуправляемом коде. (Хотя как показал Майкл в статье, скорость бывает разной и в нашем случае видимо скорости вызова неуправляемого кода достаточна для быстрой работы)
За это сообщение автора поблагодарили: ax_mct (10).
Старый 19.01.2017, 21:11   #18  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
2,916 / 1540 (57) ++++++++
Регистрация: 12.10.2004
Цитата:
Сообщение от kashperuk Посмотреть сообщение
Вот что получилось у меня, на основании конкатенации 5 строк 20 тыщ раз
Ваня, может выложишь джоб сюда ?
Привинтим еще StringBuilder и сравним.
Старый 19.01.2017, 23:32   #19  
skuull is offline
skuull
Участник
Most Valuable Professional
Лучший по профессии 2014
 
352 / 322 (11) ++++++
Регистрация: 08.03.2013
Адрес: ХЗ
Цитата:
Сообщение от Logger Посмотреть сообщение
Ваня, может выложишь джоб сюда ?
Привинтим еще StringBuilder и сравним.
Заодно привинтите и String.Format
Старый 20.01.2017, 11:38   #20  
kashperuk is offline
kashperuk
Senior SDE, Dynamics AX
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,350 / 2048 (77) +++++++++
Регистрация: 30.05.2004
Адрес: Копенгаген, Дания
Цитата:
Сообщение от Logger Посмотреть сообщение
Ваня, может выложишь джоб сюда ?
Привинтим еще StringBuilder и сравним.
X++:
class RunnableClass1
{        
    const int StringSite = 100000;

	public static Int64 PlusEquals()
    {
        System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();

        stopWatch.Restart();
        str s;
        for (int i = 1; i <= StringSite; i+=5)
        {
            s += int2Str(i);
            s += int2Str(i+1);
            s += int2Str(i+2);
            s += int2Str(i+3);
            s += int2Str(i+4);
        }

        var runtime = stopWatch.ElapsedMilliseconds;
        stopWatch.Stop();

        return runtime;
    }

    public static Int64 Plus()
    {
        System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();

        stopWatch.Restart();
        str s;
        for (int i = 1; i <= StringSite; i+=5)
        {
            s = s + int2Str(i) + int2Str(i+1) + int2Str(i+2) + int2Str(i+3) + int2Str(i+4);
        }

        var runtime = stopWatch.ElapsedMilliseconds;
        stopWatch.Stop();

        return runtime;
    }

    public static Int64 ThruStrFmt()
    {
        System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();

        stopWatch.Restart();
        str s;

        for (int i = 1; i <= StringSite; i+=5)
        {
            s = strFmt('%1%2%3%4%5%6', s, int2Str(i), int2Str(i+1), int2Str(i+2), int2Str(i+3), int2Str(i+4));
        }

        var runtime = stopWatch.ElapsedMilliseconds;
        stopWatch.Stop();

        return runtime;
    }

    public static Int64 ThruTextBuffer()
    {
        System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();

        stopWatch.Restart();

        TextBuffer tb = new TextBuffer();

        for (int i = 1; i <= StringSite; i+=5)
        {
            tb.appendText(int2Str(i));
            tb.appendText(int2Str(i+1));
            tb.appendText(int2Str(i+2));
            tb.appendText(int2Str(i+3));
            tb.appendText(int2Str(i+4));
        }

        tb.getText();

        var runtime = stopWatch.ElapsedMilliseconds;
        stopWatch.Stop();

        return runtime;
    }

    /// <summary>
    /// Runs the class with the specified arguments.
    /// </summary>
    /// <param name = "_args">The specified arguments.</param>
    public static void main(Args _args)
    {   
        Box::info("START");
        info(strFmt("+= took %1 ms", RunnableClass1::PlusEquals()));
        info(strFmt("+ took %1 ms", RunnableClass1::Plus()));
        info(strFmt("strFmt took %1 ms", RunnableClass1::ThruStrFmt()));
        info(strFmt("TextBuffer took %1 ms", RunnableClass1::ThruTextBuffer()));
        Box::info("DONE");
    }

}
За это сообщение автора поблагодарили: Logger (5), Товарищ ♂uatr (1).
Теги
.net, cil, p-code, string, бега сферических коней;, производительность

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Помогите найти справку разработчика! FrolovAndy DAX: Программирование 4 19.02.2013 21:40
Нечеткое сравнение строк Logger DAX: Программирование 7 14.10.2010 20:55
Помогите найти тему про if (recordBuffer) kashperuk DAX: Программирование 6 27.11.2008 11:25
Баг? Сравнение строк длиной более 32767 символов vallys DAX: База знаний и проекты 6 16.07.2008 12:18
Помогите найти доку vitart DAX: Администрирование 18 03.07.2003 16:10
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

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

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

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