Report Engine Speed

Christian Stimming stimming at tuhh.de
Fri Feb 19 15:06:28 EST 2010


Am Freitag, 19. Februar 2010 schrieb Jeff Kletsky:
> I found the "optimizing reports" thread from October 2007, but not a lot
> since then. Has there been any significant understanding gained since
> then about what is so slow on what should be a relatively
> straightforward task? Was it ever narrowed down to bad algorithms in the
> reporting, or something else?

I've created some of the oldest reports in there. I have never done real 
profiling of the time spent in the report generation - but what I can recall 
is this: All the "number collecting calculations" in all of the reports are 
horribly inefficient, or more academic: coded in the wrong level of 
abstraction. That is, the calculation of the balance difference between start 
and end of a reporting period is usually done by obtaining the list of splits 
(transactions) in question from within the scheme code, then summing over all 
of those splits. Also, the intermediate results are not cached at all, even 
during one report generation run, so they are calculated over and over again 
when the report is generated. This turns your O(n) problem into an O(n^2) 
problem.

As I said, the problem is the level of abstaction: Most of the report code 
uses too low-level accessor functions into the txn data, like "querying for a 
list of splits", then "accumulating the sum over these splits". It would go a 
long way to choose more higher-level query functions here, like "querying for 
a balance difference for splits obeying criterion xy". The "engine" and/or the 
"libqof" part of gnucash in theory should provide sufficient such higher-level 
functions (implemented in C); it's unclear if they actually do.

However, the problem doesn't stop here: Even if those few higher-level query 
functions were being used from the schemed side of it, it would turn out their 
implementation is probably highly inefficient as well, like O(n^2) instead of 
something less than that. But as long as nobody really used these function for 
time-critical applications (or cared about the time), nobody had any incentive 
to work on the optimization here and its functional correctness was enough as 
a goal.

The optimization of the report generation obviously needs work on several 
levels. I would recommend the following:

- Use profiling to identify the 10% part of the report generation that 
consumes most of the time. Using the time-of-day is probably good enough to 
identify this section. I would guess the problem is in the calculation of each 
single amount that is displayed in the report, and most probably the amount 
calculation is programmed in scheme for the most part and using the "engine" 
query functions only on a very low level.

- Identify some higher-level query function that can fulfil the amount 
generation task, but refactors its calculation away from the reporting code. 
This higher-level query function can first be a scheme function. Once the 
functional correctness is somewhat verified, you can try to port this to C 
and/or to replace this by use of the libqof query object...

Good luck!

Regards,

Christian


More information about the gnucash-devel mailing list