Showing posts with label Slab. Show all posts
Showing posts with label Slab. Show all posts

Tuesday, November 20, 2007

2007-11-20

In a previous post, I mentioned that we need to have goals. I'm going to use Federicos goal of having the App Browser appear <1 second :-) Mission impossible? We will see...

We have numbers now, so it's time to take a closer look at the code. I mentioned that I've cheated and actually done some of this before. Well, I came as far as removing the creation of the context menu for each application. The menu that is added looks like this;



It'd be better to create it if/when a user actually right clicks on the application.

So after removing the code that creates the menu, we end up with the following stats;



Since this optimization business is not as simple as removing code that speed things up, we now need to come up with code to add this menu "on demand".

Sunday, November 18, 2007

2007-11-18

Just a quick post on how I use Git for my experiments.

I don't know if the way I use it is proper. The plan, at the end of the day, is to be able to merge optimized branches back to master, but without the code added in the profiling branch...

Get the latest sources via svn
mboman@mblxtv01:~/dev/gnome-main-menu> svn checkout svn://svn.gnome.org/svn/gnome-main-menu/branches/openSUSE-10.3/ branch-10.3

Create GIT repo
mboman@mblxtv01:~/dev/gnome-main-menu> cd branch-10.3
mboman@mblxtv01:~/dev/gnome-main-menu/branch-10.3> git init
mboman@mblxtv01:~/dev/gnome-main-menu/branch-10.3> git add .

Create a new branch
mboman@mblxtv01:~/dev/gnome-main-menu/branch-10.3> git branch profiling master

Switch to profiling branch
mboman@mblxtv01:~/dev/gnome-main-menu/branch-10.3> git checkout profiling

Add debug code, then commit
mboman@mblxtv01:~/dev/gnome-main-menu/branch-10.3> git commit -a -m "Added/Modified Debug Code"


To actually test the debug code, I created a new clone;

mboman@mblxtv01:~/dev/gnome-main-menu/branch-10.3> cd ..
mboman@mblxtv01:~/dev/gnome-main-menu> git clone branch-10.3 test
mboman@mblxtv01:~/dev/gnome-main-menu> cd test
mboman@mblxtv01:~/dev/gnome-main-menu/test> ./autogen.sh --libexecdir=/usr/lib/gnome-main-menu
mboman@mblxtv01:~/dev/gnome-main-menu/test> make
mboman@mblxtv01:~/dev/gnome-main-menu/test> sudo make install

After each time I did something in the profile branch and commited it;
mboman@mblxtv01:~/dev/gnome-main-menu/test> git pull
mboman@mblxtv01:~/dev/gnome-main-menu/test> make; sudo make install


Once the debug code is added and works as expected, create a new branch to try to optimize something specific.

Create a new branch for optimization test 1 (only create context menu when user right clicks on an application)
mboman@mblxtv01:~/dev/gnome-main-menu/branch-10.3> git branch opt-context-menu profiling
mboman@mblxtv01:~/dev/gnome-main-menu/branch-10.3> git checkout opt-context-menu

Tip: To see which branch you are actually working on;
mboman@mblxtv01:~/dev/gnome-main-menu/branch-10.3> git branch
master
* opt-context-menu
profiling

Saturday, November 17, 2007

2007-11-17

G'day!

To start off, just a disclaimer...
I've not done any GNOME/GTK development ever nor am I very experienced in GUI programming. What I'm hoping to get out of this is; 1) Experience with GNOME/GTK, 2) Experience with debugging and 3) A super fast menu system :-)

And off course, chances are that posts that has nothing to do with Slab finds is way here as well.

So this is my first post about Slab, the new GNOME Main Menu. I'm currently looking at ways to make it perform as it was on drugs.

I will start off by profiling the Application Browser (AB).

In order to improve performance, one should start by profiling the application. At least that's what Federico says, so that is what I will do :-)
After profiling is complete, one needs to decide what to optimize. Again, Federico says that you can't optimize without having goals, and again, I will obey.

I've actually already cheated and done some profiling that I posted on the openSUSE wiki. But for the purpose of this blog, I will start all over :-)

So the first thing to do is to add some debug code. I'm going to use the following (very simple, but yet not very elegant function :-)


void timeCount(char *funcName)
{
struct timeval tv;
gettimeofday(&tv, NULL);
long tms;
int i = 0;
int func = -1;
char *formatted, *str;

tms = tv.tv_sec * 1000 + tv.tv_usec / 1000;

while(lapse[i].last) {
if(!strcmp(funcName, lapse[i].funcName)) {
func = i;
break;
}
i++;
}

if(func == -1)
func = i;

if(!lapse[func].last) {
strcpy(lapse[func].funcName, funcName);
lapse[func].hello = 0;
}

if(!lapse[func].init) {
lapse[func].last = tms;
lapse[func].init = 1;
lapse[func].hello += 1;
str = g_strdup_printf ("MARK: %s: %s Begin", g_get_prgname(), funcName);
}
else {
lapse[func].curtime = (tms-lapse[func].last)+lapse[func].curtime;
lapse[func].init = 0;
str = g_strdup_printf ("MARK: %s: %s End", g_get_prgname(), funcName);
}

access (str, F_OK);
g_free (str);
}


Now I need to add this function to the beginning and end of various functions that I want to profile. I also add an exit statement in the application instead of calling gtk_main(). This allows me to run in batch mode without having to kill AB.

Then I start the application as follows;
strace -ttt -f -o test-strace.log application-browser

Once done, I use plot-timeline.py to generate a pretty picture.

The end result becomes this;



And this (Second column is the number of times the function was called and the third column is the total time spent in that function);

"generate_categories","1","1919"
"generate_categories ==> gmenu_tree_get_root_directory (app_data->tree)","1","854"
"generate_new_apps","1","44"
"layout_shell","1","12"
"create_main_window","1","1374"
"show_shell","1","1361"
"gtk_widget_show_all","1","1361"

After sprinkling some more debug code (and also added the option to not include a specific function in the plot), the result is;



"main","1","0"
"generate_categories","1","2588"
"generate_categories ==> gmenu_tree_get_root_directory (app_data->tree)","1","860"
"generate_category","9","1666"
"generate_launchers","95","762"
"check_specific_apps_hack","154","19"
"insert_launcher_into_category","162","1545"
"application_tile_new_full","162","1130"
"nameplate_tile_class_init","1","0"
"nameplate_tile_constructor","172","117"
"nameplate_tile_init","172","11"
"nameplate_tile_setup","172","41"
"application_tile_setup","162","851"
"themed_icon_new","162","52"
"themed_icon_set_property","324","18"
"nameplate_tile_set_property","678","198"
"themed_icon_show","162","127"
"libslab_get_gconf_value","1","7"
"libslab_gconf_notify_add","1","0"
"libslab_gnome_desktop_item_new_from_unknown_id","13","12"
"application_launcher_compare","3212","193"
"generate_new_apps","1","62"
"layout_shell","1","27"
"app_resizer_new","1","0"
"app_resizer_get_type","24","0"
"app_resizer_class_init","1","0"
"create_application_category_sections","1","13"
"populate_application_category_sections","1","9"
"remove_container_entries","12","1"
"populate_application_category_section","10","8"
"app_resizer_layout_table_default","10","5"
"resize_table","10","2"
"relayout_table","10","3"
"app_resizer_set_table_cache","1","0"
"create_filter_section","1","1"
"create_groups_section","1","0"
"populate_groups_section","1","0"
"create_actions_section","1","0"
"create_main_window","1","1377"
"show_shell","1","1364"
"gtk_widget_show_all","1","1364"
"themed_icon_style_set","162","202"
"app_resizer_size_allocate","3","65"
"relayout_tables_if_needed","2","0"
"calculate_num_cols","2","0"

Running the same as above, but without strace will render completely different numbers. So for the sake of being able to create pretty pictures throughout this exercise, strace will only be used when we need to create a new pretty picture and we can then compare that to what we have above. The numbers below were generated without using strace.

"generate_categories","1","821"
"generate_categories ==> gmenu_tree_get_root_directory (app_data->tree)","1","337"
"generate_category","9","463"
"generate_launchers","95","216"
"check_specific_apps_hack","154","0"
"insert_launcher_into_category","162","453"
"application_tile_new_full","162","400"
"nameplate_tile_class_init","1","0"
"nameplate_tile_constructor","172","53"
"nameplate_tile_init","172","0"
"nameplate_tile_setup","172","29"
"application_tile_setup","162","314"
"themed_icon_new","162","6"
"themed_icon_set_property","324","0"
"nameplate_tile_set_property","678","76"
"themed_icon_show","162","54"
"libslab_get_gconf_value","1","0"
"libslab_gconf_notify_add","1","1"
"libslab_gnome_desktop_item_new_from_unknown_id","13","2"
"application_launcher_compare","3212","2"
"generate_new_apps","1","21"
"layout_shell","1","11"
"app_resizer_new","1","0"
"app_resizer_get_type","24","0"
"app_resizer_class_init","1","0"
"create_application_category_sections","1","6"
"populate_application_category_sections","1","2"
"remove_container_entries","12","0"
"populate_application_category_section","10","1"
"app_resizer_layout_table_default","10","1"
"resize_table","10","0"
"relayout_table","10","1"
"app_resizer_set_table_cache","1","0"
"create_filter_section","1","0"
"create_groups_section","1","1"
"populate_groups_section","1","0"
"create_actions_section","1","0"
"create_main_window","1","1156"
"show_shell","1","1144"
"gtk_widget_show_all","1","1144"
"themed_icon_style_set","162","178"
"app_resizer_size_allocate","3","58"
"relayout_tables_if_needed","2","0"
"calculate_num_cols","2","0"