[gtk+/filesystemmodel: 17/28] add _gtk_file_system_model_get_value() to speed up sorting
- From: Benjamin Otte <otte src gnome org>
- To: svn-commits-list gnome org
- Subject: [gtk+/filesystemmodel: 17/28] add _gtk_file_system_model_get_value() to speed up sorting
- Date: Tue, 23 Jun 2009 16:18:17 -0400 (EDT)
commit f8c59d67818c5f2b6d731e115be23bf9d2c39dad
Author: Benjamin Otte <otte gnome org>
Date: Mon Jun 22 11:54:56 2009 +0200
add _gtk_file_system_model_get_value() to speed up sorting
"speed up" is kind of an understatement here, because sorting went from
~5 seconds to less than 0.5 seconds for my test case. There is 2
significant problems with gtk_tree_model_get():
1) The value is copied, which takes quite a bit of time for strings.
~25% of excessive time
2) The tree model functions need to lookup the interface vfunc. And
gtk_tree_model_get() doesn't do that only once, but multiple times
(verifying column id, getting the actual value, ...)
~75% of excessive time
This function works around both of these issues, but introduces an ugly
extra function that should not be necessary, but I can't imagine how to
get rid of it.
gtk/gtkfilechooserdefault.c | 65 +++++++++++++++++++++++++++++++++---------
gtk/gtkfilesystemmodel.c | 62 +++++++++++++++++++++++++++++-----------
gtk/gtkfilesystemmodel.h | 3 ++
3 files changed, 99 insertions(+), 31 deletions(-)
---
diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c
index 441b04e..c45f4ee 100644
--- a/gtk/gtkfilechooserdefault.c
+++ b/gtk/gtkfilechooserdefault.c
@@ -6094,10 +6094,20 @@ install_list_model_filter (GtkFileChooserDefault *impl)
#define COMPARE_DIRECTORIES \
GtkFileChooserDefault *impl = user_data; \
+ GtkFileSystemModel *fs_model = model == (GtkTreeModel *) impl->browse_files_model ? \
+ impl->browse_files_model : NULL; \
gboolean dir_a, dir_b; \
\
- gtk_tree_model_get (model, a, MODEL_COL_IS_FOLDER, &dir_a, -1); \
- gtk_tree_model_get (model, b, MODEL_COL_IS_FOLDER, &dir_b, -1); \
+ if (fs_model) \
+ { \
+ dir_a = g_value_get_boolean (_gtk_file_system_model_get_value (fs_model, a, MODEL_COL_IS_FOLDER)); \
+ dir_b = g_value_get_boolean (_gtk_file_system_model_get_value (fs_model, b, MODEL_COL_IS_FOLDER)); \
+ } \
+ else \
+ { \
+ gtk_tree_model_get (model, a, MODEL_COL_IS_FOLDER, &dir_a, -1); \
+ gtk_tree_model_get (model, b, MODEL_COL_IS_FOLDER, &dir_b, -1); \
+ } \
\
if (dir_a != dir_b) \
return impl->list_sort_ascending ? (dir_a ? -1 : 1) : (dir_a ? 1 : -1) /* Directories *always* go first */
@@ -6112,23 +6122,34 @@ name_sort_func (GtkTreeModel *model,
COMPARE_DIRECTORIES;
else
{
- gchar *key_a, *key_b;
+ const char *key_a, *key_b;
gint result;
- gtk_tree_model_get (model, a, MODEL_COL_NAME_COLLATED, &key_a, -1);
- gtk_tree_model_get (model, b, MODEL_COL_NAME_COLLATED, &key_b, -1);
+ if (fs_model)
+ {
+ key_a = g_value_get_string (_gtk_file_system_model_get_value (fs_model, a, MODEL_COL_NAME_COLLATED));
+ key_b = g_value_get_string (_gtk_file_system_model_get_value (fs_model, b, MODEL_COL_NAME_COLLATED));
+ }
+ else
+ {
+ gtk_tree_model_get (model, a, MODEL_COL_NAME_COLLATED, &key_a, -1);
+ gtk_tree_model_get (model, b, MODEL_COL_NAME_COLLATED, &key_b, -1);
+ }
if (key_a && key_b)
result = strcmp (key_a, key_b);
else if (key_a)
- return 1;
+ result = 1;
else if (key_b)
- return -1;
+ result = -1;
else
- return 0;
+ result = 0;
- g_free (key_a);
- g_free (key_b);
+ if (!fs_model)
+ {
+ g_free ((char *) key_a);
+ g_free ((char *) key_b);
+ }
return result;
}
@@ -6146,8 +6167,16 @@ size_sort_func (GtkTreeModel *model,
{
gint64 size_a, size_b;
- gtk_tree_model_get (model, a, MODEL_COL_SIZE, &size_a, -1);
- gtk_tree_model_get (model, b, MODEL_COL_SIZE, &size_b, -1);
+ if (fs_model)
+ {
+ size_a = g_value_get_int64 (_gtk_file_system_model_get_value (fs_model, a, MODEL_COL_SIZE));
+ size_b = g_value_get_int64 (_gtk_file_system_model_get_value (fs_model, b, MODEL_COL_SIZE));
+ }
+ else
+ {
+ gtk_tree_model_get (model, a, MODEL_COL_SIZE, &size_a, -1);
+ gtk_tree_model_get (model, b, MODEL_COL_SIZE, &size_b, -1);
+ }
return size_a > size_b ? -1 : (size_a == size_b ? 0 : 1);
}
@@ -6165,8 +6194,16 @@ mtime_sort_func (GtkTreeModel *model,
{
glong ta, tb;
- gtk_tree_model_get (model, a, MODEL_COL_MTIME, &ta, -1);
- gtk_tree_model_get (model, b, MODEL_COL_MTIME, &tb, -1);
+ if (fs_model)
+ {
+ ta = g_value_get_long (_gtk_file_system_model_get_value (fs_model, a, MODEL_COL_MTIME));
+ tb = g_value_get_long (_gtk_file_system_model_get_value (fs_model, b, MODEL_COL_MTIME));
+ }
+ else
+ {
+ gtk_tree_model_get (model, a, MODEL_COL_MTIME, &ta, -1);
+ gtk_tree_model_get (model, b, MODEL_COL_MTIME, &tb, -1);
+ }
return ta > tb ? -1 : (ta == tb ? 0 : 1);
}
diff --git a/gtk/gtkfilesystemmodel.c b/gtk/gtkfilesystemmodel.c
index 34d8396..d4cc013 100644
--- a/gtk/gtkfilesystemmodel.c
+++ b/gtk/gtkfilesystemmodel.c
@@ -348,26 +348,14 @@ gtk_file_system_model_get_value (GtkTreeModel *tree_model,
GValue *value)
{
GtkFileSystemModel *model = GTK_FILE_SYSTEM_MODEL (tree_model);
- FileModelNode *node;
+ const GValue *original;
g_return_if_fail ((guint) column < model->n_columns);
g_return_if_fail (ITER_IS_VALID (model, iter));
- node = get_node (model, ITER_INDEX (iter));
-
- if (!G_VALUE_TYPE (&node->values[column]))
- {
- g_value_init (&node->values[column], model->column_types[column]);
- model->get_func (model,
- node->file,
- node->info,
- column,
- &node->values[column],
- model->get_data);
- }
-
- g_value_init (value, model->column_types[column]);
- g_value_copy (&node->values[column], value);
+ original = _gtk_file_system_model_get_value (model, iter, column);
+ g_value_init (value, G_VALUE_TYPE (original));
+ g_value_copy (original, value);
}
static gboolean
@@ -1166,7 +1154,7 @@ _gtk_file_system_model_get_info (GtkFileSystemModel *model,
* @model: a #GtkFileSystemModel
* @iter: a #GtkTreeIter pointing to a row of @model
*
- * Gets the path for a particular row in @model.
+ * Gets the file for a particular row in @model.
*
* Return value: the file. This object is owned by @model and
* or freed. If you want to save the path for later use,
@@ -1185,6 +1173,46 @@ _gtk_file_system_model_get_file (GtkFileSystemModel *model,
return node->file;
}
+/**
+ * _gtk_file_system_model_get_value:
+ * @model: a #GtkFileSystemModel
+ * @iter: a #GtkTreeIter pointing to a row of @model
+ * @column: the column to get the value for
+ *
+ * Gets the value associated with the given row @iter and @column.
+ * This is a performance optimization for the calls
+ * gtk_tree_model_get() or gtk_tree_model_get_value(), which copy
+ * the value and spend a considerable amount of time in iterator
+ * lookups. Both of which are slow.
+ *
+ * Returns: a pointer to the actual value as stored in @model.
+ **/
+const GValue *
+_gtk_file_system_model_get_value (GtkFileSystemModel *model,
+ GtkTreeIter * iter,
+ int column)
+{
+ FileModelNode *node;
+
+ g_return_val_if_fail (GTK_IS_FILE_SYSTEM_MODEL (model), NULL);
+ g_return_val_if_fail (column >= 0 && (guint) column < model->n_columns, NULL);
+
+ node = get_node (model, ITER_INDEX (iter));
+
+ if (!G_VALUE_TYPE (&node->values[column]))
+ {
+ g_value_init (&node->values[column], model->column_types[column]);
+ model->get_func (model,
+ node->file,
+ node->info,
+ column,
+ &node->values[column],
+ model->get_data);
+ }
+
+ return &node->values[column];
+}
+
gboolean
_gtk_file_system_model_get_iter_for_file (GtkFileSystemModel *model,
GtkTreeIter *iter,
diff --git a/gtk/gtkfilesystemmodel.h b/gtk/gtkfilesystemmodel.h
index bf8e766..fc50721 100644
--- a/gtk/gtkfilesystemmodel.h
+++ b/gtk/gtkfilesystemmodel.h
@@ -54,6 +54,9 @@ gboolean _gtk_file_system_model_get_iter_for_file(GtkFileSystemModel
GFile * file);
GFile * _gtk_file_system_model_get_file (GtkFileSystemModel *model,
GtkTreeIter *iter);
+const GValue * _gtk_file_system_model_get_value (GtkFileSystemModel *model,
+ GtkTreeIter * iter,
+ int column);
void _gtk_file_system_model_set_show_hidden (GtkFileSystemModel *model,
gboolean show_hidden);
void _gtk_file_system_model_set_show_folders (GtkFileSystemModel *model,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]