GNOME Bugzilla – Bug 94535
slow over remote connection
Last modified: 2004-12-22 21:47:04 UTC
At work, I am able to connect to my linux box at home where I can start remote gtk/gnome applications. I noticed that gtk is clearly not optimized for slow connections. For example, if I open a menu and move the mouse to the last item then the menu items will be slowly enabled and disabled ones by ones potentially showing each submenu. If each item takes 2 to 3 seconds to be processed then I may have to wait 30 seconds or more before the final item is finally selected. I suspect that events are processed by sequentially. A more optimal way would be to queue events and to group them to reduce the number of actions effectively processed. For example, a 'leave widget' event would cancel a previous 'enter widget' event. PS: does anyone know a way to simulate a slow connection on a local system (maybe with Xnest)?
I have been meaning to file this for a long time. Can I commit? --- gtkmenuitem.c 23 Sep 2002 22:46:28 -0000 1.85 +++ gtkmenuitem.c 30 Sep 2002 18:09:32 -0000 @@ -724,7 +724,7 @@ gtk_real_menu_item_select (GtkItem *item } gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_PRELIGHT); - gtk_widget_draw (GTK_WIDGET (menu_item), NULL); + gtk_widget_queue_draw (GTK_WIDGET (menu_item)); } static void @@ -757,7 +757,7 @@ gtk_real_menu_item_deselect (GtkItem *it } gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_NORMAL); - gtk_widget_draw (GTK_WIDGET (menu_item), NULL); + gtk_widget_queue_draw (GTK_WIDGET (menu_item)); } static gboolean
Sure, but: - Are you sure this will help that much? I don't see any round trips, so it won't have an effect on high latency circumstances and it reduces the total amount drawn by only 50%. Fixing latency problems is almost totally a question of looking for the round trips. - Maybe you want to clean up the other couple of gtk_widget_draw() calls in gtk+ while you are at it?
That was a fast reply. If I understand the patch then 2 consecutive draws are replaced by a single draw. This is clearly more efficient than the current behavior but the remaining draw should also be cancelled. Also, I do not think that this patch can prevent submenus to be displayed. Submenus are the killer cases.
Aren't there round trips if the menu has alpha-blended icons next to the items?
I thought gtk_widget_draw() called gdk_flush(), but I see it doesn't. I'll look at the other few calls to gtk_widget_draw(). An idea I just got (it's probably bad, but I'll post it anyway): Maintain a new region in GdkWindow with these properties: - Disjoint with the invalid region - The pixels it covers are valid (ie, they are the same as was previously drawn) It would be used like this: - When idle-exposing, use the union of the invalid region and this new region. - widgets should be able to add and remove stuff from it. Gdk would preserve the invariants. - Expose events would remove the area from this region and add to the invalid region This would allow a widget to "cancel" a draw.
Yeah, that's a bad idea :-). It adds a whole lot of complexity and it would be really hard for a widget to know when it could safely cancel a draw; what if there intervening changes to the font or something? The nice thing about the draw logic in GTK+-2 is it is really simple and straightforward. (Note that gtkmain.c compresses adjacent enter/leave events. But it doesn't actually do any good for menu items since we get motion events betweeenthe enter and the leave.)
The gtk_widget_draw() fixes are in cvs now. Wrt. the submenus, note that current behavior is to pop out if there has been at least 75 ms since last pop-out. This means the first submenu is _always_ popped out immediately (since for the first submenu, there will always have been 75 ms since last submenu pop-out.) The patch in bug 74950 removes this behavior and makes pop-outs much less frequent.
I don't think there is really anything concrete here to work on, so I'm going to close the bug. It will probably help a lot to have the RENDER extension on the target X server if you don't.
The problem is not caused by the performance of the X server but by the latency between the server and the client. Basically, gtk is processing obsolete old X11 events while newer X11 events are already received but are waiting in the queue. I can use an example: You come back from a long trip abroad and you notice that during this period, a friend or yours send you 20 emails asking you to send him a document using the email of different hotels (he is also traveling a lot). So what you do is to read the OLDEST email and send the document to the specified address. A few hours latter, you receive a reply from this hotel telling you that your friend is not anymore in this hotel. So you try the 2nd OLDEST email address and so on. Of course, acting like that is plain stupid. You should have used immediately the email address in the LATEST email. Now if you replace "hotel" by "menu entry", "friend" by "mouse pointer", and "friend email" by "motion event" then you are back to my initial problem. GTK is process obsolete motion events while newer ones are already received (in the event stack).
The reason I recommend RENDER is that if the extension is present, the number of round-trips GTK+ does for particular drawing is much reduced. And round-trips are what kills performance on slow connections. It's very hard for GTK+ to (in general) say that events it receives should be ignored because there is something newer in the queue ... there are all sorts of tricky bugs you can trigger if you start saying that some events don't matter. In some cases, a protocol like VNC can work better than X for remote display because VNC knows that some change had no effect because the bits didn't change in in the end. From GTK+'s point of view, the bits just coincidentally ended up the same. Soeren's fix will probably improve things a bit because it will be doing less drawing, so you won't _see_ the intermediate menu items being drawn, then undrawn. The the draw/undraw will be compressed into a single draw in the unselected state. Getting rid of this single draw is really hard within the GTK+/X model. (On the other hand, performance may appear worse GTK+ will just sit their churning but apparently doing nothing.)