gnumeric r16494 - in branches/gnumeric-1-8: . plugins/fn-lookup src



Author: mortenw
Date: Tue Apr  8 18:28:59 2008
New Revision: 16494
URL: http://svn.gnome.org/viewvc/gnumeric?rev=16494&view=rev

Log:
2008-04-08  Morten Welinder  <terra gnome org>

	* src/dependent.c (workbook_recalc): If we recalculated anything,
	emit recalc-finished on the application.

	* src/application.c (gnm_app_class_init): Install new
	"recalc-finished" signal.

	* src/ranges.c (gnm_sheet_range_dup, gnm_sheet_range_equal,
	gnm_sheet_range_hash, gnm_range_hash, gnm_range_equal): New
	functions.

2008-04-08  Morten Welinder  <terra gnome org>

	* functions.c (find_index_linear_equal_string): New function for a
	common special case.  Fixes #525875.
	(go_plugin_init): Install signal to clear caches after recalcs.
	(go_plugin_shutdown): Remove above signal.




Modified:
   branches/gnumeric-1-8/ChangeLog
   branches/gnumeric-1-8/NEWS
   branches/gnumeric-1-8/plugins/fn-lookup/ChangeLog
   branches/gnumeric-1-8/plugins/fn-lookup/functions.c
   branches/gnumeric-1-8/src/application.c
   branches/gnumeric-1-8/src/dependent.c
   branches/gnumeric-1-8/src/ranges.c
   branches/gnumeric-1-8/src/ranges.h

Modified: branches/gnumeric-1-8/NEWS
==============================================================================
--- branches/gnumeric-1-8/NEWS	(original)
+++ branches/gnumeric-1-8/NEWS	Tue Apr  8 18:28:59 2008
@@ -16,6 +16,7 @@
 	* Fix inc/dec buttons for General.  [#510252]
 	* Fix CONCATENATE's empty case.
 	* Improve performance of analysis tools for large ranges.
+	* Fix performance of repeated [VH]LOOKUP with constant data range.  [#525875]
 
 --------------------------------------------------------------------------
 Gnumeric 1.8.2

Modified: branches/gnumeric-1-8/plugins/fn-lookup/functions.c
==============================================================================
--- branches/gnumeric-1-8/plugins/fn-lookup/functions.c	(original)
+++ branches/gnumeric-1-8/plugins/fn-lookup/functions.c	Tue Apr  8 18:28:59 2008
@@ -36,7 +36,7 @@
 #include <ranges.h>
 #include <expr.h>
 #include <expr-impl.h>
-#include <expr-impl.h>
+#include <application.h>
 #include <expr-name.h>
 #include <parse-util.h>
 #include <gnm-i18n.h>
@@ -49,6 +49,42 @@
 
 GNM_PLUGIN_MODULE_HEADER;
 
+static GHashTable *lookup_string_cache;
+
+static void
+clear_caches (void)
+{
+	if (lookup_string_cache) {
+		g_hash_table_destroy (lookup_string_cache);
+		lookup_string_cache = NULL;
+	}
+}
+
+static GHashTable *
+get_string_cache (const GnmSheetRange *sr)
+{
+	GHashTable *h;
+
+	if (!lookup_string_cache) {
+		lookup_string_cache = g_hash_table_new_full
+			((GHashFunc)gnm_sheet_range_hash,
+			 (GEqualFunc)gnm_sheet_range_equal,
+			 (GDestroyNotify)gnm_sheet_range_free,
+			 (GDestroyNotify)g_hash_table_destroy);
+	}
+
+	h = g_hash_table_lookup (lookup_string_cache, sr);
+	if (!h) {
+		h = g_hash_table_new_full (g_str_hash, g_str_equal,
+					   g_free, NULL);
+		g_hash_table_insert (lookup_string_cache,
+				     gnm_sheet_range_dup (sr), h);
+	}
+
+	return h;
+}
+
+/* -------------------------------------------------------------------------- */
 
 static gboolean
 find_type_valid (GnmValue const *find)
@@ -154,6 +190,58 @@
 }
 
 static int
+find_index_linear_equal_string (GnmFuncEvalInfo *ei,
+				const char *s, GnmValue const *data,
+				gboolean vertical)
+{
+	GHashTable *h;
+	gpointer pres;
+	char *sc;
+	gboolean found;
+	GnmRangeRef const *rr;
+	Sheet *start_sheet, *end_sheet;
+	GnmSheetRange sr;
+
+	if (data->type != VALUE_CELLRANGE)
+		return -2;
+	rr = value_get_rangeref (data);
+
+        gnm_rangeref_normalize (rr, ei->pos, &start_sheet, &end_sheet, &sr.range);
+	if (start_sheet != end_sheet)
+		return -2;
+
+	/* We need to do this early before calls to value_peek_string gets
+	   called too often.  */
+	sc = g_utf8_casefold (s, -1);
+
+	sr.sheet = start_sheet;
+	h = get_string_cache (&sr);
+
+	if (g_hash_table_size (h) == 0) {
+		int lp, length = calc_length (data, ei->pos, vertical);
+
+		for (lp = 0; lp < length; lp++) {
+			GnmValue const *v = get_elem (data, lp, ei->pos, vertical);
+			char *vc;
+
+			if (!VALUE_IS_STRING (v))
+				continue;
+
+			vc = g_utf8_casefold (value_peek_string (v), -1);
+			if (g_hash_table_lookup_extended (h, vc, NULL, NULL))
+				g_free (vc);
+			else
+				g_hash_table_insert (h, vc, GINT_TO_POINTER (lp));
+		}
+	}
+
+	found = g_hash_table_lookup_extended (h, sc, NULL, &pres);
+	g_free (sc);
+
+	return found ? GPOINTER_TO_INT (pres) : -1;
+}
+
+static int
 find_index_linear (GnmFuncEvalInfo *ei,
 		   GnmValue const *find, GnmValue const *data,
 		   gint type, gboolean vertical)
@@ -162,9 +250,16 @@
 	GnmValDiff comp;
 	int length, lp, index = -1;
 
+	if (VALUE_IS_STRING (find) && type == 0) {
+		const char *s = value_peek_string (find);
+		int i = find_index_linear_equal_string (ei, s, data, vertical);
+		if (i != -2)
+			return i;
+	}
+
 	length = calc_length (data, ei->pos, vertical);
 
-	for (lp = 0; lp < length; lp++){
+	for (lp = 0; lp < length; lp++) {
 		GnmValue const *v = get_elem (data, lp, ei->pos, vertical);
 
 		g_return_val_if_fail (v != NULL, -1);
@@ -1263,7 +1358,7 @@
 	/* REMEMBER this is a transpose */
 	res = value_new_array_non_init (rows, cols);
 
-	for (r = 0; r < rows; ++r){
+	for (r = 0; r < rows; ++r) {
 		res->v_array.vals [r] = g_new (GnmValue *, cols);
 		for (c = 0; c < cols; ++c)
 			res->v_array.vals[r][c] = value_dup(
@@ -1330,3 +1425,17 @@
 
         {NULL}
 };
+
+G_MODULE_EXPORT void
+go_plugin_init (GOPlugin *plugin, GOCmdContext *cc)
+{
+	g_signal_connect (gnm_app_get_app (), "recalc-finished",
+			  G_CALLBACK (clear_caches), NULL);
+}
+
+G_MODULE_EXPORT void
+go_plugin_shutdown (GOPlugin *plugin, GOCmdContext *cc)
+{
+	g_signal_handlers_disconnect_by_func (gnm_app_get_app (),
+					      G_CALLBACK (clear_caches), NULL);
+}

Modified: branches/gnumeric-1-8/src/application.c
==============================================================================
--- branches/gnumeric-1-8/src/application.c	(original)
+++ branches/gnumeric-1-8/src/application.c	Tue Apr  8 18:28:59 2008
@@ -52,6 +52,7 @@
 	CUSTOM_UI_ADDED,
 	CUSTOM_UI_REMOVED,
 	CLIPBOARD_MODIFIED,
+	RECALC_FINISHED,
 	LAST_SIGNAL
 };
 
@@ -82,6 +83,7 @@
 	void (*custom_ui_added)	    (GnmApp *gnm_app, GnmAppExtraUI *ui);
 	void (*custom_ui_removed)   (GnmApp *gnm_app, GnmAppExtraUI *ui);
 	void (*clipboard_modified)  (GnmApp *gnm_app);
+	void (*recalc_finished)     (GnmApp *gnm_app);
 } GnmAppClass;
 
 static GObjectClass *parent_klass;
@@ -751,6 +753,13 @@
 		NULL, NULL,
 		g_cclosure_marshal_VOID__VOID,
 		G_TYPE_NONE, 0);
+	signals [RECALC_FINISHED] = g_signal_new ("recalc_finished",
+		GNM_APP_TYPE,
+		G_SIGNAL_RUN_LAST,
+		G_STRUCT_OFFSET (GnmAppClass, recalc_finished),
+		NULL, NULL,
+		g_cclosure_marshal_VOID__VOID,
+		G_TYPE_NONE, 0);
 }
 
 static void

Modified: branches/gnumeric-1-8/src/dependent.c
==============================================================================
--- branches/gnumeric-1-8/src/dependent.c	(original)
+++ branches/gnumeric-1-8/src/dependent.c	Tue Apr  8 18:28:59 2008
@@ -32,6 +32,7 @@
 #include "expr.h"
 #include "expr-impl.h"
 #include "expr-name.h"
+#include "application.h"
 #include "workbook-view.h"
 #include "rendered-value.h" /* FIXME : should not be needed with JIT-R */
 #include "ranges.h"
@@ -2592,6 +2593,8 @@
 	 * expensive.
 	 */
 	if (redraw) {
+		g_signal_emit_by_name (gnm_app_get_app (), "recalc-finished");
+
 		WORKBOOK_FOREACH_SHEET (wb, sheet, {
 			SHEET_FOREACH_VIEW (sheet, sv, sv_flag_selection_change (sv););
 			sheet_redraw_all (sheet, FALSE);});

Modified: branches/gnumeric-1-8/src/ranges.c
==============================================================================
--- branches/gnumeric-1-8/src/ranges.c	(original)
+++ branches/gnumeric-1-8/src/ranges.c	Tue Apr  8 18:28:59 2008
@@ -778,6 +778,29 @@
 	return clipped;
 }
 
+gboolean
+gnm_range_equal (const GnmRange *a, const GnmRange *b)
+{
+	return range_equal (a, b);
+}
+
+guint
+gnm_range_hash (const GnmRange *r)
+{
+	guint res = 0;
+
+	res ^= r->start.col;
+	res *= 17;
+	res ^= r->start.row;
+	res *= 17;
+	res ^= r->end.col;
+	res *= 17;
+	res ^= r->end.row;
+
+	return res;
+}
+
+
 GnmSheetRange *
 gnm_sheet_range_new (Sheet *sheet, GnmRange const *r)
 {
@@ -793,6 +816,13 @@
 	return gr;
 }
 
+GnmSheetRange *
+gnm_sheet_range_dup (GnmSheetRange const *sr)
+{
+	g_return_val_if_fail (sr != NULL, NULL);
+	return gnm_sheet_range_new (sr->sheet, &sr->range);
+}
+
 /**
  * gnm_sheet_range_from_value :
  * @res :
@@ -818,6 +848,19 @@
 }
 
 gboolean
+gnm_sheet_range_equal (const GnmSheetRange *a,
+		       const GnmSheetRange *b)
+{
+	return a->sheet == b->sheet && range_equal (&a->range, &b->range);
+}
+
+guint
+gnm_sheet_range_hash (const GnmSheetRange *sr)
+{
+	return gnm_range_hash (&sr->range) ^ sr->sheet->index_in_wb;
+}
+
+gboolean
 gnm_sheet_range_overlap (GnmSheetRange const *a, GnmSheetRange const *b)
 {
 	g_return_val_if_fail (a != NULL, FALSE);

Modified: branches/gnumeric-1-8/src/ranges.h
==============================================================================
--- branches/gnumeric-1-8/src/ranges.h	(original)
+++ branches/gnumeric-1-8/src/ranges.h	Tue Apr  8 18:28:59 2008
@@ -20,6 +20,9 @@
 			    (a)->start.col == (b)->start.col && \
 			    (a)->end.col   == (b)->end.col)
 
+gboolean gnm_range_equal (const GnmRange *a, const GnmRange *b);
+guint gnm_range_hash (const GnmRange *r);
+
 /**
  * range_overlap:
  * @a: First range
@@ -98,6 +101,10 @@
 void           gnm_sheet_range_free       (GnmSheetRange *r);
 gboolean       gnm_sheet_range_from_value (GnmSheetRange *r, GnmValue const *v);
 gboolean       gnm_sheet_range_overlap    (GnmSheetRange const *a, GnmSheetRange const *b);
+GnmSheetRange *gnm_sheet_range_dup	  (GnmSheetRange const *sr);
+gboolean       gnm_sheet_range_equal      (const GnmSheetRange *a,
+					   const GnmSheetRange *b);
+guint          gnm_sheet_range_hash       (const GnmSheetRange *sr);
 
 char	      *global_range_name	  (Sheet const *sheet, GnmRange const *r);
 char	      *undo_cell_pos_name	  (Sheet const *sheet, GnmCellPos const *pos);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]