Barrido de TEXTO puro: 1427 líneas de comentario TOML. Cero ArtifactHash movidos, y eso está MEDIDO, no deducido: hasheé las 741 antes y después y los ficheros de hashes son idénticos byte a byte (723 con hash real + 18 que ya no hasheaban de antes). El guardián valió la pena: el primer barrido, filtrando por 'la línea empieza con #', movió el hash de helix, lsof y steam-runtime-sniper. La causa es que una fase se escribe como compile = <triple> ... <triple> y sus comentarios de SHELL también empiezan con #, pero viven dentro del VALOR — y las fases sí entran en hash_inputs. El barrido ahora calcula los rangos de las cadenas multilínea de TOML y no entra ahí. Quedan intactos a propósito: .hammer-zig-cc y .hammer-cargo-vendor (literales dentro de fases), hammerd, hammer-recover y toda ruta que empiece por /
108 lines
6.8 KiB
TOML
108 lines
6.8 KiB
TOML
# firefox-pgo-profile — el perfil de ejecución que optimiza a firefox. UNA MEDICIÓN CONGELADA.
|
||
#
|
||
# ══ QUÉ ES ═════════════════════════════════════════════════════════════════════════════════════
|
||
# `merged.profdata`: 501.521 funciones, 3.734.991 bloques y **38.498.366.335 ejecuciones**
|
||
# registradas sobre un corpus de **46 páginas**: las 36 de Mozilla (`build/pgo`) MÁS las 10 de
|
||
# maquetación propias de `scripts/pgo-corpus/`.
|
||
#
|
||
# ⚠ EL CORPUS SE AMPLIÓ POR UNA MEDICIÓN, NO POR CORAZONADA. Con sólo las 36 de Mozilla la ganancia
|
||
# medida fue **−9,4 %** en una página de DOM/maquetación y **−1,0 %** en `3d-raytrace`. La razón es
|
||
# que un benchmark JIT-bound es casi CIEGO al PGO —el bucle caliente lo ejecuta código que el JIT
|
||
# emite en runtime, y el PGO optimiza el intérprete, el GC y el propio JIT, no lo que el JIT
|
||
# produce—, y el corpus de Mozilla está dominado en número de páginas por SunSpider. O sea que
|
||
# entrenaba mucho justo donde el PGO menos rinde. Las 10 nuevas van al camino que sí es C++ de punta
|
||
# a punta: flexbox, grid, tablas, texto en columnas, selectores, pintado, transforms, SVG, scroll
|
||
# pegajoso y layout thrashing. Efecto medido en el propio perfil: las ejecuciones registradas pasan
|
||
# de 5.885.254.799 a 38.498.366.335 (**6,5×**).
|
||
# `firefox` lo consume con `--enable-profile-use=cross`.
|
||
#
|
||
# ══ POR QUÉ ES UNA FUENTE PINEADA Y NO UNA RECETA QUE LO GENERA ════════════════════════════════
|
||
# **El perfil NO ES DETERMINISTA**: los contadores dependen del timing de la corrida, así que dos
|
||
# generaciones no dan los mismos bytes. Si esto fuera una receta que lo produce, su ArtifactHash
|
||
# —input-addressed— no se movería entre generaciones, y firefox consumiría bytes distintos en la
|
||
# misma dirección: el build optimizado dejaría de reproducir sin que nada lo dijera. Es el mismo
|
||
# modo de fallo que el lab fuera de `hash_inputs`, fabricado a propósito.
|
||
#
|
||
# La salida es la que el SDD 26 §3.ter ya elegía: **generar el perfil UNA vez y sellarlo**, aquí como
|
||
# fuente pineada por sha256. Así el insumo es no determinista pero el build vuelve a serlo, que es
|
||
# exactamente lo que se quiere. Regenerarlo es una decisión explícita —subir un blob nuevo y cambiar
|
||
# el sha256—, nunca un accidente.
|
||
#
|
||
# ⚠ NO TIENE UPSTREAM, Y LA URL LO DICE. El blob es nuestro: sale de nuestra corrida sobre nuestro
|
||
# binario. La URL `.invalid` no resuelve por DNS a propósito (es el patrón que el ADR 0013 ya usa y
|
||
# prueba); los bytes vienen del mirror de fuentes, que sirve por sha256. Como la URL nunca estuvo en
|
||
# `hash_inputs` (ADR 0013), mover el objeto de origen no re-hashea nada.
|
||
#
|
||
# Publicado el 2026-09-07 en `takana/fuentes/<sha256>.tar` del Storage Box
|
||
# (`scripts/fuentes/mirror-env.sh` trae `TAKANA_MIRROR` y su clave).
|
||
# Verificado bajándolo de vuelta por el mismo camino que usa takana: 17.426.112 bytes, sha256 ok.
|
||
#
|
||
# ⚠ SI SE RECONSTRUYE `firefox-instrumentado`, ESTE PERFIL NO CADUCA SOLO. Un perfil recogido de un
|
||
# binario que ya no se parece al que se optimiza sigue siendo válido para clang —los contadores se
|
||
# aplican por nombre de función— pero vale menos: las funciones que ya no existen se ignoran y las
|
||
# nuevas quedan sin datos. Regenerarlo es su propia unidad de trabajo, no un efecto secundario.
|
||
# ⚠ EL JARLOG SE PROBÓ, FUNCIONA, Y ESTÁ APARCADO CON LA EVIDENCIA MEDIDA (2026-09-08).
|
||
# Se generó (`MOZ_JAR_LOG_FILE` en el entorno; NO hace falta la extensión `Quitter` de Mozilla, que
|
||
# el SDD daba por bloqueante), entró en el build, y se verificó del lado del artefacto: el `libxul`
|
||
# quedó IDÉNTICO byte a byte y sólo cambió el `omni.ja`. O sea que la función existe.
|
||
#
|
||
# Pero **convierte el `omni.ja` al formato «jar optimizado» de Mozilla**, que mueve el directorio
|
||
# central al principio:
|
||
#
|
||
# sin jarlog: PK\003\004 ZIP estándar — `zipfile` lo abre, 5306 entradas
|
||
# con jarlog: \376\204#\0 `zipfile` lo rechaza: BadZipFile
|
||
#
|
||
# Y eso ROMPE `atuq`, que reempaqueta el `omni.ja` con `zipfile` para su branding:
|
||
# `zipfile.BadZipFile: Bad magic number for central directory` en `rebrand.py`.
|
||
#
|
||
# La cuenta es asimétrica y por eso se aparca: el COSTE está MEDIDO —el navegador propio de la
|
||
# distro no se puede construir— y el BENEFICIO no. El banco corre con caché de página caliente, que
|
||
# es donde reordenar el `omni.ja` no ahorra ninguna lectura, y dio −0,1 %: por debajo del suelo de
|
||
# ruido del propio banco (~1 % entre corridas de días distintos). Cambiar algo que funciona por una
|
||
# ganancia que no se pudo medir, rompiendo algo que sí funcionaba, es mal negocio.
|
||
#
|
||
# Se retoma cuando (1) se mida el arranque EN FRÍO, que es su terreno, y (2) `rebrand.py` sepa leer
|
||
# el jar optimizado o des-optimizarlo antes. **El blob `92497cdd…` del mirror YA TRAE el jarlog**,
|
||
# así que retomarlo no exige volver a perfilar: es cambiar una línea y re-pinear el sha256.
|
||
#
|
||
name = "firefox-pgo-profile"
|
||
version = "2026.09.08"
|
||
license = "MPL-2.0"
|
||
|
||
[source]
|
||
tarball = "https://no-hay-upstream.invalid/hammer/firefox-pgo-2026-09-08.tar.xz"
|
||
sha256 = "95472411ba252e14c4d57de7193d53e4ba35fbccf4819ba95ceff1ca843e4a7a"
|
||
# ⚠ `0` Y NO EL DEFAULT. takana recorta UN componente al extraer, porque los releases GNU vienen
|
||
# con un `proyecto-version/` de más. Este tarball es nuestro y lleva el fichero en la raíz, así que
|
||
# con el default se recortaba lo único que hay y el install moría en `cp: cannot stat
|
||
# merged.profdata`. El error no menciona el recorte por ningún lado.
|
||
strip_components = 0
|
||
|
||
[build]
|
||
compiler = "clang"
|
||
|
||
[build.phases]
|
||
configure = "true"
|
||
compile = "true"
|
||
install = '''
|
||
set -e
|
||
mkdir -p /out/usr/share/firefox-pgo
|
||
cp merged.profdata /out/usr/share/firefox-pgo/merged.profdata
|
||
|
||
P=/out/usr/share/firefox-pgo/merged.profdata
|
||
|
||
# ── GUARDIÁN: QUE SEA UN PERFIL, NO UN FICHERO GRANDE ────────────────────────────────────────
|
||
# «Existe» no es «sirve», y acá el modo de fallo es especialmente callado: `--enable-profile-use`
|
||
# con un profdata vacío o de otra versión no rompe el build de firefox — lo hace más lento y ya.
|
||
# O sea que un perfil malo sella en verde, reproduce, y lo único que se pierde es justo lo que se
|
||
# fue a buscar. Se le pregunta a `llvm-profdata` cuántas funciones trae.
|
||
n=$(llvm-profdata show "$P" 2>/dev/null | sed -n 's/^Total functions: //p')
|
||
case "${n:-0}" in ''|*[!0-9]*) n=0 ;; esac
|
||
test "$n" -gt 100000 || {
|
||
echo "!! el profdata declara $n funciones (esperaba >100000): perfil vacío o ilegible" >&2
|
||
llvm-profdata show "$P" 2>&1 | head -5 >&2
|
||
exit 1
|
||
}
|
||
echo "guardián: perfil válido — $n funciones, $(stat -c%s "$P") bytes"
|
||
'''
|