Andrew,
Sorry for taking a long time getting back. I finally went deeper into the net
worth barchart report (which is also used to create the income/expenses chart
report), and found that changing the report-utilities.scm's
gnc:get-comm-balance-at-date function to NOT use qof resulted in a tremendous
increase in speed. Now, I'm not sure that is an acceptable solution --
particularly when we are trying to transition to be closer to SQL.
Nevertheless, I've attached the patch (report-utilities.patch) for this part.
However, for cash flow report, I got that to run in less than a second too
(processing all of my transactions dating back to 2006 -- something like 5000
transactions). The problem there was that the line:
(gnc:report-percent-done (* 85 (/ work-done
splits-to-do))))
Was being run thousands of times. That is a quite expensive call just to
update the progress -- particularly if you have thousands of splits to do.
What I did was change it to only update the progress every time it changes by
1%. The progress still seems to move quite smoothly (in the short time that
it runs -- it runs really fast.
So...there are two patches attached.
Let me know if it works, and I'm curious what others have to say about the
idea of swapping that report-utilities method to not use qof. It is also
possible that I'm missing something since for different commodities, maybe
the qof method is more accurate. I doubt that is the case, though.
By the way, I've subscribed to the gnucash-devel digest.
-Tim
Index: src/report/standard-reports/cash-flow.scm
===================================================================
--- src/report/standard-reports/cash-flow.scm (revision 17795)
+++ src/report/standard-reports/cash-flow.scm (working copy)
@@ -152,23 +152,28 @@
(define (same-account? a1 a2)
(string=? (gncAccountGetGUID a1) (gncAccountGetGUID a2)))
- (define (same-split? s1 s2)
- (string=? (gncSplitGetGUID s1) (gncSplitGetGUID s2)))
+ (define accounts-hashed
+ (let ((accounts-hashed (make-hash-table 100)))
+ (for-each
+ (lambda (account)
+ (hash-set! accounts-hashed (gncAccountGetGUID account) #t))
+ accounts)
+ accounts-hashed))
- (define account-in-list?
- (lambda (account accounts)
- (cond
- ((null? accounts) #f)
- ((same-account? (car accounts) account) #t)
- (else (account-in-list? account (cdr accounts))))))
+ (define seen-splits-map (make-hash-table 100))
+
+ (define account-in-accounts-list?
+ (lambda (account)
+ (hash-ref accounts-hashed (gncAccountGetGUID account))))
- (define split-in-list?
- (lambda (split splits)
- (cond
- ((null? splits) #f)
- ((same-split? (car splits) split) #t)
- (else (split-in-list? split (cdr splits))))))
+ (define split-seen?
+ (lambda (split)
+ (hash-ref seen-splits-map (gncSplitGetGUID split))))
+ (define add-split-seen
+ (lambda (split)
+ (hash-set! seen-splits-map (gncSplitGetGUID split) #t)))
+
(define account-in-alist
(lambda (account alist)
(cond
@@ -204,7 +209,7 @@
(let ((sub-accounts (gnc:acccounts-get-all-subaccounts accounts)))
(for-each
(lambda (sub-account)
- (if (not (account-in-list? sub-account accounts))
+ (if (not (account-in-accounts-list? sub-account))
(set! accounts (append accounts sub-accounts))))
sub-accounts)))
@@ -226,6 +231,10 @@
(money-diff-collector (gnc:make-commodity-collector))
(splits-to-do (gnc:accounts-count-splits accounts))
+ ; Only update the progress by increasing it by 1% every time that sufficient
+ ; number of splits are done to warrant incrementing it.
+ (progress-update-interval
+ (if (> splits-to-do 85) (quotient splits-to-do 85) 1))
(seen-split-list '())
(time-exchange-fn #f)
(commodity-list #f))
@@ -252,7 +261,8 @@
(for-each
(lambda (split)
(set! work-done (+ 1 work-done))
- (gnc:report-percent-done (* 85 (/ work-done splits-to-do)))
+ (if (equal? 0 (modulo work-done progress-update-interval))
+ (gnc:report-percent-done (* 85 (/ work-done splits-to-do))))
(let ((parent (xaccSplitGetParent split)))
(if (and (gnc:timepair-le (gnc-transaction-get-date-posted parent) to-date-tp)
(gnc:timepair-ge (gnc-transaction-get-date-posted parent) from-date-tp))
@@ -278,10 +288,10 @@
;(gnc:debug (xaccAccountGetName s-account))
(if (and ;; make sure we don't have
(not (null? s-account)) ;; any dangling splits
- (not (account-in-list? s-account accounts)))
- (if (not (split-in-list? s seen-split-list))
+ (not (account-in-accounts-list? s-account)))
+ (if (not (split-seen? s))
(begin
- (set! seen-split-list (cons s seen-split-list))
+ (add-split-seen s)
(if (gnc-numeric-negative-p s-value)
(let ((pair (account-in-alist s-account money-in-alist)))
;(gnc:debug "in:" (gnc-commodity-get-printname s-commodity)
@@ -304,6 +314,7 @@
(money-in-collector 'add report-currency s-report-value)
(s-account-in-collector 'add report-currency s-report-value))
)
+ ; Else s-value positive
(let ((pair (account-in-alist s-account money-out-alist)))
;(gnc:debug "out:" (gnc-commodity-get-printname s-commodity)
; (gnc-numeric-to-double s-amount)
Index: src/report/report-system/report-utilities.scm
===================================================================
--- src/report/report-system/report-utilities.scm (revision 17795)
+++ src/report/report-system/report-utilities.scm (working copy)
@@ -275,12 +275,22 @@
(gnc:warn
"gnc:numeric-collector called with wrong argument: "
amount)))
+ ((minus) (if (gnc:gnc-numeric? amount)
+ (set! value (gnc-numeric-add (gnc-numeric-neg amount) value
+ GNC-DENOM-AUTO GNC-DENOM-LCD))
+ (gnc:warn
+ "gnc:numeric-collector called with wrong argument: "
+ amount)))
((total) value)
(else (gnc:warn "bad gnc:numeric-collector action: " action))))))
;; Replace all 'action function calls by the normal functions below.
(define (gnc:numeric-collector-add collector amount)
(collector 'add amount))
+
+(define (gnc:numeric-collector-minus collector amount)
+ (collector 'minus amount))
+
(define (gnc:numeric-collector-total collector)
(collector 'total #f))
@@ -458,9 +468,7 @@
;; values rather than double values.
(define (gnc:account-get-comm-balance-at-date account
date include-children?)
- (let ((balance-collector (gnc:make-commodity-collector))
- (query (qof-query-create-for-splits))
- (splits #f))
+ (let ((balance-collector (gnc:make-commodity-collector)))
(if include-children?
(for-each
@@ -470,24 +478,9 @@
(lambda (child)
(gnc:account-get-comm-balance-at-date child date #f))
account)))
-
- (qof-query-set-book query (gnc-get-current-book))
- (xaccQueryAddSingleAccountMatch query account QOF-QUERY-AND)
- (xaccQueryAddDateMatchTS query #f date #t date QOF-QUERY-AND)
- (qof-query-set-sort-order query
- (list SPLIT-TRANS TRANS-DATE-POSTED)
- (list QUERY-DEFAULT-SORT)
- '())
- (qof-query-set-sort-increasing query #t #t #t)
- (qof-query-set-max-results query 1)
-
- (set! splits (qof-query-run query))
- (qof-query-destroy query)
-
- (if (and splits (not (null? splits)))
- (gnc-commodity-collector-add balance-collector
+ (gnc-commodity-collector-add balance-collector
(xaccAccountGetCommodity account)
- (xaccSplitGetBalance (car splits))))
+ (xaccAccountGetBalanceAsOfDate account (gnc:timepair->secs date)))
balance-collector))
;; Calculate the increase in the balance of the account in terms of
_______________________________________________
gnucash-devel mailing list
[email protected]
https://lists.gnucash.org/mailman/listinfo/gnucash-devel