From 9ed89c17dee752154c36d71cae93d20cccfc71ef Mon Sep 17 00:00:00 2001 From: Berke Güzel Date: Mon, 12 Oct 2026 14:27:51 +0300 Subject: perf: optimize hot-path loops, data structures, and cache locality --- src/common/backend.c | 8 ++++++-- src/common/input.c | 9 +++++++-- src/common/loop.c | 54 ++++++++++++++++++++++++++++++++++------------------ 3 files changed, 49 insertions(+), 22 deletions(-) (limited to 'src/common') diff --git a/src/common/backend.c b/src/common/backend.c index 4c755bd..c8d2caf 100644 --- a/src/common/backend.c +++ b/src/common/backend.c @@ -217,9 +217,13 @@ bool yasl_surface_present(struct yasl_surface *s, const struct yasl_framebuffer fb->size.x <= 0 || fb->size.y <= 0 || damage->n < -1 || damage->n > YASL_DAMAGE_MAX) return false; - struct yasl_damage_list clipped = {.n = damage->n}; - if (damage->n >= 0) { + struct yasl_damage_list clipped; + clipped.n = damage->n; + if (damage->n < 0) { + clipped.bounds = damage->bounds; + } else { clipped.n = 0; + clipped.bounds = (struct yasl_rect2i){0}; for (int i = 0; i < damage->n; i++) { struct yasl_rect2i r = damage->rects[i]; if (r.width < 0 || r.height < 0) return false; diff --git a/src/common/input.c b/src/common/input.c index eac4d1a..ff578e3 100644 --- a/src/common/input.c +++ b/src/common/input.c @@ -53,8 +53,13 @@ bool input_queue_push(struct input_queue *q, const struct yasl_input_event *ev) goto failed; struct yasl_input_event *events = malloc(capacity * sizeof(*events)); if (!events) goto failed; - for (size_t i = 0; i < q->count; i++) - events[i] = q->events[(q->head + i) % q->capacity]; + if (q->events && q->count > 0) { + size_t first = q->capacity - q->head; + if (first > q->count) first = q->count; + memcpy(events, q->events + q->head, first * sizeof(*events)); + if (q->count > first) + memcpy(events + first, q->events, (q->count - first) * sizeof(*events)); + } free(q->events); q->events = events; q->capacity = capacity; diff --git a/src/common/loop.c b/src/common/loop.c index a63df16..18d62b1 100644 --- a/src/common/loop.c +++ b/src/common/loop.c @@ -25,9 +25,9 @@ struct yasl_fd_source { struct yasl_timer_source { yasl_timer_cb fn; void *ud; - yasl_timer_id id; uint64_t interval_ns; uint64_t deadline_ns; + yasl_timer_id id; bool deleted; }; @@ -330,13 +330,18 @@ int yasl_loop_step(struct yasl_loop *l, int timeout_ms) for (int i = 0; i < count; i++) { if (pcopy[i].revents) { short revents = pcopy[i].revents; - // Verify that the source was not deleted by an earlier callback in this step + // Fast-path: check if source is still at index i before linear scan bool valid = false; - for (int j = 0; j < l->count; j++) { - if (l->fds[j].id == scopy[i].id) { - l->pollfds[j].revents = 0; - valid = true; - break; + if (i < l->count && l->fds[i].id == scopy[i].id) { + l->pollfds[i].revents = 0; + valid = true; + } else { + for (int j = 0; j < l->count; j++) { + if (l->fds[j].id == scopy[i].id) { + l->pollfds[j].revents = 0; + valid = true; + break; + } } } if (valid && scopy[i].fn) { @@ -367,18 +372,31 @@ int yasl_loop_step(struct yasl_loop *l, int timeout_ms) uint64_t next_interval = timer_src.fn(ud, tid, interval); handled++; - for (int j = 0; j < l->timer_count; j++) { - if (l->timers[j].id == tid) { - if (next_interval == 0 || l->timers[j].deleted) { - l->timers[j].deleted = true; - } else { - l->timers[j].interval_ns = next_interval; - if (l->timers[j].deadline_ns + next_interval > now) - l->timers[j].deadline_ns += next_interval; - else - l->timers[j].deadline_ns = now + next_interval; + // Fast-path: timer is usually still at index i unless an earlier timer was deleted + if (i < l->timer_count && l->timers[i].id == tid) { + if (next_interval == 0 || l->timers[i].deleted) { + l->timers[i].deleted = true; + } else { + l->timers[i].interval_ns = next_interval; + if (l->timers[i].deadline_ns + next_interval > now) + l->timers[i].deadline_ns += next_interval; + else + l->timers[i].deadline_ns = now + next_interval; + } + } else { + for (int j = 0; j < l->timer_count; j++) { + if (l->timers[j].id == tid) { + if (next_interval == 0 || l->timers[j].deleted) { + l->timers[j].deleted = true; + } else { + l->timers[j].interval_ns = next_interval; + if (l->timers[j].deadline_ns + next_interval > now) + l->timers[j].deadline_ns += next_interval; + else + l->timers[j].deadline_ns = now + next_interval; + } + break; } - break; } } } -- cgit v1.2.3