From 849c041446deb004de5e53f066eecb152930a4cd Mon Sep 17 00:00:00 2001 From: Sergio Date: Sat, 29 Aug 2026 19:31:48 +0000 Subject: [PATCH] =?UTF-8?q?tasas:=20los=204=20experimentos=20que=20=C2=A79?= =?UTF-8?q?=20dej=C3=B3=20nombrados,=20medidos=20con=20root?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SDD 25 §9 listó seis experimentos que no se pudieron correr y por qué. Cuatro de ellos sólo pedían privilegios, y esta sesión los tuvo. Programas y salidas crudas en docs/evidencia/tasas-kernel-2026-08-29/. 1. proc connector (bench_connector.c) — el sondeo de /proc no es lento, es CIEGO: 200 procesos de vida mínima lanzados uno cada 10 ms, sondeando cada 100 ms se ven **0 de 200**; por connector, **200 de 200**. Y esperar el evento no cuesta nada frente a waitpid (116,0 vs 114,8 µs, dentro del ruido), con 0 eventos perdidos en 1400. Sorpresa: taskstats por genetlink **no es más rápido** que parsear /proc/self/stat (2 688 vs 2 697 ns). Su valor es el CONTENIDO (delay accounting), no la velocidad. 2. reflink (bench_reflink.c) — el «copiar en O(1)» existe y NO está en ext4: FICLONE no soportado, y copy_file_range ≈ read+write (13,7 vs 14,5 ms). En xfs y btrfs es PLANO: 64 MiB en 0,010 ms y 512 MiB —ocho veces más— en 0,020 ms, contra 512,7 ms de read+write. **25 600× a 512 MiB.** 3. io_uring SQPOLL (bench_sqpoll.c) — no rescata el veredicto de T12: sobre datos cacheados pierde igual. ext4: pread 554 ns < io_uring 618 < SQPOLL 868. tmpfs: pread 749 < SQPOLL 1 409 < io_uring 2 030 (ahí sí mejora al io_uring normal, 1,4×, pero sigue perdiendo contra la syscall). Y se come un core. 4. syscalls por invocación de compilador — con el strace DEL PROPIO CORPUS (store/3c1fd8c0…-strace), que es la respuesta a «no hay strace en esta máquina». gcc: 1 803 syscalls por un `-c` trivial, **1 095 con error (61%), 919 de ellas readlink** — la canonicalización de rutas, que T8 no medía. Pero al piso de 78,7 ns son 0,14 ms sobre 30,5 ms de compilado: **el cruce al kernel es el 0,5%**. La tormenta de rutas vale milisegundos, no minutos. Condiciones distintas a la corrida original (load ~1,3 sobre 4 vCPU contra 7,3) ⇒ los absolutos NO se comparan entre corridas, sólo los cocientes dentro de una. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01ACUcwo9mZsE5ocYVE9npih --- .../tasas-kernel-2026-08-29/bench_connector.c | 312 ++++++++++++++++++ .../tasas-kernel-2026-08-29/bench_reflink.c | 106 ++++++ .../tasas-kernel-2026-08-29/bench_sqpoll.c | 112 +++++++ .../tasas-kernel-2026-08-29/connector.txt | 20 ++ .../tasas-kernel-2026-08-29/reflink.txt | 34 ++ .../tasas-kernel-2026-08-29/sqpoll.txt | 13 + .../syscalls-compilador.txt | 126 +++++++ 7 files changed, 723 insertions(+) create mode 100644 docs/evidencia/tasas-kernel-2026-08-29/bench_connector.c create mode 100644 docs/evidencia/tasas-kernel-2026-08-29/bench_reflink.c create mode 100644 docs/evidencia/tasas-kernel-2026-08-29/bench_sqpoll.c create mode 100644 docs/evidencia/tasas-kernel-2026-08-29/connector.txt create mode 100644 docs/evidencia/tasas-kernel-2026-08-29/reflink.txt create mode 100644 docs/evidencia/tasas-kernel-2026-08-29/sqpoll.txt create mode 100644 docs/evidencia/tasas-kernel-2026-08-29/syscalls-compilador.txt diff --git a/docs/evidencia/tasas-kernel-2026-08-29/bench_connector.c b/docs/evidencia/tasas-kernel-2026-08-29/bench_connector.c new file mode 100644 index 00000000..cd57516e --- /dev/null +++ b/docs/evidencia/tasas-kernel-2026-08-29/bench_connector.c @@ -0,0 +1,312 @@ +/* bench_connector.c — proc connector (netlink) y taskstats contra sondear /proc. + * + * Cierra el experimento 1 de SDD 25 §9, que quedo sin medir por falta de CAP_NET_ADMIN. + * Requiere root. Tres fases: + * A. LATENCIA fork+_exit+waitpid vs fork+_exit+esperar el evento del connector. + * B. CEGUERA procesos cortos vistos por el connector vs vistos sondeando /proc cada 100 ms. + * C. TASKSTATS una consulta binaria por genetlink vs parsear /proc//stat. + * + * Se compila con: cc -O2 -o bench_connector bench_connector.c + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static volatile long sink; +static inline double now_ns(void){ struct timespec t; clock_gettime(CLOCK_MONOTONIC,&t); return t.tv_sec*1e9+t.tv_nsec; } +static int cmpd(const void*a,const void*b){ double x=*(const double*)a,y=*(const double*)b; return (x>y)-(xdata; +} + +/* Vacia lo que haya en el socket sin bloquear. */ +static void cn_drain(int s){ + int fl=fcntl(s,F_GETFL,0); fcntl(s,F_SETFL,fl|O_NONBLOCK); + char b[4096]; while(recv(s,b,sizeof b,0)>0){} + fcntl(s,F_SETFL,fl); +} + +static void fase_a(int s){ + printf("\n### A. Latencia de notificacion: waitpid contra evento del connector\n"); + printf("%-44s %10s %10s\n","BENCH (ns por proceso)","min","mediana"); + const long N=200; + + double r[ROUNDS]; + for(int q=0;qlim){ perdidos++; break; } + struct pollfd pf={.fd=s,.events=POLLIN}; + if(poll(&pf,1,50)<=0) continue; + struct proc_event *e=cn_read(s,buf,sizeof buf); + if(!e) continue; + if(e->what==PROC_EVENT_EXIT && e->event_data.exit.process_pid==p) break; + } + int st; waitpid(p,&st,0); + } + r[q]=(now_ns()-t0)/(double)N; + } + report("fork+_exit+esperar EXIT del connector",r,ROUNDS,N); + printf("eventos EXIT que no llegaron en 200 ms: %ld de %ld\n",perdidos,(long)N*ROUNDS); +} + +/* ---------------------------------------------------------------- ceguera del sondeo */ + +#define BURST 200 /* procesos cortos */ +#define SPACING_US 10000 /* uno cada 10 ms => 2 s de rafaga */ +#define POLL_MS 100 /* periodo del sondeo, generoso: un supervisor real no baja de aca */ + +/* Lanza BURST hijos que viven lo minimo, y escribe sus pids por el pipe. */ +static void spawner(int wfd){ + for(int i=0;id_name[0]<'0'||e->d_name[0]>'9') continue; + pid_t p=(pid_t)atol(e->d_name); + if(nvwhat==PROC_EVENT_EXIT){ + pid_t p=e->event_data.exit.process_pid; + if(nv su CPU es cota superior. Lo que cuenta: COBERTURA.\n"); +} + +/* ---------------------------------------------------------------- taskstats */ + +static int genl_family(int s,const char *name){ + struct { struct nlmsghdr n; struct genlmsghdr g; char buf[256]; } req; + memset(&req,0,sizeof req); + req.n.nlmsg_type=GENL_ID_CTRL; req.n.nlmsg_flags=NLM_F_REQUEST; req.n.nlmsg_seq=1; req.n.nlmsg_pid=getpid(); + req.g.cmd=CTRL_CMD_GETFAMILY; req.g.version=1; + struct nlattr *a=(struct nlattr*)req.buf; + a->nla_type=CTRL_ATTR_FAMILY_NAME; a->nla_len=NLA_HDRLEN+strlen(name)+1; + strcpy((char*)a+NLA_HDRLEN,name); + req.n.nlmsg_len=NLMSG_LENGTH(GENL_HDRLEN)+NLA_ALIGN(a->nla_len); + if(send(s,&req,req.n.nlmsg_len,0)<0) return -1; + + char rb[4096]; ssize_t r=recv(s,rb,sizeof rb,0); + if(r<0) return -1; + struct nlmsghdr *nh=(struct nlmsghdr*)rb; + if(nh->nlmsg_type==NLMSG_ERROR) return -1; + struct nlattr *na=(struct nlattr*)((char*)NLMSG_DATA(nh)+GENL_HDRLEN); + int len=NLMSG_PAYLOAD(nh,0)-GENL_HDRLEN; + while(len>0){ + if(na->nla_type==CTRL_ATTR_FAMILY_ID) return *(__u16*)((char*)na+NLA_HDRLEN); + len-=NLA_ALIGN(na->nla_len); + na=(struct nlattr*)((char*)na+NLA_ALIGN(na->nla_len)); + } + return -1; +} + +static int ts_query(int s,int fam,pid_t pid,unsigned long long *cpu_ns){ + struct { struct nlmsghdr n; struct genlmsghdr g; char buf[128]; } req; + memset(&req,0,sizeof req); + req.n.nlmsg_type=fam; req.n.nlmsg_flags=NLM_F_REQUEST; req.n.nlmsg_seq=2; req.n.nlmsg_pid=getpid(); + req.g.cmd=TASKSTATS_CMD_GET; req.g.version=TASKSTATS_VERSION; + struct nlattr *a=(struct nlattr*)req.buf; + a->nla_type=TASKSTATS_CMD_ATTR_PID; a->nla_len=NLA_HDRLEN+sizeof(__u32); + *(__u32*)((char*)a+NLA_HDRLEN)=pid; + req.n.nlmsg_len=NLMSG_LENGTH(GENL_HDRLEN)+NLA_ALIGN(a->nla_len); + if(send(s,&req,req.n.nlmsg_len,0)<0) return -1; + + char rb[8192]; ssize_t r=recv(s,rb,sizeof rb,0); + if(r<0) return -1; + struct nlmsghdr *nh=(struct nlmsghdr*)rb; + if(nh->nlmsg_type==NLMSG_ERROR) return -1; + struct nlattr *na=(struct nlattr*)((char*)NLMSG_DATA(nh)+GENL_HDRLEN); + int len=NLMSG_PAYLOAD(nh,0)-GENL_HDRLEN; + while(len>0){ + if(na->nla_type==TASKSTATS_TYPE_AGGR_PID || na->nla_type==TASKSTATS_TYPE_AGGR_TGID){ + struct nlattr *in=(struct nlattr*)((char*)na+NLA_HDRLEN); + int il=na->nla_len-NLA_HDRLEN; + while(il>0){ + if(in->nla_type==TASKSTATS_TYPE_STATS){ + struct taskstats *ts=(struct taskstats*)((char*)in+NLA_HDRLEN); + *cpu_ns=ts->ac_utime*1000ULL+ts->ac_stime*1000ULL; + return 0; + } + il-=NLA_ALIGN(in->nla_len); + in=(struct nlattr*)((char*)in+NLA_ALIGN(in->nla_len)); + } + } + len-=NLA_ALIGN(na->nla_len); + na=(struct nlattr*)((char*)na+NLA_ALIGN(na->nla_len)); + } + return -1; +} + +static void fase_c(void){ + printf("\n### C. Estadisticas de UNA tarea: taskstats binario contra /proc de texto\n"); + int s=socket(PF_NETLINK,SOCK_DGRAM|SOCK_CLOEXEC,NETLINK_GENERIC); + if(s<0){ printf("taskstats: sin socket genetlink (%s)\n",strerror(errno)); return; } + struct sockaddr_nl a; memset(&a,0,sizeof a); a.nl_family=AF_NETLINK; a.nl_pid=getpid(); + if(bind(s,(struct sockaddr*)&a,sizeof a)<0){ printf("taskstats: bind (%s)\n",strerror(errno)); close(s); return; } + int fam=genl_family(s,TASKSTATS_GENL_NAME); + if(fam<0){ printf("taskstats: la familia %s no esta (kernel sin TASKSTATS)\n",TASKSTATS_GENL_NAME); close(s); return; } + unsigned long long ns=0; + if(ts_query(s,fam,getpid(),&ns)<0){ printf("taskstats: la consulta fallo (%s)\n",strerror(errno)); close(s); return; } + printf("familia TASKSTATS = %d, cpu de este proceso = %llu ns\n",fam,ns); + + printf("%-44s %10s %10s\n","BENCH (ns por consulta)","min","mediana"); + const long N=2000; + double r[ROUNDS]; + for(int q=0;q0){ b[n]=0; char *p=strrchr(b,')'); for(int f=0;p&&f<12;f++) p=strchr(p+1,' '); + sink=p?atol(p+1):0; } + } + r[q]=(now_ns()-t0)/(double)N; + } + report("open+read+parse /proc/self/stat",r,ROUNDS,N); + close(s); +} + +int main(void){ + if(geteuid()!=0) fprintf(stderr,"aviso: sin root el connector no se suscribe (CAP_NET_ADMIN)\n"); + printf("# bench_connector — SDD 25 seccion 9, experimento 1\n"); + int s=cn_open(); + if(s<0){ printf("proc connector: no disponible (%s)\n",strerror(errno)); } + else { fase_a(s); fase_b(s); close(s); } + fase_c(); + return 0; +} diff --git a/docs/evidencia/tasas-kernel-2026-08-29/bench_reflink.c b/docs/evidencia/tasas-kernel-2026-08-29/bench_reflink.c new file mode 100644 index 00000000..8e961ea5 --- /dev/null +++ b/docs/evidencia/tasas-kernel-2026-08-29/bench_reflink.c @@ -0,0 +1,106 @@ +/* bench_reflink.c — copiar un fichero: reflink (FICLONE), copy_file_range y read+write. + * + * Cierra el experimento 2 de SDD 25 seccion 9 (T11), que quedo sin medir porque exige mkfs sobre + * un loop, o sea root. La pregunta: el "copiar en O(1)" que la gente espera de copy_file_range, + * cuanto vale de verdad, y en que filesystem. + * + * Uso: bench_reflink (el dir debe estar en el FS que se quiere medir) + * Se compila con: cc -O2 -o bench_reflink bench_reflink.c + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MB (1024*1024) +static long SIZE = 64*MB; /* se puede fijar por argv[3] en MiB: la copia O(1) hay que verla PLANA */ +#define ROUNDS 7 + +static inline double now_ns(void){ struct timespec t; clock_gettime(CLOCK_MONOTONIC,&t); return t.tv_sec*1e9+t.tv_nsec; } +static int cmpd(const void*a,const void*b){ double x=*(const double*)a,y=*(const double*)b; return (x>y)-(x 1e6) printf("%-40s %9.3f ms %9.3f ms %8.0f MB/s\n",n,min/1e6,med/1e6,(double)SIZE/(min/1e9)/1e6); + else printf("%-40s %9.3f ms %9.3f ms (plano: no mueve datos)\n",n,min/1e6,med/1e6); + fflush(stdout); +} + +static int src_fd(const char *dir,char *path,size_t n){ + snprintf(path,n,"%s/origen.bin",dir); + int fd=open(path,O_CREAT|O_RDWR|O_TRUNC,0644); + if(fd<0) return -1; + char *b=malloc(MB); memset(b,0xA5,MB); + for(long i=0;i [MiB]\n",argv[0]); return 2; } + const char *dir=argv[1], *etiqueta=argv[2]; + if(argc>3) SIZE=atol(argv[3])*MB; + char src[512],dst[512]; + int in=src_fd(dir,src,sizeof src); + if(in<0){ fprintf(stderr,"no pude crear el origen en %s: %s\n",dir,strerror(errno)); return 1; } + snprintf(dst,sizeof dst,"%s/copia.bin",dir); + + printf("\n### copia de %ld MiB sobre %s\n",SIZE/MB,etiqueta); + printf("%-40s %12s %12s\n","BENCH","min","mediana"); + + double r[ROUNDS]; + int ok=0; + + /* 1. reflink de fichero entero: la copia O(1) de verdad (comparte extents COW). */ + for(int q=0;q0) (void)!write(out,buf,n); } + r[q]=now_ns()-t0; + close(out); + } + report("read+write (1 MiB)",r,ROUNDS); + free(buf); + + unlink(dst); unlink(src); close(in); + return 0; +} diff --git a/docs/evidencia/tasas-kernel-2026-08-29/bench_sqpoll.c b/docs/evidencia/tasas-kernel-2026-08-29/bench_sqpoll.c new file mode 100644 index 00000000..0d97e3cc --- /dev/null +++ b/docs/evidencia/tasas-kernel-2026-08-29/bench_sqpoll.c @@ -0,0 +1,112 @@ +/* bench_sqpoll.c — io_uring con SQPOLL contra io_uring normal y contra pread. + * + * Cierra el experimento 4 de SDD 25 seccion 9: SQPOLL pide CAP_SYS_NICE, asi que la corrida + * original no pudo mirarlo. La pregunta que dejo abierta T12: io_uring pierde sobre datos ya + * cacheados porque el cruce al kernel no se amortiza — con SQPOLL NO HAY cruce (un hilo del + * kernel consume la cola), asi que este es el caso donde deberia ganar. + * + * Uso: bench_sqpoll + * Se compila con: cc -O2 -o bench_sqpoll bench_sqpoll.c -luring + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#define MB (1024*1024) +#define SIZE (64*MB) +#define BS 4096 +#define ROUNDS 7 +#define DEPTH 32 +#define OPS 50000 + +static volatile long sink; +static inline double now_ns(void){ struct timespec t; clock_gettime(CLOCK_MONOTONIC,&t); return t.tv_sec*1e9+t.tv_nsec; } +static int cmpd(const void*a,const void*b){ double x=*(const double*)a,y=*(const double*)b; return (x>y)-(x \n",argv[0]); return 2; } + char path[512]; snprintf(path,sizeof path,"%s/sqpoll.bin",argv[1]); + int fd=open(path,O_CREAT|O_RDWR|O_TRUNC,0644); + if(fd<0){ fprintf(stderr,"no pude crear %s: %s\n",path,strerror(errno)); return 1; } + char *b=malloc(MB); memset(b,0x5A,MB); + for(int i=0;iflags|=IOSQE_FIXED_FILE; + } + io_uring_submit_and_wait(&ring,batch); + struct io_uring_cqe *c; unsigned h; int seen=0; + io_uring_for_each_cqe(&ring,h,c){ if(c->res<0) sink=c->res; seen++; } + io_uring_cq_advance(&ring,seen); + done+=batch; + } + r[q]=(now_ns()-t0)/(double)OPS; + } + report(usar_fijo?"io_uring SQPOLL (fd registrado)":"io_uring SQPOLL (fd normal)",r,ROUNDS,OPS); + io_uring_queue_exit(&ring); + } else printf("SQPOLL: no disponible (%s) — pide CAP_SYS_NICE\n",strerror(errno)); + + unlink(path); close(fd); + return 0; +} diff --git a/docs/evidencia/tasas-kernel-2026-08-29/connector.txt b/docs/evidencia/tasas-kernel-2026-08-29/connector.txt new file mode 100644 index 00000000..46d80e9b --- /dev/null +++ b/docs/evidencia/tasas-kernel-2026-08-29/connector.txt @@ -0,0 +1,20 @@ +# condiciones: 2026-08-29T19:27:32Z · 7.1.4-artix1-1 · load 1.25 1.30 1.93 · 4285 MiB libres · root +# bench_connector — SDD 25 seccion 9, experimento 1 + +### A. Latencia de notificacion: waitpid contra evento del connector +BENCH (ns por proceso) min mediana +fork+_exit+waitpid (SIGCHLD, la base) 114825.2 123130.6 (n=200) +fork+_exit+esperar EXIT del connector 116041.0 133773.5 (n=200) +eventos EXIT que no llegaron en 200 ms: 0 de 1400 + +### B. Ceguera: 200 procesos de vida minima, uno cada 10 ms +sondeo /proc cada 100 ms : 0 de 200 procesos vistos (23 barridos, 10.5 ms de CPU) +proc connector (eventos) : 200 de 200 procesos vistos (95.4 ms de CPU) +NOTA: el connector se lee aca con espera activa de 200 us, que NO es el modo de un + supervisor real (seria epoll) => su CPU es cota superior. Lo que cuenta: COBERTURA. + +### C. Estadisticas de UNA tarea: taskstats binario contra /proc de texto +familia TASKSTATS = 41, cpu de este proceso = 198921000 ns +BENCH (ns por consulta) min mediana +taskstats por genetlink (binario) 2688.1 2726.3 (n=2000) +open+read+parse /proc/self/stat 2696.7 2716.5 (n=2000) diff --git a/docs/evidencia/tasas-kernel-2026-08-29/reflink.txt b/docs/evidencia/tasas-kernel-2026-08-29/reflink.txt new file mode 100644 index 00000000..ce993f7f --- /dev/null +++ b/docs/evidencia/tasas-kernel-2026-08-29/reflink.txt @@ -0,0 +1,34 @@ +# condiciones: 2026-08-29T19:29:16Z · 7.1.4-artix1-1 · load 1.30 1.30 1.87 +# xfsprogs mkfs.xfs version 7.1.1 · btrfs-progs mkfs.btrfs, part of btrfs-progs v7.1 + +### copia de 64 MiB sobre ext4 +BENCH min mediana +FICLONE (reflink entero) no soportado (Operation not supported) +copy_file_range 13.655 ms 15.013 ms 4914 MB/s +read+write (1 MiB) 14.455 ms 14.911 ms 4643 MB/s +# xfs montado: xfs rw,relatime,inode64,logbufs=8,logbsize=32k,noquota + +### copia de 64 MiB sobre xfs (loop) +BENCH min mediana +FICLONE (reflink entero) 0.010 ms 0.013 ms (plano: no mueve datos) +copy_file_range 0.010 ms 0.010 ms (plano: no mueve datos) +read+write (1 MiB) 10.964 ms 11.290 ms 6121 MB/s + +### copia de 512 MiB sobre xfs (loop), fichero 8x mas grande +BENCH min mediana +FICLONE (reflink entero) 0.020 ms 0.021 ms (plano: no mueve datos) +copy_file_range 0.019 ms 0.020 ms (plano: no mueve datos) +read+write (1 MiB) 512.712 ms 600.930 ms 1047 MB/s +# btrfs montado: btrfs rw,relatime,ssd,discard=async,space_cache=v2,subvolid=5,subvol=/ + +### copia de 64 MiB sobre btrfs (loop) +BENCH min mediana +FICLONE (reflink entero) 0.006 ms 0.014 ms (plano: no mueve datos) +copy_file_range 0.006 ms 0.008 ms (plano: no mueve datos) +read+write (1 MiB) 31.323 ms 32.181 ms 2143 MB/s + +### copia de 512 MiB sobre btrfs (loop), fichero 8x mas grande +BENCH min mediana +FICLONE (reflink entero) 0.015 ms 0.020 ms (plano: no mueve datos) +copy_file_range 0.015 ms 0.020 ms (plano: no mueve datos) +read+write (1 MiB) 236.891 ms 533.540 ms 2266 MB/s diff --git a/docs/evidencia/tasas-kernel-2026-08-29/sqpoll.txt b/docs/evidencia/tasas-kernel-2026-08-29/sqpoll.txt new file mode 100644 index 00000000..cbbf17e5 --- /dev/null +++ b/docs/evidencia/tasas-kernel-2026-08-29/sqpoll.txt @@ -0,0 +1,13 @@ +# condiciones: 2026-08-29T19:30:07Z · 7.1.4-artix1-1 · load 2.23 1.61 1.95 · root + +### 4K aleatorios en cache sobre ext4 (profundidad 32) +BENCH (ns/op) min mediana +pread 4K (una syscall por op) 554.4 590.2 (n=50000) +io_uring sin SQPOLL 617.7 633.8 (n=50000) +io_uring SQPOLL (fd registrado) 867.7 1068.6 (n=50000) + +### 4K aleatorios en cache sobre tmpfs (profundidad 32) +BENCH (ns/op) min mediana +pread 4K (una syscall por op) 749.3 764.2 (n=50000) +io_uring sin SQPOLL 2029.6 2237.6 (n=50000) +io_uring SQPOLL (fd registrado) 1409.3 2296.8 (n=50000) diff --git a/docs/evidencia/tasas-kernel-2026-08-29/syscalls-compilador.txt b/docs/evidencia/tasas-kernel-2026-08-29/syscalls-compilador.txt new file mode 100644 index 00000000..c92d1aa9 --- /dev/null +++ b/docs/evidencia/tasas-kernel-2026-08-29/syscalls-compilador.txt @@ -0,0 +1,126 @@ +# condiciones: 2026-08-29T19:30:50Z · 7.1.4-artix1-1 · strace 6.19 DEL PROPIO CORPUS (store/3c1fd8c0…-strace) +# fuente: hola.c — un main() con stdio/stdlib/string, o sea el caso MAS BARATO posible + +=== cc -O2 -c (gcc 16) === +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 17960 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 17971 attached +% time seconds usecs/call calls errors syscall +------ ----------- ----------- --------- --------- ---------------- + 80.09 0.048227 24113 2 wait4 + 7.44 0.004479 4 923 919 readlink + 3.00 0.001808 17 105 read + 2.30 0.001387 6 228 127 openat + 1.28 0.000772 8 92 mmap + 1.02 0.000614 87 7 4 execve + 0.87 0.000522 5 101 close + 0.78 0.000470 4 100 fstat + 0.77 0.000466 232 2 clone3 + 0.77 0.000463 6 67 24 newfstatat + 0.37 0.000220 7 31 brk + 0.27 0.000165 8 20 mprotect + 0.17 0.000100 4 23 15 access + 0.11 0.000065 3 19 rt_sigaction + 0.10 0.000060 30 2 unlink + 0.09 0.000056 18 3 getcwd + 0.09 0.000056 5 11 prlimit64 + 0.09 0.000055 6 8 write + 0.09 0.000053 3 14 rt_sigprocmask + 0.07 0.000043 3 12 lseek + 0.04 0.000026 3 7 getrandom + 0.04 0.000022 11 2 munmap + 0.04 0.000022 3 6 6 ioctl + 0.02 0.000013 4 3 sysinfo + 0.02 0.000011 3 3 rseq + 0.02 0.000010 3 3 arch_prctl + 0.02 0.000010 3 3 set_tid_address + 0.02 0.000010 3 3 set_robust_list + 0.01 0.000007 3 2 fcntl + 0.01 0.000004 3 1 getrusage +------ ----------- ----------- --------- --------- ---------------- +100.00 0.060214 33 1803 1095 total + +=== zig cc -O2 -c (zig 0.16.0) === +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 17979 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 17980 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 17984 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 17988 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 17989 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 17990 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 17993 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 18047 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 18053 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 18054 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 18055 attached +/mnt/vvv/hammer/store/3c1fd8c0fbb20c272c2935d5b5ca63bc51be257c271e96e312ee86ed6886f89d-strace/usr/bin/strace: Process 18056 attached +% time seconds usecs/call calls errors syscall +------ ----------- ----------- --------- --------- ------------------ + 69.79 1.378703 1248 1104 14 futex + 25.60 0.505698 101139 5 wait4 + 1.26 0.024957 2495 10 poll + 0.69 0.013629 42 318 80 openat + 0.33 0.006426 18 353 mmap + 0.31 0.006187 38 162 43 newfstatat + 0.18 0.003615 47 76 read + 0.17 0.003425 54 63 pread64 + 0.17 0.003361 17 195 rt_sigprocmask + 0.15 0.003003 12 245 close + 0.13 0.002634 25 105 29 readlink + 0.13 0.002511 179 14 8 execve + 0.12 0.002410 15 159 fstat + 0.12 0.002312 28 82 mprotect + 0.09 0.001870 103 18 munmap + 0.09 0.001743 435 4 clone + 0.08 0.001520 27 56 brk + 0.08 0.001497 748 2 mkdirat + 0.07 0.001355 43 31 19 access + 0.06 0.001176 4 254 preadv + 0.06 0.001096 16 67 rt_sigaction + 0.05 0.000936 117 8 clone3 + 0.03 0.000545 45 12 readv + 0.02 0.000492 28 17 set_robust_list + 0.02 0.000483 53 9 7 faccessat2 + 0.02 0.000430 6 69 statx + 0.02 0.000353 25 14 write + 0.02 0.000342 15 22 prlimit64 + 0.02 0.000297 22 13 rseq + 0.01 0.000277 25 11 madvise + 0.01 0.000256 32 8 pipe2 + 0.01 0.000247 19 13 13 ioctl + 0.01 0.000242 16 15 getrandom + 0.01 0.000210 30 7 sched_getaffinity + 0.01 0.000155 25 6 dup2 + 0.01 0.000149 18 8 sigaltstack + 0.01 0.000147 13 11 lseek + 0.01 0.000134 22 6 getdents64 + 0.00 0.000088 29 3 1 unlinkat + 0.00 0.000078 12 6 arch_prctl + 0.00 0.000075 18 4 gettid + 0.00 0.000073 12 6 set_tid_address + 0.00 0.000060 29 2 rename + 0.00 0.000048 16 3 ftruncate + 0.00 0.000045 22 2 pwritev + 0.00 0.000036 17 2 flock + 0.00 0.000028 28 1 readlinkat + 0.00 0.000022 22 1 renameat + 0.00 0.000020 20 1 unlink + 0.00 0.000016 5 3 sysinfo + 0.00 0.000008 7 1 uname + 0.00 0.000005 4 1 getcwd +------ ----------- ----------- --------- --------- ------------------ +100.00 1.975424 547 3608 214 total + +=== reparto de fallos del gcc (ENOENT por buscar cabeceras) === +166 + +=== tiempo de pared del MISMO compilado, sin strace (mínimo/mediana de 7) === +cc -O2 -c hola.c min 30.5 ms mediana 33.3 ms +zig cc -O2 -c hola.c min 53.6 ms mediana 58.9 ms + +=== lectura === +gcc: 1803 syscalls, 1095 con error (61%) — 919 de 923 readlink FALLAN. + Al piso medido de 78,7 ns por syscall, 1803 cruces = 0,14 ms sobre 30,5 ms de compilado + => el cruce al kernel es el 0,5% del compilado. La tormenta de rutas de T8 vale + MILISEGUNDOS por invocación, no minutos. +zig cc: 3608 syscalls, sólo 214 con error, pero 1104 futex (70% del tiempo EN syscall) y 5 wait4. + Su perfil no es de búsqueda de rutas sino de coordinación entre hilos; el tiempo de + syscall que reporta strace -c es espera BLOQUEADA, no CPU.