From 2a6d5d207d7f51ea8468a396b4ef371160ba3fa4 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Fri, 10 Apr 2009 18:15:48 +0200 Subject: [PATCH] client_stack(): Only stack windows once per mainloop I was creating 2000 wiboxes in a loop (don't ask) and creating them took forever. According to callgrind, there were about 2 million calls to xcb_configure_window() and most (if not all) of them were from client_stack(). Awesome spent 70% of its cpu time in these client_stack() calls. client_stack() is O(N^2) on the number of clients (it walks the list of clients itself twice and each call to client_stack_above() walks the list too) and O(N) on the number of wiboxes (it walks the wibox list twice). So obviously calls to it should be rare. This patch makes client_stack() only set a flag which is later checked. This should reduce the number of restacks to the bare minimum. With this patch, neither xcb_configure_window() nor anything else client_stack() related shows up as having a lot of calls or using much cpu time. Signed-off-by: Uli Schlachter Signed-off-by: Julien Danjou --- client.c | 13 +++++++++++-- client.h | 8 +++++++- event.h | 2 ++ structs.h | 2 ++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/client.c b/client.c index e18686dc..c1ff4437 100644 --- a/client.c +++ b/client.c @@ -344,8 +344,8 @@ client_layer_translator(client_t *c) * \todo It might be worth stopping to restack everyone and only stack `c' * relatively to the first matching in the list. */ -void -client_stack() +static void +client_real_stack(void) { uint32_t config_win_vals[2]; client_node_t *node, *last = *client_node_list_last(&globalconf.stack); @@ -400,6 +400,15 @@ client_stack() } } +void +client_stack_refresh() +{ + if (!globalconf.client_need_stack_refresh) + return; + globalconf.client_need_stack_refresh = false; + client_real_stack(); +} + /** Manage a new client. * \param w The window. * \param wgeom Window geometry. diff --git a/client.h b/client.h index d2cd3e7a..0d28753a 100644 --- a/client.h +++ b/client.h @@ -55,7 +55,6 @@ DO_RCNT(client_t, client, client_delete) bool client_maybevisible(client_t *, int); client_t * client_getbywin(xcb_window_t); -void client_stack(void); void client_ban(client_t *); void client_unban(client_t *); void client_manage(xcb_window_t, xcb_get_geometry_reply_t *, int, bool); @@ -79,6 +78,7 @@ void client_focus(client_t *); void client_focus_update(client_t *); void client_unfocus(client_t *); void client_unfocus_update(client_t *); +void client_stack_refresh(void); int luaA_client_newindex(lua_State *); @@ -86,6 +86,12 @@ int luaA_client_userdata_new(lua_State *, client_t *); DO_SLIST(client_t, client, client_unref) +static inline void +client_stack(void) +{ + globalconf.client_need_stack_refresh = true; +} + /** Put client on top of the stack. * \param c The client to raise. */ diff --git a/event.h b/event.h index d4d26784..9c398843 100644 --- a/event.h +++ b/event.h @@ -26,12 +26,14 @@ #include "wibox.h" #include "layout.h" +#include "client.h" static inline int awesome_refresh(void) { layout_refresh(); wibox_refresh(); + client_stack_refresh(); return xcb_flush(globalconf.connection); } diff --git a/structs.h b/structs.h index 24875ed2..a7d61a09 100644 --- a/structs.h +++ b/structs.h @@ -381,6 +381,8 @@ struct awesome_t luaA_ref mousegrabber; /** Focused screen */ screen_t *screen_focus; + /** Need to call client_stack_refresh() */ + bool client_need_stack_refresh; }; DO_ARRAY(const void *, void, DO_NOTHING)