Vec<T> es un array dinámico y creciente que almacena elementos en un único bloque de memoria asignado (en el heap). La adición de un nuevo elemento (push) aumenta la longitud y, si es necesario, se asigna nueva memoria (re-asigna). Durante el push, la capacidad se incrementa exponencialmente para evitar reasignaciones constantes. Al eliminar un elemento (pop/remove), la capacidad no disminuye automáticamente.
Un problema común son las asignaciones excesivas y realocaciones al añadir continuamente.
Ejemplo de trabajo con asignación previa:
let mut v = Vec::with_capacity(1000); for i in 0..1000 { v.push(i); } assert_eq!(v.capacity(), 1000);
Pregunta: ¿Qué ocurrirá con la capacidad de vec después de llamar a v.shrink_to_fit()? ¿Será igual a la longitud?
Respuesta incorrecta: Sí, siempre, después de shrink_to_fit capacidad == len.
Respuesta correcta: No necesariamente, la implementación de shrink_to_fit es un "deseo" para el asignador. Normalmente, se busca la capacidad mínima posible, y pueden existir particularidades según la implementación del asignador (por ejemplo, puede permanecer por encima de la longitud).
Ejemplo:
let mut v = Vec::with_capacity(10); for i in 0..5 { v.push(i); } v.shrink_to_fit(); // capacidad ≥ len (5), pero no se garantiza que sean iguales
Historia
Un desarrollador empujaba repetidamente objetos en Vec sin establecer la capacidad, lo que resultaba en un crecimiento exponencial de la realocación con grandes volúmenes de datos, ralentizando todo el procesamiento en "ciclos pesados". La optimización usando
with_capacityredujo el tiempo en 10 veces.
Historia
El equipo intentó ahorrar memoria llamando regularmente a
shrink_to_fitdespués de cada pop(). Como resultado, surgieron ciclos constantes de realocate/free y degradación del rendimiento, casi provocando un DoS del servicio.
Historia
Mantuvieron Vec como un campo de una estructura con referencias internas a sus elementos. Después de una realocación (push más allá de la capacidad), las referencias se invalidaron, y los errores resultantes fueron difíciles de rastrear hasta que se ejecutó en producción.