Created
November 2, 2025 21:36
-
-
Save 3dgoose/f488fd06e82beed75acb9b66fe7a0e39 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <SDL2/SDL.h> | |
| #include <pthread.h> | |
| #include <signal.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <time.h> | |
| #include <stdint.h> | |
| static volatile int running = 1; | |
| static size_t pagesz = 4096; | |
| void handle_sig(int sig) { (void)sig; running = 0; } | |
| typedef struct { volatile int *running; } cpu_arg_t; | |
| void *cpu_worker(void *arg) { | |
| cpu_arg_t *a = (cpu_arg_t*)arg; | |
| volatile double x = 0.0; | |
| while (*a->running) { | |
| for (int i = 0; i < 20000; ++i) x += (i*1e-6)+x*1e-7; | |
| } | |
| (void)x; | |
| return NULL; | |
| } | |
| typedef struct { | |
| size_t bytes; | |
| size_t chunk_size; | |
| volatile int *running; | |
| char **store_ptrs; | |
| size_t store_cap; | |
| size_t stored; | |
| } alloc_arg_t; | |
| void *alloc_worker(void *arg) { | |
| alloc_arg_t *a = (alloc_arg_t*)arg; | |
| size_t remaining = a->bytes; | |
| while (remaining > 0 && *a->running) { | |
| size_t this_size = remaining < a->chunk_size ? remaining : a->chunk_size; | |
| char *buf = malloc(this_size); | |
| if (!buf) break; | |
| for (size_t off = 0; off < this_size; off += pagesz) buf[off] = (char)(off & 0xFF); | |
| // store pointer to keep alive | |
| if (a->stored >= a->store_cap) { | |
| size_t newcap = a->store_cap ? a->store_cap * 2 : 256; | |
| char **tmp = realloc(a->store_ptrs, newcap * sizeof(char*)); | |
| if (!tmp) { a->store_ptrs[0] = buf; a->stored = 1; a->store_cap = 1; } | |
| else { a->store_ptrs = tmp; a->store_cap = newcap; } | |
| } | |
| a->store_ptrs[a->stored++] = buf; | |
| remaining -= this_size; | |
| } | |
| return NULL; | |
| } | |
| int main() { | |
| // hardcoded parameters | |
| double gb = 320.0; | |
| int cpu_threads = 24; | |
| int duration = 100; // seconds | |
| pagesz = sysconf(_SC_PAGESIZE); | |
| signal(SIGINT, handle_sig); | |
| signal(SIGTERM, handle_sig); | |
| size_t total_bytes = (size_t)(gb * 1024.0*1024.0*1024.0); | |
| srand((unsigned)time(NULL)); | |
| printf("Running fixed test: %.2f GiB, %d CPU threads, %ds\n", gb, cpu_threads, duration); | |
| // SDL init | |
| if (SDL_Init(SDL_INIT_VIDEO) != 0) fprintf(stderr, "SDL init failed: %s\n", SDL_GetError()); | |
| SDL_Window *win = SDL_CreateWindow("SDL Aggressive Fixed", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN); | |
| SDL_Renderer *ren = win ? SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED) : NULL; | |
| // CPU threads | |
| pthread_t *cthreads = calloc(cpu_threads, sizeof(pthread_t)); | |
| cpu_arg_t *cargs = calloc(cpu_threads, sizeof(cpu_arg_t)); | |
| for (int i = 0; i < cpu_threads; ++i) { cargs[i].running = &running; | |
| pthread_create(&cthreads[i], NULL, cpu_worker, &cargs[i]); | |
| } | |
| // Allocation threads | |
| int alloc_threads = 4; | |
| pthread_t *athreads = calloc(alloc_threads, sizeof(pthread_t)); | |
| alloc_arg_t *aargs = calloc(alloc_threads, sizeof(alloc_arg_t)); size_t per_thread = total_bytes / alloc_threads; | |
| size_t remainder = total_bytes % alloc_threads; | |
| size_t chunk = 256UL*1024UL*1024UL; // 256 MiB chunks | |
| for (int i = 0; i < alloc_threads; ++i) { | |
| size_t mybytes = per_thread + (i==alloc_threads-1 ? remainder : 0); | |
| aargs[i].bytes = mybytes; aargs[i].chunk_size = chunk; | |
| aargs[i].running = &running; | |
| aargs[i].store_ptrs = NULL; | |
| aargs[i].store_cap = 0; | |
| aargs[i].stored = 0; | |
| pthread_create(&athreads[i], NULL, alloc_worker, &aargs[i]); | |
| } | |
| // MAIN LOOP - max FPS, color changes | |
| uint32_t start = SDL_GetTicks(); | |
| while (running) { | |
| if ((SDL_GetTicks()-start) >= (uint32_t)duration*1000U) break; | |
| SDL_Event e; | |
| while(SDL_PollEvent(&e)) {} | |
| if (ren) { | |
| Uint8 r = rand() & 0xFF; | |
| Uint8 g = rand() & 0xFF; | |
| Uint8 b = rand() & 0xFF; | |
| SDL_SetRenderDrawColor(ren,r,g,b,255); | |
| SDL_RenderClear(ren); | |
| SDL_RenderPresent(ren); | |
| } | |
| } | |
| running = 0; | |
| for(int i=0;i<alloc_threads;i++) pthread_join(athreads[i],NULL); | |
| for(int i=0;i<cpu_threads;i++) pthread_join(cthreads[i],NULL); | |
| // free allocated memory | |
| for(int i=0;i<alloc_threads;i++){ | |
| if(aargs[i].store_ptrs){ | |
| for(size_t j=0;j<aargs[i].stored;j++) free(aargs[i].store_ptrs[j]); | |
| free(aargs[i].store_ptrs); | |
| } | |
| } | |
| if(ren) SDL_DestroyRenderer(ren); | |
| if(win) SDL_DestroyWindow(win); | |
| SDL_Quit(); | |
| free(cthreads); free(cargs); free(athreads); free(aargs); | |
| printf("Finished cleanly.\n"); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment