Mejorando el rendimiento de MicroPython en sistemas CHERI
Los ajustes en MicroPython mejoran el rendimiento en las plataformas CHERI.
― 6 minilectura
Tabla de contenidos
MicroPython es una versión pequeña del lenguaje de programación Python. Está diseñada para funcionar en microcontroladores, que son computadoras chiquititas usadas en muchos dispositivos. MicroPython ejecuta un tipo de código llamado bytecode, que es una versión simplificada del código que una computadora puede entender.
CHERI significa Instrucciones RISC Mejoradas con Hardware de Capacidad. Es una nueva forma de manejar la memoria de manera segura en sistemas informáticos. La idea detrás de CHERI es agregar soporte especial para punteros, que se usan para acceder a diferentes áreas de memoria. Esto ayuda a prevenir errores cuando un programa intenta usar la memoria de manera incorrecta.
Trasladando MicroPython a CHERI
Cuando intentamos adaptar MicroPython para que funcionara en un sistema CHERI llamado la plataforma Morello, enfrentamos muchos desafíos, especialmente con el rendimiento. Al principio, el rendimiento de MicroPython en CHERI era mucho peor de lo esperado: cinco veces más lento que en un sistema normal.
El problema principal que observamos fue que el sistema de memoria en CHERI funciona de manera diferente a los sistemas tradicionales. Los punteros usados en CHERI son más grandes que en los sistemas regulares, lo que lleva a problemas de rendimiento. Punteros más grandes significan que la computadora tiene que hacer más trabajo para manejar la memoria.
Encontrando los Problemas de Rendimiento
Para mejorar el rendimiento, tuvimos que identificar de dónde venían los problemas. Observamos cómo MicroPython manejaba la memoria y descubrimos que hacía muchas cosas de forma ineficiente. Una de las principales fuentes de lentitud era una función responsable de asignar memoria, llamada gc_alloc()
. Esta función determina dónde almacenar los datos en la memoria.
Cuando probamos los benchmarks, vimos que algunas operaciones tardaban mucho más en CHERI que en un sistema tradicional. Por ejemplo, dos benchmarks, fannkuch y nqueens, eran más de 100 veces más lentos en el sistema CHERI.
Usamos una herramienta llamada pmcstat
para analizar esto y descubrimos que gc_alloc()
se llamaba mucho más a menudo de lo necesario. Esto indicaba que la asignación de memoria estaba causando retrasos.
Mejorando la Asignación de Memoria
Para abordar el problema de la asignación de memoria, primero miramos cómo estaba estructurado MicroPython. La forma en que MicroPython dividía su memoria en bloques estaba basada en el tamaño de los enteros. Para la versión de CHERI, necesitábamos ajustar esta configuración porque los punteros eran más grandes.
Al cambiar el tamaño de los bloques de memoria para tener en cuenta los punteros más grandes, pudimos solucionar algunos de los problemas de rendimiento. Después de este cambio, la lentitud se redujo a aproximadamente 1.8 veces en comparación con el sistema tradicional.
Analizando los Marcos de Pila
Después de abordar el tamaño de los bloques, encontramos que otra área que afectaba el rendimiento era el tamaño de los marcos de pila. Un marco de pila contiene toda la información necesaria para ejecutar una función, incluyendo variables locales y parámetros.
En MicroPython, si el marco de pila se vuelve demasiado grande, se mueve al heap, el área de memoria usada para la asignación dinámica. En CHERI, los marcos de pila eran a menudo mucho más grandes que en un sistema tradicional debido a los punteros más grandes. Esto causaba movimientos más frecuentes al heap, lo que llevaba a caídas en el rendimiento.
Modificamos una constante en MicroPython para considerar el nuevo tamaño de puntero, lo que ayudó a reducir la cantidad de veces que el programa tenía que cambiar al heap para obtener memoria. Este cambio mejoró significativamente el tiempo de ejecución en los benchmarks.
Compilador
Ineficiencias delIncluso después de abordar la gestión de memoria, notamos que el rendimiento en uno de nuestros benchmarks, pystone, seguía siendo deficiente. Descubrimos que el compilador utilizado para convertir el código de MicroPython en instrucciones para el procesador estaba generando instrucciones extra que no eran necesarias.
En programación, cómo un compilador traduce el código en instrucciones de máquina puede impactar enormemente el rendimiento. En nuestro caso, el compilador estaba creando más pasos de los necesarios para varias operaciones, especialmente con la gestión de punteros.
Actualizamos manualmente parte del código compilado para reducir la cantidad de instrucciones innecesarias. Este ajuste manual mejoró aún más el rendimiento en el benchmark de pystone.
Midiendo las Mejoras en Rendimiento
Después de hacer nuestros cambios, seguimos midiendo el rendimiento de MicroPython en el sistema CHERI. Notamos que la mayoría de los benchmarks mostraron una mejora impresionante, con sobrecargas de tiempo de ejecución que bajaron del 48% a casi el 99%, dependiendo de la prueba específica.
El benchmark que mostró la menor mejora aún tenía una lentitud del 137%, mientras que otros tenían sobrecargas entre el 6.7% y el 39%. A pesar de estas mejoras, reconocimos que se podrían lograr más mejoras a medida que la tecnología de hardware y del compilador para CHERI siguiera desarrollándose.
Conclusión: Avanzando con CHERI
Portar software a CHERI y sistemas similares no se trata solo de corregir código. También requiere ajustar cuidadosamente parámetros que dependen de cómo se gestiona la memoria. Los cambios que hicimos en MicroPython demuestran que incluso ajustes simples pueden llevar a mejoras significativas en el rendimiento.
A medida que las herramientas y el hardware para CHERI evolucionen, esperamos que el rendimiento siga mejorando. Este trabajo ilustra la importancia de entender las características únicas de tecnologías nuevas como CHERI al adaptar software existente, especialmente para sistemas que requieren alta eficiencia y seguridad en la gestión de memoria.
Estamos ansiosos por optimizar aún más MicroPython y otras aplicaciones para CHERI y ver los beneficios de este enfoque innovador en la arquitectura informática en varios campos.
Título: CHERI Performance Enhancement for a Bytecode Interpreter
Resumen: During our port of the MicroPython bytecode interpreter to the CHERI-based Arm Morello platform, we encountered a number of serious performance degradations. This paper explores several of these performance issues in detail, in each case we characterize the cause of the problem, the fix, and the corresponding interpreter performance improvement over a set of standard Python benchmarks. While we recognize that Morello is a prototypical physical instantiation of the CHERI concept, we show that it is possible to eliminate certain kinds of software-induced runtime overhead that occur due to the larger size of CHERI capabilities (128 bits) relative to native pointers (generally 64 bits). In our case, we reduce a geometric mean benchmark slowdown from 5x (before optimization) to 1.7x (after optimization) relative to AArch64, non-capability, execution. The worst-case slowdowns are greatly improved, from 100x (before optimization) to 2x (after optimization). The key insight is that implicit pointer size presuppositions pervade systems code; whereas previous CHERI porting projects highlighted compile-time and execution-time errors exposed by pointer size assumptions, we instead focus on the performance implications of such assumptions.
Autores: Duncan Lowther, Dejice Jacob, Jeremy Singer
Última actualización: 2023-09-12 00:00:00
Idioma: English
Fuente URL: https://arxiv.org/abs/2308.05076
Fuente PDF: https://arxiv.org/pdf/2308.05076
Licencia: https://creativecommons.org/licenses/by/4.0/
Cambios: Este resumen se ha elaborado con la ayuda de AI y puede contener imprecisiones. Para obtener información precisa, consulte los documentos originales enlazados aquí.
Gracias a arxiv por el uso de su interoperabilidad de acceso abierto.