Saltar al contenido
Development

La decodificación de 200KB que nadie necesitaba repetir

Por Victor Da Luz
astroperformancetestingdev-logastro-tools

Mi generador de tarjetas OG incluye una fuente de reserva para que quienes lo usan no tengan que proveer la suya. Está guardada como un string en base64 incrustado en el paquete, porque el parser de fuentes de satori no puede leer fuentes variables, y esto evita el problema por completo al usar un peso estático. Cada vez que la librería generaba una tarjeta, decodificaba ese string en base64 de vuelta a bytes crudos. Cada vez, sin excepción. Incluso al generar cincuenta tarjetas en el mismo build, para cincuenta posts distintos, usando la misma fuente.

El fix es un solo if

let cachedFonts: SatoriFont[] | null = null;

export async function defaultFonts(): Promise<SatoriFont[]> {
  if (!cachedFonts) {
    cachedFonts = [
      { name: 'Space Mono', data: Buffer.from(regularBase64, 'base64'), weight: 400, style: 'normal' },
      { name: 'Space Mono', data: Buffer.from(boldBase64, 'base64'), weight: 700, style: 'normal' },
    ];
  }
  return cachedFonts;
}

Ese es todo el cambio. Decodificar una vez, guardar el array en caché, y devolver la misma referencia todas las veces después. El tipo de fix que apenas se siente digno de una línea en el changelog.

La prueba que realmente importa acá

La versión fácil de esta prueba llama a defaultFonts() y verifica que las fuentes se vean bien: nombre, peso, que los datos sean un Buffer real con contenido real. Es una prueba válida, pero pasaría igual sin importar si la memoización funcionara o no, porque solo llama la función una vez.

La prueba que realmente demuestra algo la llama dos veces y verifica identidad, no igualdad:

test('defaultFonts memoizes - repeat calls return the identical buffer instances', async () => {
  const first = await defaultFonts();
  const second = await defaultFonts();
  assert.equal(first, second, 'should return the same cached array, not a fresh one');
  assert.equal(first[0].data, second[0].data, 'should return the same buffer instance');
});

assert.equal sobre dos Buffers verifica identidad de referencia acá, no igualdad de contenido byte por byte como haría assert.deepEqual. Dos buffers recién decodificados con los mismos bytes fallarían esta prueba, y ese es justamente el punto. Todo el bug era “decodifica los mismos bytes dos veces,” así que una verificación de igualdad de contenido pasaría sin problema incluso en la versión rota. La única prueba capaz de distinguir “memoizado” de “no memoizado, pero consistente” es una que verifique que ambas llamadas devolvieron literalmente el mismo objeto.

Por qué valía la pena hacer este fix

Es un fix pequeño para un problema pequeño. Que un solo build decodifique un par de cientos de KB de base64 unas cuantas docenas de veces de más no le va a arruinar el día a nadie. Pero se acumula de forma invisible: un sitio con cien posts que genera una tarjeta por post paga este costo cien veces por cero beneficio, y nada en el síntoma (un build un poco más lento) apunta hacia la decodificación de la fuente como causa. Barato de arreglar, fácil de pasar por alto, exactamente el perfil de bug que vale la pena sacar del backlog incluso cuando todavía nadie se está quejando.

Lecturas relacionadas