Llamadas de función en Rust: ¿realmente cuestan tanto?

Fuentes: The Cost of Indirection in Rust

Este artículo aborda una preocupación común en programación, especialmente en Rust: el costo de la indirección, es decir, la sobrecarga de las llamadas a funciones. La advertencia habitual es "cada llamada de función adicional añade sobrecarga, inlínala". Sin embargo, en el contexto del código asíncrono de Rust, esta preocupación suele ser infundada. El artículo explica que, aunque técnicamente existen costos asociados con la indirección (pases de parámetros, configuración de la máquina de estados del futuro, pinning, etc.), el compilador a menudo optimiza este código, incluso llegando a fusionar el estado de la función llamada en la máquina de estados del futuro llamador, eliminando efectivamente la sobrecarga.

El autor utiliza un ejemplo concreto: extraer un bloque de código extenso (más de 20 líneas) de un match arm en una función asíncrona a una función separada (handle_suspend). Si bien esto mejora la legibilidad y la modularidad, algunos desarrolladores pueden preocuparse por la llamada de función adicional. El artículo argumenta que esta preocupación es a menudo exagerada, ya que el compilador puede optimizar la llamada, y la sobrecarga real es insignificante en comparación con otras operaciones, como las operaciones de E/S, las esperas de bloqueos o las asignaciones de memoria. Además, el compilador puede incluso inlinar la función extraída en tiempo de compilación, eliminando por completo la sobrecarga.

El artículo proporciona ejemplos de código y un enlace a un repositorio con benchmarks para demostrar que la diferencia de rendimiento entre el código inlinado y el código con indirección es a menudo despreciable. Incluso cuando existe una diferencia, es probable que sea eclipsada por otros factores. El autor enfatiza que la verdadera penalización de eliminar la indirección no es la sobrecarga de rendimiento, sino la pérdida de legibilidad, mantenibilidad y productividad del desarrollador. La complejidad adicional de mantener código inlinado, especialmente en sistemas grandes, puede superar con creces cualquier ganancia de rendimiento marginal. El artículo concluye que es mejor confiar en el optimizador del compilador y priorizar la claridad del código, reservando la optimización manual solo para casos donde se ha medido un problema real y no hay una mejor alternativa.