Tyson Dowd's patch to use GCaches for string caching in the engine.

git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3121 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
Dave Peticolas 2000-11-06 22:42:35 +00:00
parent 4f84ccd735
commit 13bf124bfc
4 changed files with 75 additions and 34 deletions

View File

@ -42,6 +42,7 @@
#include "date.h"
#include "gnc-commodity.h"
#include "gnc-engine-util.h"
#include "gnc-engine.h"
/*
* The "force_double_entry" flag determines how
@ -91,8 +92,8 @@ xaccInitSplit(Split * split)
split->acc = NULL;
split->parent = NULL;
split->action = g_strdup("");
split->memo = g_strdup("");
split->action = g_cache_insert(gnc_string_cache, "");
split->memo = g_cache_insert(gnc_string_cache, "");
split->reconciled = NREC;
split->damount = gnc_numeric_zero();
split->value = gnc_numeric_zero();
@ -140,8 +141,8 @@ xaccCloneSplit (Split *s)
split->acc = s->acc;
split->parent = s->parent;
split->action = g_strdup(s->action);
split->memo = g_strdup(s->memo);
split->action = g_cache_insert(gnc_string_cache, s->action);
split->memo = g_cache_insert(gnc_string_cache, s->memo);
split->reconciled = s->reconciled;
split->damount = s->damount;
split->value = s->value;
@ -173,8 +174,8 @@ xaccFreeSplit( Split *split )
{
if (!split) return;
g_free (split->memo);
g_free (split->action);
g_cache_remove(gnc_string_cache, split->memo);
g_cache_remove(gnc_string_cache, split->action);
/* just in case someone looks up freed memory ... */
split->memo = NULL;
@ -207,8 +208,9 @@ xaccSplitEqual(const Split *sa, const Split *sb,
if(!guid_equal(&(sa->guid), &(sb->guid))) return FALSE;
}
if(safe_strcmp(sa->memo, sb->memo) != 0) return FALSE;
if(safe_strcmp(sa->action, sb->action) != 0) return FALSE;
/* Since these strings are cached we can just use pointer equality */
if(sa->memo != sb->memo) return FALSE;
if(sa->action != sb->action) return FALSE;
if(kvp_frame_compare(sa->kvp_data, sb->kvp_data) != 0) return FALSE;
@ -557,8 +559,8 @@ static void
xaccInitTransaction (Transaction * trans)
{
/* Fill in some sane defaults */
trans->num = g_strdup("");
trans->description = g_strdup("");
trans->num = g_cache_insert(gnc_string_cache, "");
trans->description = g_cache_insert(gnc_string_cache, "");
trans->splits = NULL;
@ -605,8 +607,8 @@ xaccCloneTransaction (Transaction *t)
trans = g_new(Transaction, 1);
trans->num = g_strdup(t->num);
trans->description = g_strdup(t->description);
trans->num = g_cache_insert(gnc_string_cache, t->num);
trans->description = g_cache_insert(gnc_string_cache, t->description);
trans->splits = g_list_copy (t->splits);
for (node = trans->splits; node; node = node->next)
@ -648,8 +650,8 @@ xaccFreeTransaction (Transaction *trans)
trans->splits = NULL;
/* free up transaction strings */
g_free (trans->num);
g_free (trans->description);
g_cache_remove(gnc_string_cache, trans->num);
g_cache_remove(gnc_string_cache, trans->description);
/* just in case someone looks up freed memory ... */
trans->num = NULL;
@ -698,8 +700,11 @@ xaccTransEqual(const Transaction *ta, const Transaction *tb,
if(!timespec_equal(&(ta->date_entered), &(tb->date_entered))) return FALSE;
if(!timespec_equal(&(ta->date_posted), &(tb->date_posted))) return FALSE;
if(safe_strcmp(ta->num, tb->num) != 0) return FALSE;
if(safe_strcmp(ta->description, tb->description) != 0) return FALSE;
/* Since we use cached strings, we can just compare pointer
* equality for num and description
*/
if(ta->num != tb->num) return FALSE;
if(ta->description != tb->description) return FALSE;
if(kvp_frame_compare(ta->kvp_data, tb->kvp_data) != 0) return FALSE;
@ -1219,14 +1224,14 @@ xaccSplitRebalance (Split *split)
xaccTransAppendSplit (trans, s);
xaccAccountInsertSplit (split->acc, s);
g_free (s->memo);
g_free (s->action);
g_cache_remove(gnc_string_cache, s->memo);
g_cache_remove(gnc_string_cache, s->action);
xaccSplitSetValue(s, gnc_numeric_neg(split->value));
xaccSplitSetShareAmount(s, gnc_numeric_neg(split->value));
s->memo = g_strdup (split->memo);
s->action = g_strdup (split->action);
s->memo = g_cache_insert(gnc_string_cache, split->memo);
s->action = g_cache_insert(gnc_string_cache, split->action);
}
}
}
@ -1425,9 +1430,11 @@ xaccTransRollbackEdit (Transaction *trans)
#define PUT_BACK(val) { g_free(trans->val); \
trans->val=orig->val; orig->val=NULL; }
#define PUT_BACK_CACHE(val) { g_cache_remove(gnc_string_cache, trans->val); \
trans->val=orig->val; orig->val=NULL; }
PUT_BACK (num);
PUT_BACK (description);
PUT_BACK_CACHE (description);
trans->date_entered.tv_sec = orig->date_entered.tv_sec;
trans->date_entered.tv_nsec = orig->date_entered.tv_nsec;
@ -1903,8 +1910,8 @@ xaccTransSetNum (Transaction *trans, const char *xnum)
if (!trans || !xnum) return;
CHECK_OPEN (trans);
tmp = g_strdup (xnum);
g_free (trans->num);
tmp = g_cache_insert(gnc_string_cache, (gpointer) xnum);
g_cache_remove(gnc_string_cache, trans->num);
trans->num = tmp;
MarkChanged (trans);
}
@ -1916,8 +1923,8 @@ xaccTransSetDescription (Transaction *trans, const char *desc)
if (!trans || !desc) return;
CHECK_OPEN (trans);
tmp = g_strdup (desc);
g_free (trans->description);
tmp = g_cache_insert(gnc_string_cache, (gpointer) desc);
g_cache_remove(gnc_string_cache, trans->description);
trans->description = tmp;
MarkChanged (trans);
}
@ -1991,8 +1998,9 @@ xaccSplitSetMemo (Split *split, const char *memo)
{
char * tmp;
if (!split || !memo) return;
tmp = g_strdup (memo);
g_free (split->memo);
tmp = g_cache_insert(gnc_string_cache, (gpointer) memo);
g_cache_remove(gnc_string_cache, split->memo);
split->memo = tmp;
MARK_SPLIT (split);
}
@ -2002,8 +2010,9 @@ xaccSplitSetAction (Split *split, const char *actn)
{
char * tmp;
if (!split || !actn) return;
tmp = g_strdup (actn);
g_free (split->action);
tmp = g_cache_insert(gnc_string_cache, (gpointer) actn);
g_cache_remove(gnc_string_cache, split->action);
split->action = tmp;
MARK_SPLIT (split);
}

View File

@ -29,7 +29,7 @@
static GList * engine_init_hooks = NULL;
static gnc_commodity_table * known_commodities = NULL;
static int engine_is_initialized = 0;
GCache * gnc_string_cache = NULL;
/********************************************************************
* gnc_engine_init
@ -43,6 +43,11 @@ gnc_engine_init(int argc, char ** argv) {
engine_is_initialized = 1;
/* initialize the string cache */
gnc_string_cache = g_cache_new( (GCacheNewFunc) g_strdup,
g_free, (GCacheDupFunc) g_strdup, g_free, g_str_hash,
g_str_hash, g_str_equal);
/* initialize the commodity table (it starts empty) */
known_commodities = gnc_commodity_table_new();

View File

@ -41,5 +41,24 @@ void gnc_engine_add_init_hook(gnc_engine_init_hook_t hook);
/* this is a global table of known commodity types. */
gnc_commodity_table * gnc_engine_commodities(void);
/* Many strings used throughout the engine are likely to be duplicated.
* So we provide a reference counted cache system for the strings, which
* shares strings whenever possible.
*
* Use g_cache_insert to insert a string into the cache (it will return a
* pointer to the cached string).
* Basically you should use this instead of g_strdup.
*
* Use g_cache_remove (giving it a pointer to a cached string) if the string
* is unused. If this is the last reference to the string it will be
* removed from the cache, otherwise it will just decrement the
* reference count.
* Basically you should use this instead of g_free.
*
* Note that all the work is done when inserting or removing. Once
* cached the strings are just plain C strings.
*/
extern GCache *gnc_string_cache;
#endif

View File

@ -23,11 +23,15 @@
#include "kvp_frame.h"
#include "guid.h"
#include "gnc-engine.h"
#include <string.h>
#include <stdio.h>
#include <glib.h>
/* Note that we keep the keys for this hash table in a GCache
* (gnc_string_cache), as it is likely we will see the same keys
* over and over again */
struct _kvp_frame {
GHashTable * hash;
};
@ -84,7 +88,7 @@ kvp_frame_new(void) {
static void
kvp_frame_delete_worker(gpointer key, gpointer value, gpointer user_data) {
g_free(key);
g_cache_remove(gnc_string_cache, key);
kvp_value_delete((kvp_value *)value);
}
@ -107,7 +111,7 @@ kvp_frame_copy_worker(gpointer key, gpointer value, gpointer user_data) {
kvp_frame * dest = (kvp_frame *)user_data;
g_hash_table_freeze(dest->hash);
g_hash_table_insert(dest->hash,
(gpointer)g_strdup(key),
(gpointer)g_cache_insert(gnc_string_cache, key),
(gpointer)kvp_value_copy(value));
g_hash_table_thaw(dest->hash);
}
@ -142,11 +146,15 @@ kvp_frame_set_slot_destructively(kvp_frame * frame, const char * slot,
& orig_key, & orig_value);
if(key_exists) {
g_hash_table_remove(frame->hash, slot);
g_free(orig_key);
g_cache_remove(gnc_string_cache, orig_key);
kvp_value_delete(orig_value);
}
if(new_value) g_hash_table_insert(frame->hash, g_strdup(slot), new_value);
if(new_value) {
g_hash_table_insert(frame->hash,
g_cache_insert(gnc_string_cache, (gpointer) slot),
new_value);
}
g_hash_table_thaw(frame->hash);
}