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