perf(wave2): dynamic config arrays, flat dwindle tree, dual client arrays

Wave 2 changes:
- Dynamic Config arrays with geometric growth (cap=16, 2x growth)
  → saves ~2.5 MB heap for typical configs vs fixed 128-entry arrays
- Proper deep-copy protocol in on_config_reload/do_reload (free old, move new, zero source)
- Flat DwindleTree array with int children[2]/parent indices
  → eliminates pointer chasing, contiguous allocation, iterative two-pass recalc
- Lazy per-tag allocation (DwindleTree.nodes starts NULL, allocates on first use)
- Dual client_arr + fstack_arr arrays alongside wl_list/fstack for cache-friendly iteration
  → arrange() and focustop() use array scan instead of linked-list pointer chase
- All arrays maintain size-tracking (nclients, nfstack) for bounds checking
- Zero-warning build with clang -Werror -Wpedantic
This commit is contained in:
2026-07-02 23:50:43 -04:00
parent fb0f49e861
commit 7f3cad8cb6
6 changed files with 323 additions and 275 deletions
+26 -14
View File
@@ -5,10 +5,8 @@
#include <wlr/types/wlr_session_lock_v1.h>
#include "wlr_ext_workspace_v1.h"
/* forward declarations */
struct Client;
struct LayerSurface;
typedef struct DwindleNode DwindleNode;
#ifndef TAGCOUNT
#define TAGCOUNT 9
@@ -21,15 +19,30 @@ typedef struct {
void (*arrange)(Monitor *);
} Layout;
/* Cold state — accessed only on layout changes, not every frame.
* Allocated lazily on first dwindle/master layout use. */
struct DwindleNode {
int children[2];
int parent;
struct Client *client;
struct wlr_box box;
float split_ratio;
int split_top;
int is_node;
};
typedef struct DwindleNode DwindleNode;
typedef struct {
struct DwindleNode *nodes;
int node_count;
int node_cap;
} DwindleTree;
typedef struct MonitorCold {
const Layout *lt[TAGCOUNT][2];
unsigned int sellt[TAGCOUNT];
float mfact;
int nmaster;
char ltsymbol[TAGCOUNT][16];
DwindleNode *dwindle_root[TAGCOUNT];
DwindleTree dwindle_tree[TAGCOUNT];
struct Client *dwindle_focus[TAGCOUNT];
struct Client *master_master[TAGCOUNT];
int master_side[TAGCOUNT];
@@ -39,23 +52,22 @@ struct Monitor {
struct wl_list link;
struct wlr_output *wlr_output;
struct wlr_scene_output *scene_output;
struct wlr_scene_rect *fullscreen_bg; /* See createmon() for info */
struct wlr_scene_rect *fullscreen_bg;
struct wl_listener frame;
struct wl_listener destroy;
struct wl_listener request_state;
struct wl_listener destroy_lock_surface;
struct wlr_session_lock_surface_v1 *lock_surface;
struct wlr_box m; /* monitor area, layout-relative */
struct wlr_box w; /* window area, layout-relative */
struct wl_list layers[4]; /* LayerSurface.link */
struct MonitorCold *cold; /* lazy-allocated layout state */
struct wlr_box m;
struct wlr_box w;
struct wl_list layers[4];
struct MonitorCold *cold;
int gaps;
unsigned int seltags;
struct wlr_ext_workspace_group_handle_v1 *ext_group;
uint32_t tagset[2];
int asleep;
int scratchpad_visible; /* whether scratchpad is shown */
struct Client *scratchpad_prev_focus; /* client focused before scratchpad opened */
struct Client *scratchpad_current; /* currently visible scratchpad client */
int scratchpad_visible;
struct Client *scratchpad_prev_focus;
struct Client *scratchpad_current;
};