La CPU de la consola portátil Playdate opera muy rápido, pero acceder a la memoria principal, especialmente cuando los datos no están ya en la caché, es comparativamente lento. Esta asimetría significa que los programas que mantienen sus datos de trabajo en registros y su código más frecuentemente ejecutado dentro de la limitada caché de instrucciones pueden alcanzar casi la velocidad máxima, incluso si contienen muchos loops o sufren fallos de predicción de ramas. Por consiguiente, los desarrolladores que buscan cargas de trabajo de alto rendimiento, como emuladores o simuladores, deben priorizar minimizar el tráfico hacia la lenta memoria principal maximizando el uso de registros y haciendo que el bucle principal quepa ajustadamente dentro de la caché de instrucciones.

Para reducir el footprint de la caché de instrucciones, el autor recomienda compilar con -Os en lugar de -O3, recortar las tablas switch grandes en menos ramas y aislar los opcodes poco usados o casos extremos fuera del núcleo caliente. Al marcar funciones con __attribute__((section (``.text.<name>'')) ) y utilizar un script de enlazado personalizado copiado de la carpeta C_API/buildsupport del SDK, el enlazador puede colocar todas las funciones núcleo en un bloque contiguo único, cuyo tamaño puede inspeccionarse con nm Source/pdex.elf | sort > syms.txt. Para los datos, la región de memoria acoplada estrechamente (TCM)—donde reside la pila de hardware—ofrece un acceso más rápido que la RAM ordinaria; los objetos asignados en la pila se ejecutan entonces más rápidamente, y los desarrolladores pueden usar memcpy para copiar estructuras de heap o estáticas a un área reservada de baja pila (el dtcm_mempool) durante la duración de un cálculo, copiando el resultado de vuelta posteriormente. Asimismo, las funciones pueden marcarse para la región TCM de instrucciones (ITCM) mediante un macro que agrega __attribute__((section (``.itcm. '')) ) __attribute__((short_call)), copiado de .text a TCM en tiempo de ejecución con atención cuidadosa a la congruencia de direcciones módulo 2, los atributos short_call/long_call y vaciando la caché de instrucciones después de la copia.

Incluso después de aplicar los trucos anteriores, las compilaciones pueden mostrar una ``lotería de rendimiento'' donde cambios aparentemente no relacionados provocan grandes oscilaciones impredecibles en la velocidad. Esto se debe a dos efectos de hardware: el desalineamiento de líneas de caché (el tamaño de línea de 32 bytes significa que una función cuya dirección de inicio no es múltiplo de 32 puede cruzar dos líneas, arrastrando vecinos no deseados o dejando código útil sin caché) y la tabla de predicción de ramas, donde las direcciones de instrucción que difieren en múltiplos de 1024 pueden compartir las mismas entradas de predictor, provocando fallos de predicción. La mitigación implica alinear deliberadamente funciones y bucles a límites de 32 bytes en el mapa de enlazado (. = ALIGN(32); . += offset) o con indicadores del compilador como -falign-loops=32, y esparcir . = ALIGN(1024); . += n opciones basadas en una compilación conocida buena para decorrelacionar los índices de predictor. Aunque la prefetch ha mostrado un beneficio limitado en la Playdate, estas técnicas de alineación han eliminado en gran medida el efecto de la lotería de rendimiento en la práctica.