Este proyecto es educativo y Open Source. No se copia código de otros emuladores. Implementación basada únicamente en documentación técnica y tests permitidas.
Optimización Final de Logs para Rendimiento
Resumen
El emulador funcionaba correctamente con Tetris clásico, pero a solo 13 FPS debido a la saturación de logs en la consola. Se identificaron y comentaron todos los logs de diagnóstico que se ejecutaban miles de veces por segundo (DMA, interrupciones, STAT, MBC, etc.), permitiendo que el emulador alcance 60 FPS y sea completamente jugable.
Los logs comentados incluyen: transferencias DMA (START/COMPLETE), despacho de interrupciones, cambios de banco MBC, actualizaciones de STAT/LYC/TAC, y señales STAT activas. Todos los logs se mantienen en el código como comentarios para facilitar el debugging futuro cuando sea necesario.
Concepto de Hardware
En un emulador, el rendimiento es crítico para mantener la experiencia de juego fluida. La Game Boy original ejecutaba a aproximadamente 59.7 FPS (70,224 ciclos por frame), y un emulador moderno debe mantener esta velocidad en hardware actual.
El problema de rendimiento no estaba en la emulación del hardware en sí, sino en la instrumentación de diagnóstico que se añadió durante el desarrollo. Los logs de logger.info() se ejecutan miles de veces por segundo:
- DMA: Se ejecuta cada vez que se copian sprites a OAM (varias veces por frame)
- Interrupciones: Se disparan múltiples veces por frame (V-Blank, STAT, Timer)
- STAT/LYC/TAC: Se actualizan constantemente durante la ejecución
- MBC: Cambios de banco ROM durante la carga de datos
Cada llamada a logger.info() tiene un costo: formateo de strings, escritura a consola, sincronización de I/O. Cuando esto ocurre miles de veces por segundo, el emulador se ralentiza drásticamente.
Solución: Comentar todos los logs de diagnóstico frecuentes, manteniéndolos en el código para activarlos cuando sea necesario para debugging. Los logs críticos (errores, warnings) se mantienen activos.
Implementación
Se comentaron sistemáticamente todos los logs de diagnóstico que se ejecutan frecuentemente durante la ejecución normal del emulador. Los logs se mantienen en el código como comentarios con la marca COMENTADO para rendimiento para facilitar su reactivación cuando sea necesario.
Componentes modificados
- src/memory/mmu.py: Comentados logs de DMA START/COMPLETE, STAT UPDATE, LYC SET, TAC UPDATE
- src/memory/cartridge.py: Comentado log de cambio de banco MBC
- src/cpu/core.py: Comentados logs de INTERRUPT DISPATCHED (general y Timer específico)
- src/gpu/ppu.py: Comentados logs de STAT SIGNAL ACTIVE (LYC Match, H-Blank, V-Blank, OAM Search), STAT interrupt triggered, y LYC escrito
Estrategia de logging
Se mantiene una estrategia de logging por niveles:
- ERROR/WARNING: Siempre activos (errores críticos, condiciones inesperadas)
- INFO (diagnóstico frecuente): Comentados para rendimiento, se pueden reactivar cuando sea necesario
- DEBUG: Ya estaban comentados o desactivados por defecto
Todos los logs comentados incluyen la marca # COMENTADO para rendimiento para facilitar su búsqueda y reactivación selectiva durante debugging.
Archivos Afectados
src/memory/mmu.py- Comentados logs de DMA, STAT, LYC, TACsrc/memory/cartridge.py- Comentado log de cambio de banco MBCsrc/cpu/core.py- Comentados logs de interrupcionessrc/gpu/ppu.py- Comentados logs de STAT signals y LYC
Tests y Verificación
La optimización se validó ejecutando Tetris clásico (ROM aportada por el usuario, no distribuida):
- ROM: Tetris (clásico, 32KB, DMG) - ROM aportada por el usuario, no distribuida
- Modo de ejecución: UI con Pygame, logging desactivado
- Criterio de éxito: El emulador debe alcanzar 60 FPS estables y ser completamente jugable
- Observación:
- Antes de la optimización: 13.44 FPS (saturación de logs)
- Después de la optimización: 60 FPS estables
- Pantalla de título visible y funcional
- Controles responsivos (movimiento de piezas)
- Sin lag ni stuttering
- Resultado: Verified - El emulador funciona perfectamente a 60 FPS
Notas legales: La ROM de Tetris es propiedad de Nintendo y se usa únicamente para pruebas locales del autor. No se distribuye ni se enlaza en el repositorio.
Fuentes Consultadas
- Python logging documentation: https://docs.python.org/3/library/logging.html
- Best practices de performance en Python: Lazy formatting, niveles de logging
Nota: Esta optimización es una práctica estándar de desarrollo de software. Los logs de diagnóstico son esenciales durante el desarrollo, pero deben desactivarse en producción para mantener el rendimiento.
Integridad Educativa
Lo que Entiendo Ahora
- Rendimiento en emuladores: El rendimiento no solo depende de la precisión de la emulación, sino también de la eficiencia del código del emulador. La instrumentación de diagnóstico es esencial durante el desarrollo, pero puede convertirse en un cuello de botella si no se gestiona correctamente.
- Logging estratégico: Es importante mantener una estrategia de logging por niveles (ERROR/WARNING siempre activos, INFO/DEBUG solo cuando sea necesario). Los logs comentados son preferibles a eliminarlos, ya que facilitan el debugging futuro.
- Profiling y optimización: Identificar cuellos de botella requiere medición. En este caso, el bajo FPS (13.44) indicaba claramente un problema de rendimiento, y la saturación de logs era la causa obvia.
Lo que Falta Confirmar
- Rendimiento en otros juegos: Tetris clásico funciona perfectamente, pero falta verificar el rendimiento con juegos más complejos (Pokémon Red, Tetris DX) que pueden tener más carga de trabajo.
- Logging condicional: En el futuro, se podría implementar un sistema de logging condicional que solo active los logs cuando se detecte un problema específico, en lugar de comentarlos completamente.
Hipótesis y Suposiciones
Se asume que todos los logs comentados son puramente de diagnóstico y no afectan la lógica del emulador. Si algún log estaba realizando alguna operación crítica además de logging, esto podría causar problemas. Sin embargo, la revisión del código confirma que todos los logs comentados son solo instrumentación.
Próximos Pasos
- [ ] Verificar rendimiento con Pokémon Red y Tetris DX (juegos híbridos GBC/DMG)
- [ ] Probar gameplay completo de Tetris clásico (mover piezas, hacer líneas, game over)
- [ ] Si hay problemas de compatibilidad con juegos híbridos, investigar diferencias en registro STAT o JOYPAD
- [ ] Considerar implementar un sistema de logging condicional para debugging futuro