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
+3 -23
View File
@@ -3,40 +3,20 @@
#include "monitor.h"
#include "client.h"
/* dwindle binary tree node */
struct DwindleNode {
DwindleNode *children[2];
DwindleNode *parent;
Client *client;
struct wlr_box box;
float split_ratio;
int split_top;
int is_node;
};
/* layout table and count */
extern const Layout layouts[];
extern const unsigned int layout_count;
/* layout entry points (called via Layout.arrange function pointer) */
void dwindle(Monitor *m);
void master(Monitor *m);
void monocle(Monitor *m);
/* helpers used across modules */
[[nodiscard]] int current_tag_idx(Monitor *m);
[[nodiscard]] const Layout *curlayout(Monitor *m);
void ensure_cold(Monitor *m);
/* dwindle tree helpers (exposed for swapdir) */
[[nodiscard]] DwindleNode *dwindle_find_leaf(DwindleNode *n, Client *c);
void dwindle_recalc(DwindleNode *n, int gap);
/* lifecycle helpers (called from peachwm.c unmap/cleanup) */
void dwindle_free_tree(DwindleNode *n);
[[nodiscard]] int dwindle_find_leaf(const DwindleTree *tree, Client *c);
void dwindle_recalc(DwindleTree *tree, int gap);
void dwindle_free_tree(DwindleTree *tree);
void dwindle_remove_client(Client *c);
void master_remove_client(Client *c);
/* tile drag swap (called from buttonpress handler) */
void swaptiled(Client *a, Client *b);