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

98 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.