mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
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:
parent
4f84ccd735
commit
13bf124bfc
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user