#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include "yasl/yasl.h" #include "yasl/loop.h" #include "yasl/timing.h" #include "yasl/native.h" #include "common/input.h" #if YASL_HAS_WAYLAND #include "yasl/native/wayland.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: Public Wayland Surface Handle Lookup */ static void bench_surface_lookup(void) { const int num_surfaces = 16; const int lookups = 10000000; struct yasl_display_spec spec = { .app_id = "org.yasl.benchmark", .backend = YASL_BACKEND_WAYLAND, }; struct yasl_display *d = yasl_display_open(NULL, &spec); struct yasl_surface *surfaces[num_surfaces]; memset(surfaces, 0, sizeof(surfaces)); if (d) { for (int i = 0; i < num_surfaces; i++) { struct yasl_surface_spec sspec = { .title = "Benchmark", .size = { .x = 320, .y = 240 }, }; surfaces[i] = yasl_surface_create_toplevel(d, &sspec); } } uint64_t t0 = get_time_ns(); uintptr_t sum = 0; for (int i = 0; i < lookups; i++) { struct wl_surface *found = yasl_wayland_surface_get_wl_surface(surfaces[i % num_surfaces]); sum += (uintptr_t)found; } uint64_t t1 = get_time_ns(); printf("[1] wayland_surface_lookup : %7.2f ms (%d lookups over %d surfaces, checksum=%lx)\n", (double)(t1 - t0) / 1e6, lookups, num_surfaces, (unsigned long)sum); if (d) { for (int i = 0; i < num_surfaces; i++) { if (surfaces[i]) yasl_surface_destroy(surfaces[i]); } yasl_display_close(d); } } /* Benchmark 2: Public Surface Geometry & Refresh Timing */ static void bench_output_follow(void) { const int iters = 10000000; struct yasl_display_spec spec = { .app_id = "org.yasl.benchmark", .backend = YASL_BACKEND_WAYLAND, }; struct yasl_display *d = yasl_display_open(NULL, &spec); struct yasl_surface *s = NULL; if (d) { struct yasl_surface_spec sspec = { .title = "Benchmark", .size = { .x = 320, .y = 240 }, }; s = yasl_surface_create_toplevel(d, &sspec); } uint64_t t0 = get_time_ns(); uint64_t sum = 0; for (int i = 0; i < iters; i++) { struct yasl_geometry geom = yasl_surface_geometry(s); struct yasl_timing timing = yasl_surface_timing(s); int dev = yasl_scale_to_device(320.0, geom.scale_120); sum += (uint64_t)dev + timing.refresh_ns; } uint64_t t1 = get_time_ns(); printf("[2] surface_geometry_timing : %7.2f ms (%d iterations, checksum=%llu)\n", (double)(t1 - t0) / 1e6, iters, (unsigned long long)sum); if (s) yasl_surface_destroy(s); if (d) yasl_display_close(d); } #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; }