Возращаясь к вопросу о прозводительности.

Обсуждение Stimulsoft Reports.NET
Леонид
Сообщения: 329
Зарегистрирован: 23 июл 2009, 09:53
Откуда: Moscow

Возращаясь к вопросу о прозводительности.

Сообщение Леонид »

Не пойму, что не так. Доделал один из отчётов. Да, он сложный, да, он использует DockStyle = Left, CanGrow и GrowToHeight во всех текстовых полях, т.к. это действительно необходимо.
Но в любом случае, запрос Oracle выполняется 2-4 сек., а отчёт рисуется 25-30 сек., и в нём при этом ровно 5 страниц. Это ненормально!

Отчёт с xml-файлом и схемой в приложении поста, чтобы можно было посмотреть. Но это нереально медленно, т.к. в старом проекте на Дельфе под FastReport'ом 3-м тоже самое рисуется несколько секунд. А когда я делают выборку по филиалам, то select выполяется около 16 секунд, а рисуется 16 минут, правда там и страниц намного больше, несколько сотен. Но это в любом случае неприемлемо. Т.к. это время на Intel Quad 2 Q6600 2.4 Ghz, а что же будет на Celeron'ах???

Я пробовал следовать всем Вашим рекомендациям, а именно, убрал у всех бендов и текстовых полей CanGrow и пр., убрал DockStyle (поставил None) и прочее, но не помогло.
Вложения
slow_report.zip
(36.85 КБ) 237 скачиваний
Леонид
Сообщения: 329
Зарегистрирован: 23 июл 2009, 09:53
Откуда: Moscow

Возращаясь к вопросу о прозводительности.

Сообщение Леонид »

Ребята, ну что, есть какие-нибудь идеи или соображения по поводу топика?
Ivan
Сообщения: 641
Зарегистрирован: 10 авг 2006, 05:40
Откуда: Stimulsoft Office

Возращаясь к вопросу о прозводительности.

Сообщение Ivan »

Здравствуйте.

С проблемой разобрались.
Пожалуйста у текстбокса Text49 установите свойство TextFormat в General и свойство HideZeros в false.
В этом поле у вас выводится только текст, а при обработке свойства HideZeros производится парсинг поля и получаются exceptions, которые и тормозят.
Также мы подправили код метода, чтобы в будущем такая ситуация не возникала.

Спасибо.
Леонид
Сообщения: 329
Зарегистрирован: 23 июл 2009, 09:53
Откуда: Moscow

Возращаясь к вопросу о прозводительности.

Сообщение Леонид »

Сделал всё, как Вы сказали, но увы, это не помогло. Отчёт (5 страниц) по прежнему рисуется 26 сек. Даже не знаю, что делать.
Ivan
Сообщения: 641
Зарегистрирован: 10 авг 2006, 05:40
Откуда: Stimulsoft Office

Возращаясь к вопросу о прозводительности.

Сообщение Ivan »

Здравствуйте.

Если причина низкой скорости работы связана с exceptions, вы можете посмотреть, в каком именно текстбоксе возникает ошибка.
Для этого запустите ваш отчет в дизайнере, и после того как он отобразится в превью, на закладке Messages в нижней части дизайнера будет список всех ошибок, которые возникли при построении отчета.

Спасибо.
Леонид
Сообщения: 329
Зарегистрирован: 23 июл 2009, 09:53
Откуда: Moscow

Возращаясь к вопросу о прозводительности.

Сообщение Леонид »

Ivan писал(а):Здравствуйте.

Если причина низкой скорости работы связана с exceptions, вы можете посмотреть, в каком именно текстбоксе возникает ошибка.
Для этого запустите ваш отчет в дизайнере, и после того как он отобразится в превью, на закладке Messages в нижней части дизайнера будет список всех ошибок, которые возникли при построении отчета.
Видимо не связано с ошибками, т.к. я запустил дизайнер после отрисовки отчёта, в Messages ничего не написано, т.е. ошибок нет, а скорость отрисовки всё тех же 5 страниц крайне низкая - 25-27 сек.

Вопрос, а у Вас рисуется за какое время? В любом случае проблема не решена.
Леонид
Сообщения: 329
Зарегистрирован: 23 июл 2009, 09:53
Откуда: Moscow

Возращаясь к вопросу о прозводительности.

Сообщение Леонид »

Сегодня "игрался" с отчётом в целях отыскать проблему производительности. Нашёл - это ячейки, в которых присутствуют конструкции вида: {IIF(Sum(DataBand1, qrMain.SALES_PLAN) <= 0, 0, Div(Totals.Sum(DataBand1, qrMain.AMOUNT_OUT) - Totals.Sum(DataBand1, qrMain.AMOUNT_RET), Totals.Sum(DataBand1, qrMain.SALES_PLAN)) * 100)}. То есть, вероятно, проблема возникает из-за медленного суммирования ячеек.

Итог экспериментов таков. Из ячеек в группах с заголовками (последние справа): "% плана продаж", "% плана оплат", "% отгр. к пред. году", "Обор." убрал весь интерпертируемый код вообще.
Результат - 5 страниц рисуется 3-4 сек., вместо 25-27 сек.

А те 63 страницы, которые рисовались 16 минут стали рисоваться за 10-11 сек. Это шок, ребята!!! :boom:

Иными словами, проблема оказалась даже не в HideZeroes, т.к. вместе с тем, что я убрал из всех этих четырёх ячеек код (во всех группах), но оставил во всех текстовых полях в Header'е HideZeroes у ВСЕХ полей - никаких exception отчёт не выдавал и время отрисовки сильно не изменилось.

Прошу Вас разобраться почему так медленно происходит суммирование в ячейках с группами.

Вложения
sum_trouble.png
sum_trouble.png (19 КБ) 3558 просмотров
Ivan
Сообщения: 641
Зарегистрирован: 10 авг 2006, 05:40
Откуда: Stimulsoft Office

Возращаясь к вопросу о прозводительности.

Сообщение Ivan »

Здравствуйте.

Разъясняем ситуацию.
Конструкция типа Totals.Sum(DataBand, Field) вычисляет сумму по указанному полю для всех записей датабэнда. При этом датабэнд прокручивается полностью для каждого вызова функции, что и создает приличные затраты времени.

В вашем случае используется одиннадцать групфутеров, на каждом по четыре текстбокса с выражениями, в каждом выражении по 3-4 вызова функции. Итого получается больше сотни вызовов функции, соответственно датабэнд прокручивается полностью больше сотни раз.

Но всё это легко оптимизируется. Изучив ваш отчет видим, что в каждом из указанных столбцов выражения одинаковые. Соответственно, мы выносим все вычисления сумм за пределы цикла. Для этого делаем следующее:
- создаем в словаре четыре переменных Func1, Func2, Func3, Func4 типа decimal.
- в событии BeforePrint компонента ReportTitle пишем следующий код для вычисления сумм:

Код: Выделить всё

Func1 = Div(Div(Totals.Sum(DataBand1, qrMain.DEBT_START) + Totals.Sum(DataBand1, qrMain.DEBT_END), 2) * Var_k, Totals.Sum(DataBand1, qrMain.AMOUNT_PAY));
Func2 = Div(Totals.Sum(DataBand1, qrMain.AMOUNT_OUT) - Totals.Sum(DataBand1, qrMain.AMOUNT_RET), Totals.Sum(DataBand1, qrMain.SALES_PLAN)) * 100;
Func3 = Div(Totals.Sum(DataBand1, qrMain.AMOUNT_PAY), Totals.Sum(DataBand1, qrMain.PAYMENTS_PLAN)) * 100;
Func4 = Div((Totals.Sum(DataBand1, qrMain.AMOUNT_OUT) - Totals.Sum(DataBand1, qrMain.AMOUNT_RET)), (Totals.Sum(DataBand1, qrMain.AMOUNT_PREV_OUT) - Totals.Sum(DataBand1, qrMain.AMOUNT_PREV_RET)) * 100);
- во всех местах вызова функций заменяем выражения на соответствующие переменные, например вместо кода

Код: Выделить всё

{IIF(Sum(DataBand1, qrMain.SALES_PLAN) <= 0, 0, Div(Totals.Sum(DataBand1, qrMain.AMOUNT_OUT) - Totals.Sum(DataBand1, qrMain.AMOUNT_RET), Totals.Sum(DataBand1, qrMain.SALES_PLAN)) * 100)}
пишем код

Код: Выделить всё

{IIF(Sum(DataBand1, qrMain.SALES_PLAN) <= 0, 0, Func4}
Сравниваем скорость построения отчета. На нашей тестовой машине первоначальный отчет строился 35 секунд, после оптимизации полученный отчет строится за 5 секунд.
Пример оптимизированного отчета прикреплен к топику.

Спасибо.
Вложения

[Расширение было запрещено, вложение больше недоступно.]

Леонид
Сообщения: 329
Зарегистрирован: 23 июл 2009, 09:53
Откуда: Moscow

Возращаясь к вопросу о прозводительности.

Сообщение Леонид »

Сделал всё, как Вы написали, всё заработало.

Теперь то, что рисовалось 16 минут рендериться за 33 секунды. :biggrin:

Ещё я изменил конструкцию вида {IIF(Sum(DataBand1, qrMain.SALES_PLAN) <= 0, 0, Func4} на {IIF(SaleSimpleSum <= 0, 0, Func4}, а SaleSimpleSum объявил как decimal и рассчитал (Sum(DataBand1, qrMain.SALES_PLAN)) в BeforePrint в ReportTitle. И так во всех четырёх полях всех GroupFooter'ов. В итоге, 16 минут (63 страницы) рисуются за 15 секунд, что впечатляет.

Правда после рендеринга сам вывод на экран длится порядка 15 секунд, т.е. в итоге суммарно получается 30-35 секунд. Это круто в любом случае. Вопрос по поводу вывода на экран отрендеренного отчёта в MDI это уже тема другой ветки.

Благодарю за помощь, Вы очень помогли, т.к. это один из самых важных отчётов. :feelgood:

P.S. Ещё вопрос. А нельзя ли сделать в будущих релизах анализ таких (одинаковых) кусков кода, где присутствуют суммирования по всему DataTable, чтобы не создавать кучу переменных, а сам генератор отчётов подставлял в нужные места вместо кода Sum(DataBand1, qrMain.SALES_PLAN) какую-нибудь уже посчитанную переменную?
Леонид
Сообщения: 329
Зарегистрирован: 23 июл 2009, 09:53
Откуда: Moscow

Возращаясь к вопросу о прозводительности.

Сообщение Леонид »

Сейчас внимательнее посмотрел на отчёт и понял, что считается-то неправильно, т.к. значение должно считаться для каждой группы, а оно получается считается один раз для всего DataTable, а потом значение просто подставляется для каждой группы. Это неверно.

Как же быть??? :oho:

Может быть на другое событие вешать пересчёт переменных Func1, Func2 и т.д.?
Вложения
groupfooter_sum.png
groupfooter_sum.png (11.42 КБ) 3536 просмотров
Ответить