|

Optimizar memoria AWS Graviton con ASCT: la guía técnica

Ponele que migrás un servicio de Java a una instancia AWS Graviton porque te prometieron mejor relación precio/rendimiento, lo probás y anda más lento que en x86. ¿El problema? Casi nunca es el CPU. Es cómo tu código toca la memoria. Optimizar memoria AWS Graviton con ASCT empieza por medir latencias y bandwidth reales antes de tocar una sola línea.

El Arm System Characterization Tool (ASCT) es una utilidad de Arm para caracterizar el subsistema de memoria de procesadores ARM64. En AWS Graviton mide la topología de cores, la jerarquía de caché (L1, L2, L3), la configuración NUMA, la latencia de acceso y el ancho de banda de streaming. Sirve para diagnosticar cuellos de botella en aplicaciones memoria-bound y ajustar el código a cada generación de Graviton.

En resumen

  • ASCT mide topología de CPU, cachés, NUMA, latencia y bandwidth en instancias Graviton con técnicas de bajo nivel como pointer chasing.
  • Graviton4 tiene menos latencia en L2/L3 que Graviton2 y caché L3 más grande (36 MB por socket vs 32 MB).
  • El bandwidth single-core de Graviton4 es bastante superior al de Graviton2 según las mediciones de la fuente.
  • NUMA importa: Graviton2 es single socket, Graviton4 puede ser dual socket. Cruzar sockets agrega latencia.
  • La clave práctica: mantené tu working set dentro de L2 y evitás los “memory cliffs” que matan el rendimiento.

¿Por qué es crítica la eficiencia de memoria en workloads Graviton?

La velocidad de cómputo del CPU es solo una parte de la historia. Cuando tu aplicación es memoria-bound (pasa más tiempo esperando datos que calculando), lo que manda es qué tan rápido el procesador puede traer esos datos desde la caché o la DRAM.

Acá viene lo importante: cada nivel de caché tiene una latencia distinta. L1 responde en unos nanosegundos, L2 un poco más, L3 bastante más, y la DRAM física puede tardar 100 ns o más. Si tu working set (el conjunto de datos que tu código toca activamente) entra en L2, volás. Si se desborda y cae a L3 o a DRAM, te pegás contra lo que se conoce como “performance cliff”: el rendimiento se cae a un pozo de golpe, no de a poco.

¿Y por qué Graviton específicamente? Porque entre generaciones Amazon cambió cosas que importan mucho acá: tamaños de caché, tipo de DRAM (DDR4 a DDR5), y la cantidad de sockets. Lo que funcionaba bárbaro en Graviton2 puede comportarse distinto en Graviton4. Medir es la única forma de saberlo. Esto se conecta con lo que analizamos en pipelines de CI/CD en instancias Graviton.

¿Qué es ASCT y cómo caracteriza el subsistema de memoria?

El Arm System Characterization Tool es la herramienta que usa el autor del artículo original en dev.to para meterse abajo del capó. No es un benchmark sintético de marketing. Mide el sistema como es, con técnicas pensadas para esquivar trampas comunes.

La principal trampa son los prefetchers. El hardware moderno adivina qué dato vas a pedir después y lo trae antes. Eso está buenísimo para la app real, pero arruina una medición de latencia: si medís un acceso secuencial, el prefetcher ya tiene el dato listo y vas a creer que la DRAM es rapidísima. Mentira.

Para esquivarlo, ASCT usa pointer chasing: arma una cadena de punteros donde cada acceso depende del anterior, en orden aleatorio. Así el prefetcher no puede adivinar nada y medís la latencia de round-trip real, la que de verdad va a sufrir tu código cuando salta por una estructura de datos dispersa en memoria.

¿Qué te devuelve concretamente? La topología de cores, la estructura de cachés verificada (no la que dice la spec sino la que mide), la configuración NUMA, y números de latencia y bandwidth por nivel.

¿Cómo explorar topología CPU y NUMA en Graviton con ASCT?

Antes de correr un solo benchmark, tenés que entender cómo está organizado el sistema. Cuántos cores, cómo se agrupan, cuántos nodos NUMA hay. Esto cambia radicalmente entre generaciones.

Graviton2 es un solo socket, con hasta 64 cores y un único nodo NUMA. Eso simplifica la vida: cualquier core accede a cualquier porción de memoria con una latencia parecida, no hay que preocuparse por dónde “vive” cada dato. Para más detalles técnicos, mirá ejecutar builds en procesadores ARM.

Graviton4 cambió el juego. Las instancias más grandes pueden venir con dos sockets y, por lo tanto, con NUMA real (hasta 96 cores en las configuraciones top). Acá sí importa dónde corre tu thread y dónde está su memoria. Si un core del socket 0 tiene que ir a buscar datos a la DRAM del socket 1, paga un peaje de latencia por cruzar el interconnect.

Eso sí: para muchas instancias single-socket de Graviton4 este problema no existe. Por eso primero identificás la topología con ASCT y recién después decidís si tenés que hacerte cargo de NUMA o no. Asumir sin medir es el error clásico.

¿Cómo medir latencia de memoria con benchmarks?

La técnica, ya lo dijimos, es pointer chasing. Cadena de dependencias que obliga al procesador a esperar cada acceso antes de lanzar el siguiente. Eso te da la latencia pura de cada nivel de la jerarquía.

Los rangos típicos que vas a ver en Graviton, según las mediciones de la fuente:

  • L1: entre 4 y 5 ns. Es la caché más cercana al core, la que querés que tenga tus datos calientes.
  • L2: entre 4 y 5,4 ns. Todavía rapidísima. Acá es donde querés que viva tu working set.
  • L3: entre 10 y 15 ns. Compartida entre cores, ya empezás a notar la diferencia.
  • DRAM: 100 ns o más. El abismo. Cada vez que caés acá, perdés un orden de magnitud.

El dato fuerte de la comparación generacional: Graviton4 mide menos latencia en L2 y L3 que Graviton2. No es magia, es ingeniería. Cachés más grandes y mejor diseñadas hacen que tu working set entre con más holgura y que los accesos compartidos cuesten menos.

¿Cómo medir bandwidth de memoria?

La latencia te dice cuánto tarda un acceso. El bandwidth te dice cuántos datos podés mover por segundo. Para workloads de streaming (procesar arrays gigantes de punta a punta) el bandwidth es lo que manda. Complementá con servir contenido desde múltiples regiones.

ASCT corre tests de bandwidth single-core y multi-core. Lo que destaca la fuente: Graviton4 alcanza un pico de streaming bastante superior al de Graviton2. El salto se explica en buena parte por el paso a memoria DDR5.

Ojo con un detalle que casi siempre se ignora. El throughput teórico que figura en la spec y el throughput real bajo contención son dos cosas distintas. Cuando 64 cores le pegan a la memoria al mismo tiempo, el bandwidth por core baja porque el bus se satura. Por eso el test multi-core importa tanto: te muestra qué pasa de verdad cuando tu app escala, no en el papel.

¿Cuáles son los cambios de memoria entre Graviton2, Graviton4 y Graviton5?

Acá la tabla comparativa con lo que cambió entre generaciones. Una aclaración de entrada: los datos de Graviton5 son especulativos. Amazon no publicó specs oficiales todavía, así que tomalo con pinzas. Lo de Graviton2 y Graviton4 sale de las mediciones de la fuente.

CaracterísticaGraviton2Graviton4Graviton5 (especulativo)
Caché L164 KB/core64 KB/core64 KB/core
Caché L21 MB2 MB2 MB
Caché L3 (por socket)32 MB36 MB~12 MB
DRAMDDR4DDR5DDR5+
NUMASingle socketHasta dual socketSingle socket
Latencia L2/L3ReferenciaMenorSin datos
optimizar memoria aws graviton diagrama explicativo

El cambio más visible es la caché L3: de 32 MB en Graviton2 a 36 MB por socket en Graviton4. Eso es muchísimo más espacio para que tus datos compartidos no caigan a DRAM. Sumale el salto de DDR4 a DDR5 y entendés de dónde viene la mejora de bandwidth.

¿Cómo usar los insights de ASCT para optimizar aplicaciones?

Medir está bien, pero el objetivo es que tu app vaya más rápido. Estas son las estrategias concretas que salen de caracterizar el subsistema de memoria. Tema relacionado: ejecutar workloads sin dependencias externas.

  • Mantené el working set dentro de L2. Si sabés que L2 son 2 MB en Graviton4, diseñá tus estructuras para que el conjunto activo entre ahí. Procesar en bloques (tiling) en vez de barrer arrays enormes de una es la técnica clásica.
  • Evitá los memory cliffs. Si tu dataset está justo en el borde de un nivel de caché, un pequeño aumento te tira al pozo. Conocé los tamaños exactos y dejá margen.
  • Compilá para ARM64 de verdad. Usá flags optimizados para la arquitectura objetivo (por ejemplo -mcpu=neoverse-v2 para Graviton4) en vez de un binario genérico. El compilador puede generar mejores patrones de acceso.
  • Hacete cargo de NUMA en Graviton4 dual socket. Pineá threads y memoria al mismo nodo con herramientas como numactl. No dejes que el scheduler reparta los datos cruzando sockets.
  • Considerá prefetching manual. Si tu patrón de acceso es predecible pero el prefetcher de hardware no lo agarra, un prefetch explícito puede ayudar.

Si tu workload corre en infraestructura propia o gestionás VPS y servidores para tus proyectos, podés aplicar la misma lógica de caracterización antes de elegir el tamaño de instancia. Para alojamiento web y dominios en Argentina, donweb.com es una opción local a tener en cuenta.

Errores comunes al optimizar memoria en Graviton

  • Medir con accesos secuenciales. El prefetcher te miente. Si no usás pointer chasing o acceso aleatorio, tus números de latencia van a estar inflados y vas a tomar decisiones equivocadas.
  • Asumir que Graviton4 siempre tiene NUMA. Muchas instancias son single socket. Optimizar para NUMA donde no hay NUMA agrega complejidad inútil. Medí primero.
  • Usar binarios x86 recompilados a la rápida. Compilar sin flags específicos de la arquitectura deja rendimiento sobre la mesa. El binario funciona, pero no aprovecha lo que el chip puede dar.
  • Confiar en el bandwidth teórico de la spec. Bajo contención multi-core el número real es bastante menor. Si dimensionás tu app con el pico teórico, te vas a quedar corto.

Preguntas Frecuentes

¿Qué es ASCT y para qué sirve en Graviton?

ASCT (Arm System Characterization Tool) es una herramienta de Arm que mide el subsistema de memoria de procesadores ARM64. En Graviton sirve para identificar la topología de cores, verificar la jerarquía de caché, detectar la configuración NUMA y medir latencia y ancho de banda reales, sin que los prefetchers distorsionen los resultados.

¿Cómo analizar la memoria en instancias AWS Graviton?

Primero identificás la topología (cores, cachés, NUMA) con ASCT. Después corrés benchmarks de latencia con pointer chasing para medir cada nivel de la jerarquía y tests de bandwidth single-core y multi-core para el throughput de streaming. Con esos números detectás si tu app es memoria-bound y dónde está el cuello de botella.

¿Cuáles son las latencias de memoria en Graviton2 vs Graviton4?

Según las mediciones de la fuente, los rangos típicos son L1 de 4 a 5 ns, L2 de 4 a 5,4 ns, L3 de 10 a 15 ns y DRAM más de 100 ns. Graviton4 muestra menos latencia en L2 y L3 que Graviton2, gracias a cachés más grandes y mejor diseño.

¿Qué impacto tiene NUMA en el rendimiento de Graviton?

En Graviton2 (single socket) NUMA no es un problema porque hay un solo nodo. En instancias Graviton4 dual socket sí: si un thread accede a memoria de otro socket, paga latencia extra por cruzar el interconnect. La solución es pinear threads y memoria al mismo nodo con herramientas como numactl.

¿Cómo optimizar aplicaciones para mejor uso de caché en Graviton?

Mantené el working set dentro de L2 procesando en bloques (tiling), evitá los memory cliffs dejando margen respecto al tamaño de cada nivel de caché, y compilá con flags específicos de ARM64. En workloads con patrones predecibles, el prefetching manual también puede ayudar.

Conclusión

Lo que cambió acá no es Graviton: es la posibilidad de medirlo con precisión antes de adivinar. ASCT te saca la venda de los ojos y te muestra las latencias y el bandwidth reales de cada generación, con la diferencia clave de que Graviton4 tiene cachés mucho más grandes (36 MB de L3 por socket), menos latencia en L2/L3 y bandwidth de streaming bastante superior al de Graviton2.

¿Qué hacer con esto? Si tenés un workload memoria-bound corriendo en Graviton, caracterizalo con ASCT antes de cambiar de instancia o reescribir código. Mantené el working set en L2, fijate si tu instancia tiene NUMA, compilá para la arquitectura correcta. La ganancia de rendimiento casi siempre está en cómo tocás la memoria, no en cuántos GHz tenés.

Fuentes

Te puede interesar...