sergio/takana
> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…
⎇ 84e3737e10e17927380ed3e232e50cebfdd39123
docs/evidencia/tasas-kernel-2026-08-29/bench_pin.c
Historia
Quién tocó qué
crudo
SDD 25: las tasas del kernel medidas, y el MEMCG que falta en las recetas
1/* bench_pin.c — mismas medidas, PINNEADAS a un cpu, para sacar la cola del scheduler
2 * de en medio y dejar ver el efecto puro. */
3#define _GNU_SOURCE
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <unistd.h>
8#include <time.h>
9#include <sched.h>
10#include <pthread.h>
11#include <spawn.h>
12#include <sys/wait.h>
13#include <sys/mman.h>
14extern char **environ;
15static inline double now_ns(void){ struct timespec t; clock_gettime(CLOCK_MONOTONIC,&t); return t.tv_sec*1e9+t.tv_nsec; }
16static int cmpd(const void*a,const void*b){ double x=*(const double*)a,y=*(const double*)b; return (x>y)-(x<y); }
17#define R 9
18static void rep(const char*n,double*r){ qsort(r,R,sizeof(double),cmpd); printf("%-46s %9.1f %9.1f\n",n,r[0],r[R/2]); fflush(stdout); }
19static void pin(int c){ cpu_set_t s; CPU_ZERO(&s); CPU_SET(c,&s); sched_setaffinity(0,sizeof s,&s); }
20static char *area; static long asz;
21static void grow(long mb){ if(area)munmap(area,asz); asz=mb*1024L*1024; if(!mb){area=0;return;}
22 area=mmap(0,asz,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
23 madvise(area,asz,MADV_NOHUGEPAGE); for(long o=0;o<asz;o+=4096) area[o]=1; }
24static void* nada(void*p){ (void)p; return 0; }
25int main(int argc,char**argv){
26 pin(2);
27 const char *sta=argc>1?argv[1]:"/bin/true", *dyn=argc>2?argv[2]:"/bin/true", *mus=argc>3?argv[3]:sta;
28 printf("%-46s %9s %9s\n","BENCH (us/op), PINNEADO a 1 cpu","min","mediana");
29 printf("--- fork vs espacio de direcciones del padre ---\n");
30 long mbs[]={0,64,256};
31 for(unsigned k=0;k<3;k++){ grow(mbs[k]); double a[R],b[R]; char n[90];
32 for(int q=0;q<R;q++){ double t0=now_ns(); for(int i=0;i<120;i++){pid_t p=fork(); if(!p)_exit(0); int st;waitpid(p,&st,0);} a[q]=(now_ns()-t0)/120/1000; }
33 for(int q=0;q<R;q++){ double t0=now_ns(); for(int i=0;i<120;i++){pid_t p;char*ar[]={(char*)sta,0}; if(!posix_spawn(&p,sta,0,0,ar,environ)){int st;waitpid(p,&st,0);}} b[q]=(now_ns()-t0)/120/1000; }
34 snprintf(n,sizeof n," padre %3ld MB: fork+_exit+wait",mbs[k]); rep(n,a);
35 snprintf(n,sizeof n," padre %3ld MB: posix_spawn+wait (estatico)",mbs[k]); rep(n,b); }
36 grow(0);
37 printf("--- tasa del enlazador dinamico (misma libc: glibc) ---\n");
38 { double r[R];
39 for(int q=0;q<R;q++){ double t0=now_ns(); for(int i=0;i<150;i++){pid_t p;char*a[]={(char*)sta,0};if(!posix_spawn(&p,sta,0,0,a,environ)){int st;waitpid(p,&st,0);}} r[q]=(now_ns()-t0)/150/1000; } rep(" exec glibc ESTATICO",r);
40 for(int q=0;q<R;q++){ double t0=now_ns(); for(int i=0;i<150;i++){pid_t p;char*a[]={(char*)dyn,0};if(!posix_spawn(&p,dyn,0,0,a,environ)){int st;waitpid(p,&st,0);}} r[q]=(now_ns()-t0)/150/1000; } rep(" exec glibc DINAMICO",r);
41 for(int q=0;q<R;q++){ double t0=now_ns(); for(int i=0;i<150;i++){pid_t p;char*a[]={(char*)mus,0};if(!posix_spawn(&p,mus,0,0,a,environ)){int st;waitpid(p,&st,0);}} r[q]=(now_ns()-t0)/150/1000; } rep(" exec musl ESTATICO",r); }
42 printf("--- hilo vs proceso ---\n");
43 { double r[R]; for(int q=0;q<R;q++){ double t0=now_ns(); for(int i=0;i<2000;i++){pthread_t t;pthread_create(&t,0,nada,0);pthread_join(t,0);} r[q]=(now_ns()-t0)/2000/1000; } rep(" pthread_create+join",r); }
44 printf("--- fallos de pagina, 64MB (defrag=madvise) ---\n");
45 { const long SZ=64L<<20; double r[R]; long pg=SZ/4096;
46 for(int q=0;q<R;q++){ char*m=mmap(0,SZ,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0); madvise(m,SZ,MADV_HUGEPAGE);
47 double t0=now_ns(); for(long o=0;o<SZ;o+=4096)m[o]=1; r[q]=(now_ns()-t0)/pg*1000; munmap(m,SZ);} rep(" MADV_HUGEPAGE (ns/pagina 4K)",r);
48 for(int q=0;q<R;q++){ char*m=mmap(0,SZ,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0); madvise(m,SZ,MADV_NOHUGEPAGE);
49 double t0=now_ns(); for(long o=0;o<SZ;o+=4096)m[o]=1; r[q]=(now_ns()-t0)/pg*1000; munmap(m,SZ);} rep(" MADV_NOHUGEPAGE (ns/pagina 4K)",r);
50 for(int q=0;q<R;q++){ double t0=now_ns(); char*m=mmap(0,SZ,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE,-1,0);
51 for(long o=0;o<SZ;o+=4096)m[o]=1; r[q]=(now_ns()-t0)/pg*1000; munmap(m,SZ);} rep(" MAP_POPULATE (ns/pagina 4K)",r); }
52 return 0;
53}