¿Cuáles son los métodos generalmente practicados para el uso de memoria del programa de optimización?
(nb. según el comentario de Edgar, enfatizo que se trata de usar PROGMEM de manera más eficiente).
-
Si puede reemplazar el código con una tabla cuyo tamaño sea ≤ las líneas de código, hágalo.
- En lugar de usar una secuencia de ifs, encuentre una manera de colapsar el procedimiento en una tabla
- Use tablas de punteros de función si tiene sentido
- A veces puede encontrar un mini-lenguaje que es mucho más denso que AVR instrucciones, por ejemplo, codificar la lógica del robot en 16 comandos, y luego puede empaquetar dos comandos por byte . Esto podría reducir el uso de la memoria 50 veces.
- Use funciones en lugar de código repetido; esto puede parecer obvio, pero a menudo hay formas sutiles de reescribir el código (pero tenga en cuenta que las llamadas a funciones tienen sobrecarga)
- Use tablas hash en lugar de tablas con grandes espacios
- Use punto fijo en lugar de punto flotante (por ejemplo, puede tomar un byte e interpretar su valor como un rango de 0.00 a 2.55, en lugar de usar un flotante de 4 bytes)
¿Hay alguna diferencia en el uso de la memoria si la variable se declara global o localmente?
Hablemos de la pila.
void A () {byte a [600]; ...} void B () {byte b [400]; ...} bucle vacío () {byte xxx [1000]; ...}
Este programa primero utilizará al menos 1000 bytes de RAM todo el tiempo. No hay una diferencia real en comparación con declarar xxx a nivel mundial. Pero entonces lo que es crítico es qué función llama a cuál.
Si loop () llama a A (), y luego loop () llama a B (), el programa no usará más de 1600 en ningún momento. Sin embargo, si A () llama B (), o viceversa, el programa usará 2000. Para ilustrar:
loop () [1000] └── ── A () [1600] │ [1000] └──── B () [1400] └──── A () [1600] └──── B () [1400]
versus
loop () [1000] └──── A () [1600]
└──── B () [2000] │ [1000] └──── A () [1600] └──── B () [2000]
¿Importará cuáles son las declaraciones de control / selección (como if, switch)
No hay mucha diferencia para un pequeño número de casos. De lo contrario, depende de su código. La mejor manera es probar ambos y ver cuál es mejor. Pero:
switch
es usualmente usan tablas de salto que son bastante compactas si cubre casi todos los casos en un rango (0,1,2,3,4, .., 100 ). Los if
usualmente usan una secuencia de instrucciones, que ocupan más bytes y ciclos que una entrada de tabla de salto, pero tiene más sentido si no tiene un tramo consecutivo de casos.
Uso del monitor serial. Serial.print ()
No creo que eso marque la diferencia. Los búferes de serie son pequeños (digamos 64 bytes o 128 para una placa más grande) y creo que se asignan tanto si usa Serial como si no.
Por supuesto, "cadenas literales como esta" y búferes char [] consumen memoria. Puede comentarlos (o usar #ifdef
s) cuando no los necesite.