Consider the subprogram attached. It shows a simple tree_view displaying a list_store (5000 columns and 50 rows containing integers). The display performance is very poor: when displaying the last columns, the vertical scollbar takes between 5 and 10 seconds to respond.
Preliminary note: a tree of 50 columns and 5000 rows displays better performance (scrollbars take between 0 and 1 seconds to respond).
Using the Apple Shark profiler gave me the following tree showing where the time is spent while simply scrolling the scrollbar. In this tree, line N+1 calls line N.
Self Total Library 0.0% 80.3% bigtree main 0.0% 80.3% libgtk-x11-2.0.0.dylib gtk_main 0.0% 80.3% libglib-2.0.0.dylib g_main_loop_run 0.0% 80.3% libglib-2.0.0.dylib g_main_context_iterate 0.0% 80.3% libglib-2.0.0.dylib g_main_context_dispatch 0.0% 80.3% libglib-2.0.0.dylib g_main_dispatch 0.0% 79.8% libglib-2.0.0.dylib g_idle_dispatch 0.0% 79.8% libgdk-x11-2.0.0.dylib gdk_window_update_idle 0.0% 79.8% libgdk-x11-2.0.0.dylib gdk_window_process_all_updates 0.0% 79.8% libgdk-x11-2.0.0.dylib gdk_window_process_updates_internal 0.0% 79.8% libgtk-x11-2.0.0.dylib gtk_main_do_event 0.0% 79.8% libgtk-x11-2.0.0.dylib gtk_widget_send_expose 0.0% 79.8% libgtk-x11-2.0.0.dylib gtk_widget_event_internal 0.0% 79.8% libgobject-2.0.0.dylib g_signal_emit 0.0% 79.8% libgobject-2.0.0.dylib g_signal_emit_valist 0.0% 79.8% libgobject-2.0.0.dylib signal_emit_unlocked_R 0.0% 79.8% libgobject-2.0.0.dylib g_closure_invoke 0.0% 79.8% libgobject-2.0.0.dylib g_type_class_meta_marshal 0.0% 79.8% libgtk-x11-2.0.0.dylib _gtk_marshal_BOOLEAN__BOXED 0.0% 79.8% libgtk-x11-2.0.0.dylib gtk_tree_view_expose 0.2% 79.6% libgtk-x11-2.0.0.dylib gtk_tree_view_bin_expose0.4% 26.4% libgtk-x11-2.0.0.dylib gtk_tree_view_column_cell_set_cell_data
0.0% 18.4% libgtk-x11-2.0.0.dylib gtk_tree_model_get_value 17.5% 18.0% libgtk-x11-2.0.0.dylib gtk_list_store_get_value I have two comments to make about this tree:A) it seems strange that 18% of the time is spent in gtk_list_store_get_value.
B) it seems very strange that gtk_tree_view_bin_expose calls gtk_tree_view_column_cell_set_cell_data.
Investigating further in the direction given by comment A), I saw that the following lines in gtkliststore.c were consuming the biggest amount of time:
Self Total Line Code
451 static void
452 gtk_list_store_get_value (GtkTreeModel *tree_model,
453 GtkTreeIter *iter,
454 gint column,
455 GValue *value)
0.0% 0.1% 456 {
457 GtkListStore *list_store = (GtkListStore *) tree_model;
458 GtkTreeDataList *list;
459 gint tmp_column = column;
460
0.0% 0.0% 461 g_return_if_fail (column < list_store->n_columns);
0.0% 0.4% 462 g_return_if_fail (VALID_ITER (iter, list_store));
463
0.0% 0.4% 464 list = _gtk_sequence_ptr_get_data (iter->user_data);
465
53.2% 51.8% 466 while (tmp_column-- > 0 && list)
46.5% 45.3% 467 list = list->next;
468
0.0% 0.0% 469 if (list == NULL)
470 g_value_init (value, list_store->column_headers[column]);
471 else
0.1% 1.9% 472 _gtk_tree_data_list_node_to_value (list,
473 list_store->column_headers[column],
474 value);
0.1% 0.1% 475 }
So, it seems that we spend most of our time traversing the list of
columns. Note that this explains why a tree of 5000 columns x 50 rows
has such bad performance compared to a tree of 50 columns x 5000 rows.
First suggestion: we'd be better off in this subprogram if the data was implemented as an array instead of as a linked list.
Let's turn now to comment B). Why is gtk_tree_view_bin_expose calling gtk_tree_view_column_cell_set_cell_data ?
The code doing this is the following:
/* we *need* to set cell data on all cells before the call
* to _has_special_cell, else _has_special_cell() does not
* return a correct value.
*/
for (list = (rtl ? g_list_last (tree_view->priv->columns) :
g_list_first (tree_view->priv->columns));
list;
list = (rtl ? list->prev : list->next))
{
GtkTreeViewColumn *column = list->data;
gtk_tree_view_column_cell_set_cell_data (column,
tree_view->priv->model,
&iter,
GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_IS_PARENT),
node->children?TRUE:FALSE);
}
has_special_cell = gtk_tree_view_has_special_cell (tree_view);
I'm not familiar with this area yet, so I'm puzzled: is the call to
gtk_tree_view_column_cell_set_cell_data really needed for the
purposes of gtk_tree_view_bin_expose, or is it just needed for the
call to gtk_tree_view_has_special_cell?
In any case, I suggest we cache this - probably there is no need to do it in every expose call, only after the model data has changed.
To sum up (thanks for reading me), would you accept a patch along those lines?
Nicolas
Attachment:
bigtree.c
Description: Binary data