#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include "yasl/yasl.h" #include "yasl/loop.h" #include "common/loop.h" #include "common/input.h" #if YASL_HAS_WAYLAND #include "wayland/internal.h" #endif static inline uint64_t get_time_ns(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (uint64_t)ts.tv_sec * 1000000000ull + (uint64_t)ts.tv_nsec; } #if YASL_HAS_WAYLAND /* Benchmark 1: Surface Lookup in conn_surface_for */ static void bench_surface_lookup(void) { const int num_surfaces = 16; const int lookups = 10000000; struct wayland_display c = {0}; struct wayland_surface surfaces[num_surfaces]; void *dummy_proxies[num_surfaces][16]; for (int i = 0; i < num_surfaces; i++) { memset(&surfaces[i], 0, sizeof(surfaces[i])); memset(dummy_proxies[i], 0, sizeof(dummy_proxies[i])); surfaces[i].conn = &c; surfaces[i].surface = (struct wl_surface *)dummy_proxies[i]; wl_proxy_set_user_data((struct wl_proxy *)dummy_proxies[i], &surfaces[i]); surfaces[i].conn_next = c.surfaces; c.surfaces = &surfaces[i]; } struct wl_surface *target = (struct wl_surface *)dummy_proxies[0]; uint64_t t0 = get_time_ns(); uintptr_t sum = 0; for (int i = 0; i < lookups; i++) { struct wayland_surface *found = conn_surface_for(&c, target); sum += (uintptr_t)found; } uint64_t t1 = get_time_ns(); printf("[1] conn_surface_for : %7.2f ms (%d lookups over %d surfaces, checksum=%lx)\n", (double)(t1 - t0) / 1e6, lookups, num_surfaces, (unsigned long)sum); } /* Benchmark 2: Wayland Output & Refresh Tracking */ static void bench_output_follow(void) { const int iters = 10000000; struct wayland_display c = {0}; struct wl_conn_output outs[4]; for (int i = 0; i < 4; i++) { memset(&outs[i], 0, sizeof(outs[i])); outs[i].mask = 1ull << i; outs[i].scale = i + 1; outs[i].refresh_ns = 16666666 / (i + 1); outs[i].next = (i < 3) ? &outs[i + 1] : NULL; } c.outputs = &outs[0]; struct wayland_surface w = {0}; w.conn = &c; w.outputs = 0x3; w.pending_scale_120 = 2 * YASL_SCALE_UNIT; w.frac_scale = (struct wp_fractional_scale_v1 *)1; uint64_t t0 = get_time_ns(); for (int i = 0; i < iters; i++) { surface_follow_outputs(&w); } uint64_t t1 = get_time_ns(); printf("[2] surface_follow_outputs : %7.2f ms (%d iterations over outputs list)\n", (double)(t1 - t0) / 1e6, iters); } #endif /* Benchmark 3: Input Queue Resizing Throughput */ static void bench_input_queue_resize(void) { const int batches = 50000; const int size = 2048; uint64_t t0 = get_time_ns(); for (int b = 0; b < batches; b++) { struct input_queue q = {0}; for (int i = 0; i < size; i++) { struct yasl_input_event ev = { .kind = YASL_INPUT_MOUSE, .mouse = { .pos = { .x = i, .y = b } }, }; input_queue_push(&q, &ev); } input_queue_clear(&q); } uint64_t t1 = get_time_ns(); printf("[3] input_queue_resize : %7.2f ms (%d batches x %d events = 102.4M events)\n", (double)(t1 - t0) / 1e6, batches, size); } /* Benchmark 4: Input Queue Push & Pop Throughput */ static void bench_input_queue_push_pop(void) { const int rounds = 20000; const int events_per_round = 500; struct input_queue q = {0}; uint64_t t0 = get_time_ns(); for (int r = 0; r < rounds; r++) { for (int i = 0; i < events_per_round; i++) { struct yasl_input_event ev = { .kind = YASL_INPUT_MOUSE, .mouse = { .pos = { .x = i, .y = r }, .button = 1 }, }; input_queue_push(&q, &ev); } struct yasl_input_event out; while (input_queue_pop(&q, &out)) { /* consume */ } } uint64_t t1 = get_time_ns(); input_queue_clear(&q); printf("[4] input_queue_push_pop : %7.2f ms (%d batches x %d events = 10M events)\n", (double)(t1 - t0) / 1e6, rounds, events_per_round); } /* Benchmark 5: Event Loop Timers Add & Delete */ static uint64_t timer_dummy_cb(void *ud, yasl_timer_id id, uint64_t interval_ns) { (void)ud; (void)id; (void)interval_ns; return 0; } static void bench_timers(void) { const int iters = 2000000; struct yasl_loop *loop = yasl_loop_create(); uint64_t t0 = get_time_ns(); for (int i = 0; i < iters; i++) { yasl_timer_id id = yasl_loop_add_timer(loop, 1000000, timer_dummy_cb, NULL); yasl_loop_del_timer(loop, id); } uint64_t t1 = get_time_ns(); yasl_loop_destroy(loop); printf("[5] timers_add_del : %7.2f ms (%d arm/disarm cycles)\n", (double)(t1 - t0) / 1e6, iters); } int main(void) { printf("==================== YASL Performance Benchmark ====================\n"); #if YASL_HAS_WAYLAND bench_surface_lookup(); bench_output_follow(); #endif bench_input_queue_resize(); bench_input_queue_push_pop(); bench_timers(); printf("====================================================================\n"); return 0; }