gnucash master: [new-aging] speed up split->owner
Christopher Lam
clam at code.gnucash.org
Fri May 22 22:18:23 EDT 2020
Updated via https://github.com/Gnucash/gnucash/commit/d8aecf96 (commit)
from https://github.com/Gnucash/gnucash/commit/f2a13eca (commit)
commit d8aecf9695eb558277b967148b4eca26ca6a1f27
Author: Christopher Lam <christopher.lck at gmail.com>
Date: Sat May 23 05:50:08 2020 +0800
[new-aging] speed up split->owner
several speed ups
1. split->owner will now cache results, bypassing
gncOwnerGetOwnerFromLot and gncInvoiceGetInvoiceFromLot for repeated
calls to the same split.
2. previously each call to split->owner would allocate a new
gncOwner. now a new gncOwner is only allocated during a cache
miss. the list of gncOwners is maintained and is purged when
split->owner is called with #f. There is no need to maintain a tofree
list of gncOwners anymore.
3. instead of slow gncOwnerReturnGUID to test equality, use gncOwnerEqual
diff --git a/gnucash/report/reports/standard/new-aging.scm b/gnucash/report/reports/standard/new-aging.scm
index fe44c8330..f5a915692 100644
--- a/gnucash/report/reports/standard/new-aging.scm
+++ b/gnucash/report/reports/standard/new-aging.scm
@@ -170,20 +170,11 @@ exist but have no suitable transactions."))
(not (or (eqv? type TXN-TYPE-INVOICE)
(eqv? type TXN-TYPE-PAYMENT)))))
-(define (gnc-owner-equal? a b)
- (string=? (gncOwnerReturnGUID a) (gncOwnerReturnGUID b)))
-
(define (split-has-owner? split owner)
- (let* ((split-owner (split->owner split))
- (retval (gnc-owner-equal? split-owner owner)))
- (gncOwnerFree split-owner)
- retval))
+ (gncOwnerEqual (split->owner split) owner))
(define (split-owner-is-invalid? split)
- (let* ((owner (split->owner split))
- (retval (not (gncOwnerIsValid owner))))
- (gncOwnerFree owner)
- retval))
+ (not (gncOwnerIsValid (split->owner split))))
(define (split-from-acct? split acct)
(equal? acct (xaccSplitGetAccount split)))
@@ -192,17 +183,27 @@ exist but have no suitable transactions."))
(let-values (((list-yes list-no) (partition (lambda (elt) (fn elt cmp)) lst)))
(cons list-yes list-no)))
-;; simpler version of gnc:owner-from-split. must be gncOwnerFree after
-;; use! see split-has-owner? above...
-(define (split->owner split)
- (let* ((lot (xaccSplitGetLot split))
- (owner (gncOwnerNew))
- (use-lot-owner? (gncOwnerGetOwnerFromLot lot owner)))
- (unless use-lot-owner?
- (gncOwnerCopy (gncOwnerGetEndOwner
- (gncInvoiceGetOwner (gncInvoiceGetInvoiceFromLot lot)))
- owner))
- owner))
+;; optimized from gnc:owner-from-split. It will allocate and memoize
+;; (cache) the owners because gncOwnerGetOwnerFromLot is slow. after
+;; use, it must be called with #f to free the owners.
+(define split->owner
+ (let ((ht (make-hash-table)))
+ (lambda (split)
+ (cond
+ ((not split)
+ (hash-for-each (lambda (k v) (gncOwnerFree v)) ht)
+ (hash-clear! ht))
+ ((hashv-ref ht (string-hash (gncSplitGetGUID split))) => identity)
+ (else
+ (let ((lot (xaccSplitGetLot split))
+ (owner (gncOwnerNew)))
+ (unless (gncOwnerGetOwnerFromLot lot owner)
+ (gncOwnerCopy (gncOwnerGetEndOwner
+ (gncInvoiceGetOwner
+ (gncInvoiceGetInvoiceFromLot lot)))
+ owner))
+ (hashv-set! ht (string-hash (gncSplitGetGUID split)) owner)
+ owner))))))
(define (aging-renderer report-obj receivable)
(define options (gnc:report-options report-obj))
@@ -267,8 +268,7 @@ exist but have no suitable transactions."))
(let loop ((accounts accounts)
(splits splits)
(accounts-and-owners '())
- (invalid-splits '())
- (tofree '()))
+ (invalid-splits '()))
(cond
((null? accounts)
@@ -345,7 +345,7 @@ exist but have no suitable transactions."))
acc-totals)))))
(reverse accounts-and-owners))
- (for-each gncOwnerFree tofree)
+ (split->owner #f) ;free the gncOwners
(gnc:html-document-add-object! document table)
(unless (null? invalid-splits)
@@ -371,7 +371,6 @@ exist but have no suitable transactions."))
(let lp ((acc-splits (car splits-acc-others))
(acc-totals (make-list (1+ num-buckets) 0))
(invalid-splits invalid-splits)
- (tofree tofree)
(owners-and-aging '()))
(match acc-splits
@@ -382,8 +381,7 @@ exist but have no suitable transactions."))
accounts-and-owners
(cons (list account owners-and-aging acc-totals)
accounts-and-owners))
- invalid-splits
- tofree))
+ invalid-splits))
;; txn type != TXN_TYPE_INVOICE or TXN_TYPE_PAYMENT.
(((? split-is-not-business? this) . rest)
@@ -392,7 +390,6 @@ exist but have no suitable transactions."))
acc-totals
(cons (list (format #f (_ "Invalid Txn Type ~a") type) this)
invalid-splits)
- tofree
owners-and-aging)))
;; some payment splits may have no owner in this
@@ -402,7 +399,6 @@ exist but have no suitable transactions."))
(lp rest
acc-totals
(cons (list (_ "Payment has no owner") this) invalid-splits)
- tofree
owners-and-aging))
((this . _)
@@ -416,7 +412,6 @@ exist but have no suitable transactions."))
(lp other-owner-splits
(map + acc-totals (reverse (cons aging-total aging)))
invalid-splits
- (cons owner tofree)
(if (or show-zeros (any (negate zero?) aging))
(cons (list owner aging aging-total) owners-and-aging)
owners-and-aging)))))))))))))
Summary of changes:
gnucash/report/reports/standard/new-aging.scm | 57 ++++++++++++---------------
1 file changed, 26 insertions(+), 31 deletions(-)
More information about the gnucash-changes
mailing list