La memoización (o memorización) es una técnica de programación para optimizar el rendimiento de funciones almacenando los resultados de llamadas previas y reusándolos cuando se producen entradas iguales. Cada vez que una función recibe unos mismos argumentos y devuelve un mismo resultado, ese resultado puede guardarse en una tabla (por ejemplo, una matriz asociativa o un mapa). Antes de computar de nuevo, la función consulta esa tabla de búsqueda y, si encuentra el valor, lo devuelve inmediatamente, evitando así un cálculo costoso. Esta tabla actúa como una caché local con políticas de tamaño y eliminación (por ejemplo, eliminar entradas que no se han usado durante un tiempo determinado).

Aunque relacionada con el almacenamiento en caché general, la memoización se aplica específicamente a la optimización de funciones puras y a evitar repetición de trabajo interno de algoritmos (por ejemplo, en recursividad). Se distingue de otros mecanismos de caching como el buffering o el reemplazo de páginas por su ámbito y objetivo. En algunos lenguajes de programación lógica, la memoización también se denomina tabulación; véase también tabla de búsqueda.

Cómo funciona (resumen práctico)

El flujo típico de memoización es:

  • Crear una tabla vacía asociada a la función.
  • Cuando la función se invoca, construir una clave representativa de los argumentos (por ejemplo, un string o una tupla).
  • Buscar la clave en la tabla: si existe, devolver el resultado almacenado; si no, calcular el resultado, almacenarlo bajo la clave y devolverlo.

Ejemplos comunes

Un ejemplo clásico es la función recursiva de Fibonacci. Sin memoización, la versión recursiva recalcula muchas subllamadas; con memoización, cada subresultado se calcula una vez y se reutiliza.

// Pseudocódigo memo = {} function fib(n):   if n in memo: return memo[n]   if n < 2: result = n   else: result = fib(n-1) + fib(n-2)   memo[n] = result   return result 

En lenguajes modernos existen ayudas: en Python se puede usar functools.lru_cache; en JavaScript se suele crear una función envolvente que use un Map como caché.

Diferencias con tabulación (programación dinámica)

La memoización es una estrategia top-down: se empieza por la llamada que el programa solicita y se van memoizando subproblemas según aparecen. La tabulación (bottom-up) construye de forma iterativa la solución de los subproblemas más pequeños hacia los mayores, normalmente usando una tabla predefinida. Ambas reducen la redundancia de cálculo, pero difieren en orden de cómputo y en gestión de memoria.

Consideraciones y limitaciones

  • Idempotencia y efectos colaterales: solo es segura con funciones deterministas y sin efectos secundarios (no debe aplicarse si el resultado depende de estado externo o produce efectos).
  • Claves y tipos mutables: usar argumentos mutables como claves puede producir resultados inesperados; se recomienda transformar argumentos en valores inmutables o serializables para la clave.
  • Consumo de memoria: almacenar muchos resultados puede agotar memoria; conviene aplicar políticas de límite (por número de entradas o por tiempo).
  • Invalidez de caché: cuando cambian condiciones externas (configuración, datos), hay que invalidar o limpiar la tabla para evitar usar resultados obsoletos.
  • Hilos y concurrencia: en entornos multihilo hay que sincronizar el acceso a la tabla para evitar condiciones de carrera.
  • No apta para funciones no puras: funciones que leen datos globales cambiantes, generan números aleatorios o dependen de la hora no deben memoizarse sin controles adicionales.

Buenas prácticas

  • Limitar el tamaño de la caché (por ejemplo, LRU) para controlar memoria.
  • Elegir una estrategia de clave robusta que refleje exactamente la identidad de la llamada.
  • Proveer mecanismos de limpieza (TTL, invalidación manual, políticas basadas en uso).
  • Documentar qué funciones están memoizadas y por qué (impacto en coherencia de datos).
  • Medir el beneficio: la memoización introduce overhead extra (comprobación de la tabla) que compensa solo si las llamadas repetidas son frecuentes y el cálculo original es costoso.

Conclusión

La memoización es una técnica simple y poderosa para optimizar funciones cuando existen llamadas repetidas con los mismos argumentos. Bien aplicada, puede transformar algoritmos exponenciales en lineales o polinomiales. Sin embargo, requiere atención en la gestión de memoria, en la pureza de las funciones y en la implementación de políticas de caché adecuadas para evitar problemas de coherencia y consumo excesivo de recursos.