diff --git a/docs/26-atuq-envoltorio-gecko.md b/docs/26-atuq-envoltorio-gecko.md index 6b69e688..14248746 100644 --- a/docs/26-atuq-envoltorio-gecko.md +++ b/docs/26-atuq-envoltorio-gecko.md @@ -272,7 +272,7 @@ alcanza. transitorio. **La mediana lo ignora por diseño**; una media lo habría convertido en «v2 es catastróficamente peor». Fue la razón de elegir mediana antes de ver un solo número. -**EL JARLOG: PUESTO, PROBADO EN EL ARTEFACTO, NO MEDIBLE EN EL BANCO (2026-09-08).** Desde +**EL JARLOG: PROBADO, MEDIDO, Y APARCADO PORQUE ROMPE `atuq` (2026-09-08).** Desde `d9833a58` el perfil trae también el `jarlog` y `firefox` lo consume con `--with-pgo-jarlog`. No hizo falta la extensión `Quitter` de Mozilla, que este documento daba por bloqueante: su `profileserver.py` sólo traduce `JARLOG_FILE` a `MOZ_JAR_LOG_FILE` en el entorno del navegador. @@ -292,8 +292,29 @@ reordenar `omni.ja` no ahorra ninguna lectura. Su terreno es el arranque EN FRÍ instrumento no reproduce; medirlo pediría vaciar la caché entre corridas, que es una acción de sistema. **Lo que sí está probado es que la función existe**, y del lado del artefacto: `libxul` es IDÉNTICO byte a byte entre v2 y v3 y el `omni.ja` difiere en 26 bytes — el jarlog tocó exactamente -lo que debía tocar y nada más. Se conserva porque es lo que hace upstream y no cuesta nada; lo que -no se afirma es una ganancia que no se midió. +lo que debía tocar y nada más. **Y sí costaba.** Al reconstruir `atuq` sobre ese firefox, murió: + + zipfile.BadZipFile: Bad magic number for central directory (rebrand.py) + +El jarlog 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 + +Y `atuq` reempaqueta el `omni.ja` con `zipfile` para su branding. O sea que el jarlog **rompe el +navegador propio de la distro**. + +**Aparcado, y la cuenta es asimétrica:** el coste está MEDIDO y el beneficio NO. 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 es cambiar una línea y re-pinear el sha256 — no volver a perfilar. + +⚠ **Y la lección de método, que es la que más vale:** el jarlog parecía GRATIS. «Es lo que hace +upstream y no cuesta nada» — lo escribí yo, en este documento, hace unas horas. El coste no apareció +midiendo el jarlog sino **construyendo lo que dependía de él**. Una función que se declara gratuita +sin haber reconstruido a sus consumidores no es gratuita: es no medida. ⚠ **Dato que los datos delatan:** los dos valores atípicos del banco son 120.034 y 120.030 ms, o sea exactamente el `timeout 120` del arnés. No son ruido de carga: son corridas COLGADAS al arrancar en diff --git a/recipes/firefox-pgo-profile.toml b/recipes/firefox-pgo-profile.toml index 1b128b9b..00c8fad1 100644 --- a/recipes/firefox-pgo-profile.toml +++ b/recipes/firefox-pgo-profile.toml @@ -14,16 +14,7 @@ # 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×**). -# Y desde 2026-09-08 también el **`jarlog`**: el orden en que se leen los ficheros dentro de -# `omni.ja` al arrancar, para que el empaquetador los reordene y el arranque lea secuencialmente. -# `firefox` los consume con `--enable-profile-use=cross` y `--with-pgo-jarlog`. -# -# ⚠ EL JARLOG SE GENERA EN UNA CORRIDA APARTE, Y ESO ESTÁ MEDIDO, NO SUPUESTO. Mozilla lo emite en -# la misma sesión del `profileserver.py`; acá el arnés arranca un navegador POR PÁGINA, así que -# había que saber si el fichero se acumula o se pisa. Se pisa: tras `rejilla.html` y tras -# `tablas.html` dio **exactamente los mismos 27.652 bytes y 469 líneas**. O sea que su contenido lo -# domina el ARRANQUE y no la página, y por eso una corrida dedicada vale igual que una de 46 — -# rehacer el perfilado entero sólo para obtenerlo habría sido gasto sin diferencia. +# `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 @@ -50,13 +41,37 @@ # 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.08b" +version = "2026.09.08" license = "MPL-2.0" [source] -tarball = "https://no-hay-upstream.invalid/hammer/firefox-pgo-2026-09-08b.tar.xz" -sha256 = "92497cddca82a3e92a6fbb80b8d78245543ed25418a11b681f4b28d890e3a1f0" +tarball = "https://no-hay-upstream.invalid/hammer/firefox-pgo-2026-09-08.tar.xz" +sha256 = "95472411ba252e14c4d57de7193d53e4ba35fbccf4819ba95ceff1ca843e4a7a" # ⚠ `0` Y NO EL DEFAULT. hammer 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 @@ -73,7 +88,6 @@ install = ''' set -e mkdir -p /out/usr/share/firefox-pgo cp merged.profdata /out/usr/share/firefox-pgo/merged.profdata -cp jarlog /out/usr/share/firefox-pgo/jarlog P=/out/usr/share/firefox-pgo/merged.profdata @@ -90,18 +104,4 @@ test "$n" -gt 100000 || { exit 1 } echo "guardián: perfil válido — $n funciones, $(stat -c%s "$P") bytes" - -# ── GUARDIÁN DEL JARLOG ────────────────────────────────────────────────────────────────────── -# El jarlog es el orden en que se LEEN los ficheros dentro de `omni.ja` al arrancar; con él, el -# empaquetador los reordena para que el arranque haga lecturas secuenciales. Un jarlog vacío o que -# no nombre los archivos reales no rompe el build de firefox — sólo deja el `omni.ja` sin ordenar, -# o sea que se pierde justo lo que se vino a buscar, en silencio. Se exige que nombre los DOS -# archivos que el navegador abre. -J=/out/usr/share/firefox-pgo/jarlog -test -s "$J" || { echo "!! el jarlog está vacío o no existe" >&2; exit 1; } -for a in omni.ja browser/omni.ja; do - grep -q "^$a " "$J" || { echo "!! el jarlog no menciona '$a' — ¿se generó sin arrancar el navegador?" >&2 - awk '{print $1}' "$J" | sort -u | head -5 >&2; exit 1; } -done -echo "guardián: jarlog con $(wc -l < "$J") entradas sobre omni.ja y browser/omni.ja" ''' diff --git a/recipes/firefox.toml b/recipes/firefox.toml index 0d3bf048..d7bd9dd7 100644 --- a/recipes/firefox.toml +++ b/recipes/firefox.toml @@ -79,6 +79,30 @@ # por cualquier otro motivo — que es cuando cuesta cero. Si alguien shipea `firefox` antes de eso, # se paga ahí mismo. Ver SDD 26 §6.11. +# ⚠ 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" version = "154.0" license = "MPL-2.0" @@ -255,7 +279,6 @@ ac_add_options --disable-install-strip ac_add_options --disable-cargo-incremental ac_add_options --enable-profile-use=cross ac_add_options --with-pgo-profile-path=/usr/share/firefox-pgo/merged.profdata -ac_add_options --with-pgo-jarlog=/usr/share/firefox-pgo/jarlog ac_add_options --with-wasi-sysroot=/usr/share/wasi-sysroot ac_add_options --enable-alsa ac_add_options --enable-pulseaudio @@ -474,8 +497,10 @@ build = [ # que se recalcule: ver la cabecera de `recipes/firefox-pgo-profile.toml` para por qué un perfil # generado en cada build rompería la reproducibilidad en vez de darla. # - # ✅ CON `--with-pgo-jarlog` desde 2026-09-08: además de la disposición de CÓDIGO se ordena el - # `omni.ja` para el arranque, que era la mitad que faltaba. No hizo falta la extensión `Quitter` - # de Mozilla: basta con `MOZ_JAR_LOG_FILE` en el entorno del navegador. + # ⚠ SIN `--with-pgo-jarlog`, Y ES UNA MITAD QUE FALTA, NO UN OLVIDO. Alpine pasa además un + # `jarlog` que reordena `omni.ja` para acelerar el ARRANQUE. Ese fichero lo emite el + # `profileserver.py` de Mozilla usando su extensión `Quitter`, que nuestra corrida headless no + # tiene. O sea que hoy se gana la disposición de CÓDIGO y no el orden del `omni.ja`. Es su propia + # unidad de trabajo y está escrito para que nadie lo lea como «PGO completo». "firefox-pgo-profile", ]