Previous Section  < Day Day Up >  Next Section

11.7. Compile and Examine the Source

So now that we have some idea about which calls the application is taking all of the time, we will download the source and compile it. Until now, all of our analysis was possible using the binary packages that Red Hat provides. However, now we need to dive into the source code to examine why the hot functions are called and then, when we figure out why, make changes in the source to alleviate the performance problem. As we did for GIMP, when we recompile, we generate debugging symbols by setting CFLAGS to -g before we call the configure script.

In this case, we downloaded and installed Red Hat's source rpm for nautilus, which places the source of nautilus in /usr/src/redhat/SOURCES/. By using Red Hat's source package, we have the exact source and patches that Red Hat used to create the binary in the package. It is important to investigate the source that was used to create the binaries that we have been investigating, because another version may have different performance characteristics. After we extract the source, we can begin to figure out where the bonobo_window_add_popup call is made. We can search all the source files in the nautilus directory using the commands in Listing 11.9.

Listing 11.9.

[nautilus ]$ find -type f | xargs grep bonobo_window_add_popup



./src/file-manager/fm-directory-view.c: bonobo_window_add_popup\

(get_bonobo_window (view), menu, popup_path);


Fortunately, it appears as if bonobo_window_add_popup is only called from a single function, create_popup_menu, as shown in Listing 11.10.

Listing 11.10.

static GtkMenu *create_popup_menu (FMDirectoryView *view,

                              const char *popup_path)



{

   GtkMenu *menu;





   menu = GTK_MENU (gtk_menu_new ());

   gtk_menu_set_screen (menu, gtk_widget_get_screen (GTK_WIDGET (view)));





   gtk_widget_show (GTK_WIDGET (menu));





   bonobo_window_add_popup (get_bonobo_window (view), menu, popup_path);





   g_signal_connect_object (menu, "hide",

                            G_CALLBACK (popup_menu_hidden),

                            G_OBJECT (view),

                            G_CONNECT_SWAPPED);



       return menu;



}


In turn, this function is called by two other functions: fm_directory_view_pop_up_background_context_menu and fm_directory_view_pop_up_selection_context_menu. By adding a printf to each of the functions, we can determine which one is called when we right-click a window. We then recompile nautilus, launch it, and then right-click the background of the window. nautilus prints out fm_directory_view_pop_up_background_context_menu, so we know that this is the function that is called when opening a pop-up menu in the background of the window. The source code for this function is shown in Listing 11.11.

Listing 11.11.

void fm_directory_view_pop_up_background_context_menu (FMDirectoryView

*view, GdkEventButton *event)

{

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.

 */

update_menus_if_pending (view);

eel_pop_up_context_menu

(create_popup_menu (view, FM_DIRECTORY_VIEW_POPUP_PATH_BACKGROUND),

                           EEL_DEFAULT_POPUP_MENU_DISPLACEMENT,

                    EEL_DEFAULT_POPUP_MENU_DISPLACEMENT, event);

}


Now that we have narrowed down exactly where the menu pop-ups are created and displayed, we can begin to figure out exactly which pieces are taking all the time and which pieces are ultimately calling the g_type_check_instance_is_a function that oprofile says is the hot function.

    Previous Section  < Day Day Up >  Next Section