ideas on improving the performance of gtk_tree_view



This describes an idea to improve the display performance of the tree_views, based on the sources of gtk+-2.10.11, and suggests possible solutions.


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_expose
0.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



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