Performance improvements to gnucash

Bill Carlson wwc@wwcnet.nu
Sat, 29 Jul 2000 13:35:12 -0400


Hi,

	I've been starting to make some performance
improvments to gnucash.  As background, I have a .xac
file of about 1.5MB (10 years of transactions) so
there are some things where it is quite slow (like
loading and exiting).  The following patches are based 
on the current CVS tree but apply equally well to the 
1.4 series.  The changes to Account.c improve the
the load time from 28 seconds to 8 seconds (300Mhz Pentium)
by speeding up inserts (10% effect) and honoring the 
ACC_DEFER_REBALANCE flag (300% effect). The changes to Group.c 
premark all in the group being open so the rebalances
are not done each time a split is deleted.  When combined
with the ACC_DEFER_REBALANCE flag change in Account.c,
exit times improve from 11 seconds to 2 seconds.

	As these are the first changes I've made, I didn't
really know how to sumbit them.  Since they are short, I
just included the diff -c below from the current cvs tree.
Is the the best way to do this? 

	Also, I plan to continue working on the performance
of gnucash.  I haven't had any luck getting profiling to work
(configure --enable-profile).  It generates a gmon.out file
which only contains a very small percentage of the total execution
time.  I suspect this may have something to do with guile.
Anyone have any luck with profiling?

		Cheers,

		Bill Carlson
		wwc@backboneaudio.com

Index: src/engine/Account.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Account.c,v
retrieving revision 1.81
diff -c -r1.81 Account.c
*** src/engine/Account.c        2000/07/08 12:35:01     1.81
--- src/engine/Account.c        2000/07/29 17:33:52
***************
*** 441,454 ****
       
       /* Find the insertion point */
       /* to get realy fancy, could use binary search. */
!      for(i = 0; i < (acc->numSplits - 1);) {
!        if(xaccSplitDateOrder(&(oldsplits[i]), &split) > 0) {
!          break;
!        } else {
!          acc->splits[i] = oldsplits[i];
         }
!        i++;  /* Don't put this in the loop guard!  It'll go too far. */
!      }
       /* Insertion point is now i */
     
       PINFO ("Insertion position is: %d\n", i);
--- 441,465 ----
       
       /* Find the insertion point */
       /* to get realy fancy, could use binary search. */
!      /* but to get just a little fancy, see if it's after the last one */
!      if ((acc->numSplits > 1)
!        && xaccSplitDateOrder(&split, &(oldsplits[acc->numSplits - 2])) > 0)
!        {
!        i = acc->numSplits - 1;
!        memcpy (&acc->splits[0], &oldsplits[0],
!                (acc->numSplits-1) * sizeof (oldsplits[0]));
         }
!      else
!        {
!        for(i = 0; i < (acc->numSplits - 1);) {
!          if(xaccSplitDateOrder(&(oldsplits[i]), &split) > 0) {
!            break;
!          } else {
!            acc->splits[i] = oldsplits[i];
!          }
!          i++;  /* Don't put this in the loop guard!  It'll go too far. */
!        }
!        }
       /* Insertion point is now i */
     
       PINFO ("Insertion position is: %d\n", i);
***************
*** 568,573 ****
--- 579,588 ----
    Split *split, *last_split = NULL;
  
    if( NULL == acc ) return;
+   /*
+    * if we are defering, defer!
+    */
+   if (acc->open & ACC_DEFER_REBALANCE) return;
    if (0x0 == (ACC_INVALID_BALN & acc->changed)) return;
    acc->changed &= ~ACC_INVALID_BALN;
  
Index: src/engine/Group.c
===================================================================
RCS file: /home/cvs/cvsroot/gnucash/src/engine/Group.c,v
retrieving revision 1.49
diff -c -r1.49 Group.c
*** src/engine/Group.c  2000/06/19 20:22:53     1.49
--- src/engine/Group.c  2000/07/29 17:33:53
***************
*** 78,83 ****
--- 78,98 ----
    return grp;
  }
  
+ void
+ xaccAccountGroupBeginEdit( AccountGroup *grp, int defer )
+ {
+   int i;
+   if (NULL == grp) return;
+ 
+   for( i=0; i<grp->numAcc; i++ )
+     {
+       grp->account[i]->open = ACC_BEGIN_EDIT;
+       if (defer)
+       grp->account[i]->open |= ACC_DEFER_REBALANCE;
+       xaccAccountGroupBeginEdit (grp->account[i]->children, defer);
+     }
+ }  
+ 
  /********************************************************************\
  \********************************************************************/
  
***************
*** 87,92 ****
--- 102,109 ----
    int i;
  
    if (NULL == grp) return;
+ 
+   xaccAccountGroupBeginEdit (grp, 1);
  
    for( i=0; i<grp->numAcc; i++ )
      xaccFreeAccount( grp->account[i] );