Flylib.com

Books Software

 
 
 

11.9. Finding the Time Differences


11.9. Finding the Time Differences

Now that we have narrowed down which functions do the work of creating the menu, we want to figure out which pieces are taking up all the time and which pieces are relatively lightweight. A great way to do that, without using any performance tools at all, is to just disable pieces of code and see how it changes performance. Even though this causes nautilus to function incorrectly, it will at least indicate which of the functions are taking all the time.

We first have to start by taking a baseline, because the binaries we are testing have been compiled with different flags than those provided by Red Hat. We time the scripts as we did before. In this case, a run of 100 iterations takes 30.5 seconds on the version that we have compiled ourselves . Next, we comment out the eel_pop_up_context_menu call. This shows us how much time it took nautilus to detect the mouse click and decide that a context menu needed to be created. Even if we completely optimize away all the commands in these functions, we will not be able to run any faster than this. In this case, it takes 7.6 seconds to run all 100 iterations. Next, we comment out bonobo_window_add_popup to see how much time it costs us to actually call the function that ltrace says is taking the most amount of time. If we comment out bonobo_window_add_popup , the 100 iterations take 21.9 seconds to complete. This says that if we optimize away the bonobo_window_add_popup , it can shave ~8 seconds off the total run, which is nearly a 25 percent improvement.


11.10. Trying a Possible Solution

So, as we have seen, bonobo_window_add_popup is an expensive function that must be called every time we want to create a pop-up menu. If we are repeatedly calling it with the same parameters, it may be possible to cache the value it returns from the initial call and use that every time after that instead of repeatedly calling that expensive function. Listing 11.19 shows an example of a rewritten function to do just that.

Listing 11.19.
void

fm_directory_view_pop_up_background_context_menu (FMDirectoryView *view,

                                        GdkEventButton *event)

{

   /* Primitive Cache */

   static FMDirectoryView *old_view = NULL;

   static GtkMenu *old_menu = NULL;





   g_assert (FM_IS_DIRECTORY_VIEW (view));





   /* Make the context menu items not flash as they update to proper disabled,

    * etc. states by forcing menus to update now.

    */

   if ((old_view != view)    view->details->menu_states_untrustworthy)

          {

              update_menus_if_pending (view);

              old_view = view;

              old_menu = create_popup_menu(view, FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND);

          }





  eel_pop_up_context_menu (old_menu,

         EEL_DEFAULT_POPUP_MENU_DISPLACEMENT,

         EEL_DEFAULT_POPUP_MENU_DISPLACEMENT,

         event);

}

In this case, we remember the menu that was generated last time. If we are past it in the same view, and we do not believe that the menu for that view has changed, we just use the same menu that we used last time instead of creating a new one. This is not a sophisticated technique, and it will break down if the user does not open a pop-up menu in the same directory repeatedly. For example, if the user opens a pop-up in directory 1, and then opens one in directory 2, if the user then opens a pop-up in directory 1, nautilus will still create a new menu. It is possible to create a simple cache that stores menus as they are created. When opening a menu, the first check is to see whether these views already have menus in the cache. If they do, the cached menus could be viewed ; otherwise , new ones could be created. This cache would be especially useful for some special directories, such as the desktop, computer, or home directory where the user will most likely open a pop-up menu more than once. After applying this proposed solution and timing it with the 100 iterations, the time has dropped to 24.0 seconds. This is a ~20 percent performance improvement, and close to the theoretical improvement that we would get if we did not create the menu at all (21.9 seconds). Creating pop-up menus in various directories worked as expected. The patch did not appear to break anything.

Note, however, that right now, this is just a test solution. It would have to be presented to the nautilus developers to confirm that it did not break any functionality and is suitable for inclusion. However, through the course of the hunt, we have determined what functions are slow, tracked down where they are called, and created a possible solution that objectively improves performance. It is also important to note that the improvement was objective; that is, we have hard data to prove that the new method is faster, rather than simply subjective (i.e., just saying that it feels snappier). Most developers would love to have this kind of performance bug report.