Отсутствие оптимизации
Создатели FR, хочу обратить ваше внимание на полное отсутствие оптимизации по скорости "fast reporta".
Неоправданно долго выполняется отчет с 3 группировками. При этом количество строк всего около 1600.
Проанализировав код, нашел самую медленную функцию - TfrxReport.DoGetValue;
На обработку этой функции тратится основная часть времени, причем время, занимаемое доступом к данным - мизерно.
Даже беглая оптимизация дала ощутимый прирост. Пока просто не было времени копаться глубоко.
Что было изменено:
FSysVariables - тип изменен на TStringList, что дало возможность сделать Sorted и пользоваться быстрым Find, вместо IndexOf.
if FSysVariables.Find(Expr, i) then
Далее изменен код класса TfrxVariables - добавлена функциональность сортировки и бинарного поиска по переменным. Соответственно код так же принял вид:
if FVariables.Find(Expr, i) then
if frxGlobalVariables.Find(Expr, i) Then
И это только беглый взгляд, без глубокого изучения движка. Операция сравнения строк через IndexOf - полный бред. Вы там название своего отчета дали исходя из маркетинговых задач? Потому как к оптимизации по скорости ваш движок явно не имеет никакого отношения.
Комментарии
Это я ещё молчу про такой код
case i of
0: Value := FEngine.StartDate; { Date }
1: Value := FEngine.StartTime; { Time }
2: Value := FPreviewPages.GetLogicalPageNo; { Page }
Про константы и привязку их к объектам, а не индексам походу не слышали.
В самом конце DoGetValue есть блок, который должен сработать если никакие другие блоки функции не распознали выражение. Там тоже есть строка поиска по выражению. Что самое интересное, в самом коде конструктора TfsScript.Create написано
FItems.Sorted := True;
Но тем не менее поиск описан в функции TfsScript.FindLocal
i := FItems.IndexOf(Name);
И все это происходит в обертке DOGETVALUE которая вызывается по каждому чиху.... Ну копнем что там в CALC происходит )
Кстати, занете чем отличается категория(группа) переменной от самой переменной? Ни за что не угадаете.
Не буду томить - наличием пробела впереди ))))
Вот так мы ищем категорию AnsiCompareText(Items[i].Name, ' ' + ACategory) = 0 )) Просто лол.
Ну и соответственно все элементы в коллекции ниже этого элемента входят в категорию.
А где же заканчивается категория? - да там где встретится элемент с ещё одним пробелом )).
Я что то тихо офигеваю от этого шедевра программистской мысли.
Здравствуйте,
К сожалению, в продукте могут встречаться проблемные места,
баги, "странный код" и прочие вещи свойственные для больших продуктов
которые пишут и дорабатывают разные люди.
Чтобы определить в каких случаях данные места являются
проблемными желательно направить демонстрационный пример, воспроизводящий
данное поведение. По описанию не понятно на сколько сильный прирост может дать
введение сортировки для списка из 10 элементов. Кроме этого, данный код будет выполнятся
только в случае, если не найдены поля данных. В большинстве отчетов большую
часть выражений занимают именно поля данных и до выполнения кода, который вы
привели дело не дойдет.
Для этого нам и нужен пример демонстрирующий ваш случай.
Вы пишете:
"И это только беглый взгляд, без глубокого изучения движка.
Операция сравнения строк через IndexOf - полный бред."
Но в замене IndexOf на Find для TStringList нет никакого смысла,
если вы уже установили Sorted := True; - IndexOf будет вызывать Find.
Будем благодарны если вы сможете направить нам тестовый пример,
чтобы мы могли указать нашим программистам на их ошибки.
Спасибо.