gnumeric r16494 - in branches/gnumeric-1-8: . plugins/fn-lookup src
- From: mortenw svn gnome org
- To: svn-commits-list gnome org
- Subject: gnumeric r16494 - in branches/gnumeric-1-8: . plugins/fn-lookup src
- Date: Tue, 8 Apr 2008 18:28:59 +0100 (BST)
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]