atuq: lo que limpia el contador es SOBREVIVIR un rato después de pintar, no pintar

El par aísla la variable —mismo pin, mismo perfil, misma imagen, y la única diferencia es cuánto vive
el navegador después del primer cuadro—:

  S1       +97 s,  muerta en el acto (`--until-paint`)   ⇒ contador después: 1
  cierre-1 +120 s, ~360 s de vida después de pintar      ⇒ contador después: AUSENTE

Con eso queda contestada la pregunta que dos secciones atrás este documento daba por cerrada y no lo
estaba, y A deja de ser una anomalía: también siguió viva minutos después del primer cuadro.

Se dice además lo que la tabla NO prueba: si ese arranque además SELLÓ el éxito. El volcado del
«después» sólo grepeaba el contador; ahora `toolkit.startup.last_success` va en los DOS volcados y se
guarda en la medición (`last_success_antes` / `_despues`), que es lo que faltaba para no repetir la
corrida. Si el sello se mueve, es un gancho que sella y limpia a la vez; si no, son dos.

Y queda escrito que el 16 sigue sin explicación, ahora con una contradicción medida encima:
desapareció en una corrida diálogo + ATUQ-EXIT=0, y las fases k2/k3 del umbral fueron diálogo +
ATUQ-EXIT=0 y no limpiaron nada. La respuesta buena no tapa la sucia.

La corrida `cierre-1` y el mando `--watch-prefs` son de la otra sesión del frente.
This commit is contained in:
Sergio
2026-09-15 19:09:09 +00:00
parent 005f74209c
commit 1de1fc31f6
3 changed files with 85 additions and 24 deletions
+39 -4
View File
@@ -169,6 +169,21 @@ def leer_contador_de_caidas(texto):
return None
def leer_sello_de_exito(texto):
"""Saca `toolkit.startup.last_success` de un volcado de `prefs.js`.
Es la OTRA MITAD del cálculo del contador de caídas: el contador sube mientras este sello no se
mueve, así que un contador que no cambió sólo deja de ser ambiguo —«no subió» contra «subió y se
limpió»— si se lee junto con el sello. Medido el 2026-09-15: pasó un día entero sin moverse.
"""
for linea in texto.splitlines():
if "user_pref" in linea and "toolkit.startup.last_success" in linea:
m = re.search(r"last_success\"?\s*,\s*(\d+)", linea)
if m:
return int(m.group(1))
return None
def anotar_medicion(segundos, a, pantalla=None, extra=None):
"""Deja el tiempo de primera pintura en `docs/state/primera-pintura.json`.
@@ -265,6 +280,12 @@ def main():
"(p. ej. 1152x720): la ventana arranca con un tamaño YA PERSISTIDO. Es el "
"control del 117x70 — si con semilla sale grande, lo que falla es que nadie "
"le da tamaño en el primer arranque")
ap.add_argument("--watch-prefs", action="store_true",
help="en CADA captura lee también `recent_crashes` y `last_success` del perfil y "
"los imprime con el segundo. Es lo que mide CUÁNTO tarda un arranque en "
"darse por bueno: el valor de `last_success` es la hora de ARRANQUE, no la "
"de escritura, así que el momento en que cambia sólo se sabe mirándolo "
"seguido. Ignora `--until-paint`: lo interesante pasa DESPUÉS de pintar")
ap.add_argument("--repeat", type=int, metavar="N",
help="corre N fases IDÉNTICAS en el mismo arranque. Con `--wait` corto (60 s, o "
"sea antes de que pinte) mide el contador de caídas: cada fase lee "
@@ -416,6 +437,7 @@ def main():
"last_success)|browser.sessionstore.max_resumed' %s/prefs.js" % d, 60)
print(volcado.strip())
estado["recent_crashes_antes"] = leer_contador_de_caidas(volcado)
estado["last_success_antes"] = leer_sello_de_exito(volcado)
# ⚠ EL AVISO QUE FALTABA. Medido el 2026-09-15: el arranque que encuentra el
# anterior sin terminar SUMA UNO y compara DESPUÉS, así que con 3 guardado esta
# corrida abre el diálogo de Modo de resolución de problemas y no el navegador —
@@ -542,16 +564,25 @@ def main():
medidas = {p: pintado(f) for p, f in tomas.items()}
px = max((v for v in medidas.values() if v is not None), default=None)
donde = next((p for p, v in medidas.items() if v and v > 100_000), None)
vigilancia = ""
if a.watch_prefs and perfil_d:
# Una sola lectura, corta, por captura. `tr` junta las dos líneas para que
# entren en el renglón del avance: lo que importa es CUÁNDO cambian.
vigilancia = " prefs: " + " ".join(
l.strip() for l in ser.cmd(
"grep -hE 'toolkit.startup.(recent_crashes|last_success)' "
"%s/prefs.js | tr -d '\"' | tr '\\n' ' '" % perfil_d, 60).splitlines()
if "toolkit.startup" in l and "grep" not in l)
if primera is None and px and px > 100_000:
primera = t
print(f" +{t}s ██ PRIMERA PINTURA — {px} px de la página EN {donde}", flush=True)
if a.until_paint:
print(f" +{t}s ██ PRIMERA PINTURA — {px} px de la página EN {donde}{vigilancia}", flush=True)
if a.until_paint and not a.watch_prefs:
break
else:
vivos = ser.cmd("for c in /proc/[0-9]*/comm; do cat $c 2>/dev/null; done | grep -c atuq")
v = vivos.splitlines()[1].strip() if len(vivos.splitlines()) > 1 else "?"
detalle = " ".join(f"{p}={medidas[p]}" for p in PANTALLAS)
print(f" +{t}s px de la página: {detalle} procesos atuq: {v}", flush=True)
print(f" +{t}s px de la página: {detalle} procesos atuq: {v}{vigilancia}", flush=True)
capturar(qmp_sock, out, "%s-despues" % fase)
print("== captura DESPUES de la fase", flush=True)
@@ -580,10 +611,14 @@ def main():
# siguiente, que es lo que convierte esto en una serie legible (medido:
# 2 → 3 → 4 en tres fases de un mismo arranque). Se lee con el navegador
# todavía vivo, o sea que refleja el último volcado de prefs de Gecko.
volcado = ser.cmd("grep -E 'toolkit.startup.recent_crashes' %s/prefs.js || "
# ⚠ `last_success` VA EN LOS DOS VOLCADOS. Es la otra mitad del cálculo, y
# sin él en el «después» una limpieza no dice si el arranque además SELLÓ el
# éxito: son dos preguntas que se contestan con el mismo grep y una salía muda.
volcado = ser.cmd("grep -E 'toolkit.startup.(recent_crashes|last_success)' %s/prefs.js || "
"echo '(el pref no está: arranque sin caídas pendientes)'"
% perfil_d, 60)
estado["recent_crashes_despues"] = leer_contador_de_caidas(volcado)
estado["last_success_despues"] = leer_sello_de_exito(volcado)
print("---- el contador de caídas, DESPUÉS ----")
print(volcado.strip())
# ⚠ SÓLO LA FASE BASE SE ANOTA. La serie de `primera-pintura.json` es una TASA del