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 <psychon@znc.in> Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
4b82608952
commit
2a6d5d207d
13
client.c
13
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'
|
* \todo It might be worth stopping to restack everyone and only stack `c'
|
||||||
* relatively to the first matching in the list.
|
* relatively to the first matching in the list.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
client_stack()
|
client_real_stack(void)
|
||||||
{
|
{
|
||||||
uint32_t config_win_vals[2];
|
uint32_t config_win_vals[2];
|
||||||
client_node_t *node, *last = *client_node_list_last(&globalconf.stack);
|
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.
|
/** Manage a new client.
|
||||||
* \param w The window.
|
* \param w The window.
|
||||||
* \param wgeom Window geometry.
|
* \param wgeom Window geometry.
|
||||||
|
|
8
client.h
8
client.h
|
@ -55,7 +55,6 @@ DO_RCNT(client_t, client, client_delete)
|
||||||
|
|
||||||
bool client_maybevisible(client_t *, int);
|
bool client_maybevisible(client_t *, int);
|
||||||
client_t * client_getbywin(xcb_window_t);
|
client_t * client_getbywin(xcb_window_t);
|
||||||
void client_stack(void);
|
|
||||||
void client_ban(client_t *);
|
void client_ban(client_t *);
|
||||||
void client_unban(client_t *);
|
void client_unban(client_t *);
|
||||||
void client_manage(xcb_window_t, xcb_get_geometry_reply_t *, int, bool);
|
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_focus_update(client_t *);
|
||||||
void client_unfocus(client_t *);
|
void client_unfocus(client_t *);
|
||||||
void client_unfocus_update(client_t *);
|
void client_unfocus_update(client_t *);
|
||||||
|
void client_stack_refresh(void);
|
||||||
|
|
||||||
int luaA_client_newindex(lua_State *);
|
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)
|
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.
|
/** Put client on top of the stack.
|
||||||
* \param c The client to raise.
|
* \param c The client to raise.
|
||||||
*/
|
*/
|
||||||
|
|
2
event.h
2
event.h
|
@ -26,12 +26,14 @@
|
||||||
|
|
||||||
#include "wibox.h"
|
#include "wibox.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
|
#include "client.h"
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
awesome_refresh(void)
|
awesome_refresh(void)
|
||||||
{
|
{
|
||||||
layout_refresh();
|
layout_refresh();
|
||||||
wibox_refresh();
|
wibox_refresh();
|
||||||
|
client_stack_refresh();
|
||||||
return xcb_flush(globalconf.connection);
|
return xcb_flush(globalconf.connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -381,6 +381,8 @@ struct awesome_t
|
||||||
luaA_ref mousegrabber;
|
luaA_ref mousegrabber;
|
||||||
/** Focused screen */
|
/** Focused screen */
|
||||||
screen_t *screen_focus;
|
screen_t *screen_focus;
|
||||||
|
/** Need to call client_stack_refresh() */
|
||||||
|
bool client_need_stack_refresh;
|
||||||
};
|
};
|
||||||
|
|
||||||
DO_ARRAY(const void *, void, DO_NOTHING)
|
DO_ARRAY(const void *, void, DO_NOTHING)
|
||||||
|
|
Loading…
Reference in New Issue