SDD 25 §9.5.1 — Iterador BPF contra el barrido de /proc
Medido 2026-08-31 en 'momento'. TERCERA corrida: condiciones propias, NO se cruza
con los números de §2 ni con los de §9.

== condiciones ==
kernel de desarrollo : 7.1.4-artix1-1   (Artix; NO es un kernel de hammer)
cpu                  : 4 vCPU   load: 3.85 5.27 4.91
memoria libre        : 4483 MiB disponibles
BTF del kernel       : /sys/kernel/btf/vmlinux, 6455713 bytes
libbpf               : 1.7.0
clang                : clang version 22.1.8
ruido conocido       : un 'yes' huérfano (pid 1750, reparentado a arje-zero) llevaba
                       3,5 dias quemando un core entero de los 4. Los ABSOLUTOS de
                       abajo son cotas superiores; la señal está en los cocientes.

== qué compara ==
El MISMO trabajo por los dos caminos: {pid, ppid, estado, utime, stime, comm} de todos
los procesos vivos — la foto que sandokan necesita de la máquina.
  A) /proc : readdir(/proc) + open+read+parse de /proc/<pid>/stat, uno por proceso
  B) BPF   : bpf_iter_create + read() de registros BINARIOS de tamaño fijo
  C) piso  : readdir(/proc) a secas, sin abrir nada

== las DOS barreras, comprobadas, no supuestas ==
1) El iterador se ata por ID DE TIPO BTF del vmlinux:
     prog_type=26 (BPF_PROG_TYPE_TRACING=26)
     attach_btf_id=80137  attach_btf_obj_id=1  (0 en obj_id = BTF del vmlinux)
     => el iterador se ata por ID DE TIPO BTF: sin /sys/kernel/btf/vmlinux no hay a qué atarse.
   => un kernel sin CONFIG_DEBUG_INFO_BTF no expone /sys/kernel/btf/vmlinux y no hay
      a qué atarse. La ganancia de abajo NO se compra sin pagar BTF.
2) Hace falta privilegio (CAP_BPF+CAP_PERFMON, o root). Sin él:
     $ ./bench_bpf_iter 3
       load (¿root? ¿BTF?): Operation not permitted

== 33 rondas, orden A->B ==
procesos vistos: /proc 245 · BPF 245 · readdir 245   (33 rondas, orden A->B)
carga+verificación+attach del programa BPF (una vez): 16.7 ms

  A) /proc readdir+stat+parse        min    1356.1 us   mediana    1693.9 us     5.54 us/proceso (min)
  B) iterador BPF (binario)          min     196.1 us   mediana     273.6 us     0.80 us/proceso (min)
  C) piso: readdir(/proc) solo       min     112.1 us   mediana     143.8 us     0.46 us/proceso (min)

cociente A/B (min, misma corrida): 6.91x
equilibrio: la carga (16.7 ms) se amortiza en 15 barridos
cotejo: 221 pid+comm idénticos, 0 sólo en /proc, 0 sólo en BPF

== 33 rondas, orden B->A (control de sesgo de orden) ==
procesos vistos: /proc 245 · BPF 245 · readdir 245   (33 rondas, orden B->A)
carga+verificación+attach del programa BPF (una vez): 16.5 ms

  A) /proc readdir+stat+parse        min    1676.6 us   mediana    2115.2 us     6.84 us/proceso (min)
  B) iterador BPF (binario)          min     219.6 us   mediana     338.7 us     0.90 us/proceso (min)
  C) piso: readdir(/proc) solo       min     141.1 us   mediana     218.1 us     0.58 us/proceso (min)

cociente A/B (min, misma corrida): 7.64x
equilibrio: la carga (16.5 ms) se amortiza en 12 barridos
cotejo: 221 pid+comm idénticos, 0 sólo en /proc, 0 sólo en BPF

== las tres corridas cortas previas, mismo día ==
   9 rondas A->B : A 1018,7 us · B 135,4 us · piso 101,4 us -> 7,52x
  15 rondas A->B : A 2120,7 us · B 471,1 us · piso 193,2 us -> 4,50x
  15 rondas B->A : A 1534,1 us · B 220,8 us · piso 134,0 us -> 6,95x
  33 rondas A->B : A 1184,0 us · B 151,3 us · piso 108,1 us -> 7,82x
  33 rondas B->A : A 1266,4 us · B 158,7 us · piso 110,4 us -> 7,98x
  Con pocas rondas el mínimo no converge y la máquina cargada lo ensucia (el 4,50x).
  Con 33 rondas el cociente se planta en 7,2-8,0x en las CINCO corridas y en las DOS
  direcciones: el orden no lo explica.

== los 24 comm que DIFIEREN entre los dos caminos ==
No es un fallo del programa BPF: /proc SINTETIZA el nombre de los kworkers y le pega
la workqueue que están sirviendo (wq_worker_comm). task->comm trae el nombre pelado.
    DIFIERE pid 11: /proc=[kworker/0:0H-kb] bpf=[kworker/0:0H]
    DIFIERE pid 29: /proc=[kworker/1:0H-kb] bpf=[kworker/1:0H]
    DIFIERE pid 35: /proc=[kworker/2:0H-kb] bpf=[kworker/2:0H]
    DIFIERE pid 41: /proc=[kworker/3:0H-kb] bpf=[kworker/3:0H]
    DIFIERE pid 112: /proc=[kworker/3:1H-kb] bpf=[kworker/3:1H]
    DIFIERE pid 181: /proc=[kworker/1:1H-kb] bpf=[kworker/1:1H]
    DIFIERE pid 279: /proc=[kworker/2:1H-kb] bpf=[kworker/2:1H]
    DIFIERE pid 5361: /proc=[kworker/3:0-eve] bpf=[kworker/3:0]
  [...] los 24 son kworkers; NINGÚN proceso de usuario difiere. Quien cambie /proc por
  el iterador y muestre nombres de kworker verá otra cosa — para las Cards, da igual.
