summaryrefslogtreecommitdiff
path: root/src/hist_view.c
diff options
context:
space:
mode:
authorBerke Güzel <wenekar1@gmail.com>2026-10-13 13:54:10 +0300
committerBerke Güzel <wenekar1@gmail.com>2026-10-13 13:54:10 +0300
commit274abc013e4b914b005191a7f74eaf2961a1e59e (patch)
tree1b515d6869cf8f63c5373b471c0c1b83a2da4e53 /src/hist_view.c
parent4741f7a6dfa144ce65cf3bbdd4a1bc6bee6df2e5 (diff)
Optimize loops and data structures in hist.c and hist_view.c
- Unroll fast paths in put_varint and get_varint - Replace while capacity loop with branchless term_grow_cap in runs_reserve - Vectorize continuation ring rehash with slice memcpy in cont_push - Fast-check simple line runs using combined bitwise XOR-OR mask in evict_simple_run - Resume batch simple-run eviction on interrupted sweeps in evict_for - Eliminate unused page_rows and page_simple allocations (>320 KB heap saved) - Add zero-delta bypass in Fenwick tree set_count - Replace iterative capacity loop with branchless term_next_pow2_32 in hist_view_sync - Eliminate prefix-walk in term_hist_view_find_row by reusing Fenwick remainder - Simplify upward and downward viewport movement in term_hist_view_scroll
Diffstat (limited to 'src/hist_view.c')
-rw-r--r--src/hist_view.c63
1 files changed, 34 insertions, 29 deletions
diff --git a/src/hist_view.c b/src/hist_view.c
index d413c43..29eac35 100644
--- a/src/hist_view.c
+++ b/src/hist_view.c
@@ -40,6 +40,8 @@ static void set_count(struct hist_view *v, uint64_t id, uint32_t count)
{
uint32_t slot = (uint32_t)id & (v->cap - 1);
int64_t delta = (int64_t)count - v->counts[slot];
+ if (!delta)
+ return;
v->counts[slot] = count;
v->total_rows = (uint64_t)((int64_t)v->total_rows + delta);
for (uint32_t i = slot + 1; i <= v->cap; i += i & -i)
@@ -66,12 +68,11 @@ bool term_hist_view_sync(struct hist_view *v, const struct hist *h, int cols)
rebuild = changed > v->cap / 4;
}
if (h->lines > v->cap || !v->cap) {
- uint32_t cap = 16;
- while (cap < h->lines) {
- if (cap >= UINT32_MAX / 2)
- return false;
- cap *= 2;
- }
+ if (h->lines > (UINT32_C(1) << 31))
+ return false;
+ uint32_t cap = term_next_pow2_32(h->lines < 16 ? 16 : h->lines);
+ if (cap == UINT32_MAX)
+ return false;
uint64_t *tree = calloc((size_t)cap + 1, sizeof(*tree));
uint32_t *counts = calloc(cap, sizeof(*counts));
if (!tree || !counts) {
@@ -91,15 +92,14 @@ bool term_hist_view_sync(struct hist_view *v, const struct hist *h, int cols)
memset(v->fenwick, 0, ((size_t)v->cap + 1) * sizeof(*v->fenwick));
for (uint64_t id = first; id < end; id++)
v->counts[(uint32_t)id & (v->cap - 1)] = (uint32_t)term_hist_line_estimate(h, id, cols);
- v->total_rows = 0;
/* Build all tree nodes in one pass. */
for (uint32_t i = 1; i <= v->cap; i++) {
v->fenwick[i] += v->counts[i - 1];
- v->total_rows += v->counts[i - 1];
uint32_t parent = i + (i & -i);
if (parent <= v->cap)
v->fenwick[parent] += v->fenwick[i];
}
+ v->total_rows = v->fenwick[v->cap];
} else {
for (uint64_t id = v->first_id; id < first; id++)
set_count(v, id, 0);
@@ -140,25 +140,28 @@ uint64_t term_hist_view_rows(const struct hist_view *v, const struct hist *h, in
/* Rows of the retained lines before id, in logical order. */
static uint64_t before(const struct hist_view *v, uint64_t id)
{
+ if (id <= v->first_id)
+ return 0;
uint32_t start = (uint32_t)v->first_id & (v->cap - 1);
- uint64_t n = id - v->first_id;
- uint32_t stop = start + (uint32_t)n;
+ uint32_t stop = start + (uint32_t)(id - v->first_id);
+ uint64_t p_start = prefix(v, start);
if (stop <= v->cap)
- return prefix(v, stop) - prefix(v, start);
- return prefix(v, v->cap) - prefix(v, start) + prefix(v, stop - v->cap);
+ return prefix(v, stop) - p_start;
+ return v->total_rows - p_start + prefix(v, stop - v->cap);
}
/* Physical slot of a row in tree order. */
-static uint32_t select_slot(const struct hist_view *v, uint64_t row)
+static uint32_t select_slot(const struct hist_view *v, uint64_t row, int *seg)
{
uint32_t slot = 0;
- for (uint32_t bit = v->cap; bit; bit >>= 1) {
+ for (uint32_t bit = v->cap >> 1; bit; bit >>= 1) {
uint32_t next = slot + bit;
- if (next <= v->cap && v->fenwick[next] <= row) {
+ if (v->fenwick[next] <= row) {
row -= v->fenwick[next];
slot = next;
}
}
+ *seg = (int)row;
return slot;
}
@@ -186,9 +189,8 @@ bool term_hist_view_find_row(const struct hist_view *v, const struct hist *h, in
uint32_t start = (uint32_t)v->first_id & (v->cap - 1);
uint64_t low = prefix(v, start), high = total - low;
uint64_t physical = (uint64_t)row < high ? low + row : (uint64_t)row - high;
- uint32_t slot = select_slot(v, physical);
+ uint32_t slot = select_slot(v, physical, seg);
*id = v->first_id + ((slot - start) & (v->cap - 1));
- *seg = (int)(physical - prefix(v, slot));
return true;
}
@@ -292,18 +294,21 @@ void term_hist_view_scroll(struct hist_view *v, const struct hist *h, int cols,
seg = term_hist_line_rows(h, id, cols);
}
seg -= (int64_t)lines;
- while (seg < 0 && id > hist_first_id(h))
- seg += term_hist_line_rows(h, --id, cols);
- if (seg < 0)
- seg = 0;
- for (;;) {
- int count = term_hist_line_rows(h, id, cols);
- if (seg < count)
- break;
- seg -= count;
- if (++id == hist_end_id(h)) {
- term_hist_view_reset_bottom(v);
- return;
+ if (lines > 0) {
+ while (seg < 0 && id > hist_first_id(h))
+ seg += term_hist_line_rows(h, --id, cols);
+ if (seg < 0)
+ seg = 0;
+ } else {
+ for (;;) {
+ int count = term_hist_line_rows(h, id, cols);
+ if (seg < count)
+ break;
+ seg -= count;
+ if (++id == hist_end_id(h)) {
+ term_hist_view_reset_bottom(v);
+ return;
+ }
}
}
v->anchor = (struct view_anchor){ .line_id = id, .seg = (uint32_t)seg,