Optimización en C para procesamiento en tiempo real
En esta entrada exploraremos algunas estrategias comunes para optimizar código en C cuando se requiere procesamiento en tiempo real. Estas técnicas son aplicables en proyectos de audio digital, sistemas embebidos o control de señales.
⚙️ Gestión eficiente de memoria
El acceso a memoria puede ser un cuello de botella en sistemas embebidos. Siempre que sea posible, evita asignaciones dinámicas dentro de bucles o funciones críticas.
Utiliza static o buffers globales para reducir la sobrecarga del malloc y free.
// Ejemplo: evitar malloc en bucle de tiempo real
#define BUFFER_SIZE 256
void processAudio(float *input, float *output) {
static float buffer[BUFFER_SIZE]; // memoria persistente en stack
for (int i = 0; i < BUFFER_SIZE; i++) {
output[i] = buffer[i] = 0.8f * input[i]; // procesamiento simple
}
}
🔁 Uso de buffers circulares
Los buffers circulares son útiles para almacenar flujos de datos continuos (por ejemplo, muestras de audio) sin necesidad de mover memoria constantemente.
// Ejemplo de buffer circular
#define SIZE 1024
float circularBuffer[SIZE];
int writeIndex = 0;
void addSample(float sample) {
circularBuffer[writeIndex] = sample;
writeIndex = (writeIndex + 1) % SIZE; // vuelve al inicio automáticamente
}
⚡ Inlining y macros
Las funciones pequeñas llamadas frecuentemente pueden declararse como inline para evitar la sobrecarga de llamada a función.
Esto mejora la velocidad en bucles intensivos, aunque puede aumentar el tamaño del binario.
// Ejemplo de función inline
static inline float fastMultiply(float a, float b) {
return a * b;
}
void process(float *in, float *out, int N) {
for (int i = 0; i < N; i++) {
out[i] = fastMultiply(in[i], 0.5f);
}
}
🧠 Consideraciones finales
- Evita funciones costosas dentro del bucle principal (
printf,malloc, etc.). - Usa variables
volatilesolo cuando realmente se compartan entre interrupciones o hilos. - Analiza el rendimiento con herramientas como
gprofoperf. - Compila con optimizaciones del compilador:
-O2o-O3.