Files
takana/docs/plan-variantes-cpu.md
T
Sergio 97ceb72411 takana etapa 5b: los 59 docs de diseño, runbooks y ADR
645 líneas. Los ADR entran porque en este repo SON documentos vivos, no
registros inmutables: el 0013 tiene 5 commits, el 0009 dos. Eso se comprobó
antes de decidir, no se asumió por convención general.

EXCLUIDOS por ser REGISTRO o generado: docs/evidencia/ (6), el HANDOFF de la
noche de KDE (1) y docs/state/ (24, se regenera solo). Reescribir un comando
dentro de una evidencia la falsifica.

Y el ADR 0016 se excluye de todo barrido, con un aviso adentro para el próximo
que barra: habla SOBRE el renombre, así que necesita seguir diciendo 'hammer'.
El barrido se lo llevó puesto y lo dejó titulado 'Renombre del sistema: takana
→ takana'; revertido.

Congelados, verificados uno por uno con controles: /opt/hammer, /var/lib/hammer,
/usr/bin/hammer, /mnt/vvv/hammer, la URL de gitea, hammer-farm.service,
hammer-live-install.sh, BRIEFING-hammer.md, hammerd, hammer-recover y
HAMMER_LIVE.
2026-09-09 19:25:51 +00:00

6.0 KiB
Raw Blame History

Plan — variantes por nivel de CPU (x86-64-v3) sobre el CAS

Fecha: 2026-07-16 · Origen: el linaje Solus (hwcap dirs AVX2 ~2017, lista corta medida) → Red Hat (niveles x86-64-v2/v3/v4 + glibc-hwcaps en glibc 2.33, selección en el loader) → CachyOS (repos enteros v3/v4 + LTO + scheduler). Análisis de qué forma toma eso en takana.

Tesis: takana ya tiene la mitad difícil gratis. Una variante optimizada no es un mecanismo nuevo: es la misma receta con otros flags, que sella a otro hash en el mismo store. Lo que las distros binarias resuelven con subdirectorios mágicos del loader, takana lo resuelve con lo que ya es: contenido direccionado por hash + hydrate.


1. La restricción que ordena todo el diseño: musl no tiene hwcaps

El mecanismo glibc-hwcaps es del loader de glibc. El ldso de musl no busca en subdirectorios por microarquitectura y no va a hacerlo. Conclusión estructural:

La selección de variante en takana ocurre en HYDRATE (por máquina), no en runtime (por proceso). Cada máquina hidrata la variante que su CPU soporta; el árbol instalado tiene UNA copia de cada lib, la correcta. Sin dispatch, sin dobles copias en disco, sin loader parcheado.

Esto no es una limitación disfrazada: es el modelo más simple de los dos, y el único compatible con el resto de takana (un artefacto = un hash = un contenido; "elige en runtime" rompería la correspondencia instalado↔sellado que usa todo, del journal a CVE-por-grafo).

Costo honesto: una imagen/USB "para cualquier máquina" debe llevar baseline (o dos hydrates). El punto de selección es takana hydrate / el instalador, con sonda de CPU (cpuid → nivel).

2. Mecanismo: variante = flags, cero framework nuevo

Hoy el sandbox fija CC="zig cc -mcpu=baseline" (sandbox.rs:415) precisamente para NO hornear la ISA del builder. Una variante v3 es el mismo contrato con otro valor pineado:

  • T1 — campo variant en la receta (o sección [variants.v3] que sólo sobreescribe flags/mcpu). Regla dura: la variante hereda todo lo demás de la receta canónica — misma fuente, mismos patches, mismas deps. Si diverge en algo más, no es una variante, es otra receta.
  • T2 — mcpu=x86_64_v3 pineado por nombre de nivel, nunca native (mismo argumento que baseline: la ISA del builder no puede filtrarse; el nivel es el contrato).
  • T3 — el índice firmado publica (nombre, versión, nivel, hash). El nivel es un eje más del catálogo, no un repo aparte (donde CachyOS mantiene N repos, takana tiene N hashes).
  • T4 — sonda de nivel en hydrate/instalador: detectar v2/v3/v4 y resolver el hash correspondiente, con fallback a baseline. Idempotente como todo hydrate.

La bit-repro no se toca: la reproducibilidad es por-(receta, flags); una variante v3 reproduce contra sí misma en la granja exactamente igual que hoy reproduce baseline.

3. Alcance: lista caliente (Solus), NO repo entero (CachyOS)

Recompilar el catálogo entero por nivel multiplica la granja por N para ganancias que en el 90% de los paquetes son ruido. Solus lo midió hace una década: el beneficio se concentra en un puñado de libs con kernels vectorizables. Lista caliente inicial (todas ya en el catálogo):

candidata por qué
zlib, zstd, xz (de)compresión en cada operación del propio takana
mesa el caso con más ganancia medible en GUI/juegos (llvmpipe/ACO vectorizan)
códecs (ffmpeg-clase, cuando entren) el caso clásico AVX2
pixman, cairo raster 2D — frontera GUI: sólo en worker (gotcha zig-skew)
  • T5 — piloto medido (2026-07-17, laptop TigerLake, clang 3 variantes base/v3/v4, corpus 200MB mixto fuente+binarios):
    • zstd: v3/v4 NO pagan — CORTADO de la lista. Bench interno (-b3 -i7, estable): base 144.2 vs v4 146.5 MB/s comprimiendo, 702 vs 692 descomprimiendo = ruido. Causa conocida: zstd ya hace dispatch BMI2/AVX2 en runtime ⇒ el -march del build casi no toca los kernels calientes. (Un +24% aparente de v4 en la 1ª tanda desapareció con i7: era calentamiento — lección para T6: sólo benchs con control de varianza.)
    • zlib (madler): INCONCLUSO en laptop con carga (el mismo binario base osciló 112157 MB/s entre tandas). Pero la pregunta estaba mal hecha: la respuesta buena no es una variante v3 de zlib sino zlib-ng (fork con SIMD y dispatch en runtime, drop-in ABI; Fedora 40 ya lo adoptó como zlib del sistema) ⇒ un solo artefacto, cero maquinaria de variantes. Candidato a receta; medir zlib-ng vs zlib en máquina quieta cuando toque.
    • Consecuencia estructural: los compresores modernos ya resuelven esto con dispatch interno ⇒ la lista caliente de variantes se concentra donde NO hay dispatch: mesa (llvmpipe/ACO compilan según -march) y códecs sin runtime-detect. El mecanismo T1T4 sigue válido pero su primer cliente real es mesa, no la dupla zlib/zstd.
  • T6 — regla de admisión: una lib entra a la lista caliente con benchmark que lo justifique, no por vibras. La lista vive en el repo junto a los números.

4. Lo que NO se hace

  • Repo entero v3/v4 — coste de granja ×N por ganancia marginal fuera de la lista caliente.
  • Dispatch en runtime / hwcaps — no existe en musl y el modelo por-máquina es mejor para takana de todos modos (§1).
  • -mcpu=native jamás — ni en variantes: el nivel nombrado es el contrato reproducible.
  • LTO generalizado como campaña — takana ya linkea estático con zig; el LTO por-receta se evalúa donde el benchmark de T5/T6 lo pida, no como política global.

Orden propuesto

  1. T5 (piloto zlib/zstd en worker, benchmark) — decide si el frente vale antes de tocar framework.
  2. T1T2 (campo variant + mcpu pineado) — sólo si T5 da ganancia medible.
  3. T3T4 (índice + sonda en hydrate) — cierra el ciclo usable.
  4. mesa v3 — el premio gordo para juegos; coordinar con el plan de jaula de juegos (plan-jaula-juegos.md), siempre en worker.