Vec<T> est un tableau dynamique, extensible, qui stocke les éléments dans un seul bloc de mémoire alloué (sur le tas). L'ajout d'un nouvel élément (push) augmente la longueur, et si nécessaire, une nouvelle mémoire est allouée (réallocation). Lors du push, la capacité est augmentée exponentiellement pour éviter des reallocations constantes. La capacité ne diminue pas automatiquement lors de la suppression d'un élément (pop/remove).
Un problème fréquent est les allocations excessives et les reallocations lors d'ajouts constants.
Exemple de travail avec allocation préalable:
let mut v = Vec::with_capacity(1000); for i in 0..1000 { v.push(i); } assert_eq!(v.capacity(), 1000);
Question : Que se passera-t-il avec la capacité de vec après l'appel à v.shrink_to_fit() ? Sera-t-elle exactement égale à la longueur ?
Mauvaise réponse : Oui, toujours, après shrink_to_fit capacity == len.
Bonne réponse : Pas nécessairement, l'implémentation de shrink_to_fit est un "souhait" pour l'allocateur. En général, elle tend vers la capacité minimale possible, des particularités peuvent exister selon l'implémentation de l'allocateur (par exemple, elle peut rester supérieure à la longueur).
Exemple :
let mut v = Vec::with_capacity(10); for i in 0..5 { v.push(i); } v.shrink_to_fit(); // capacity ≥ len (5), mais pas garanti qu'elle soit == len
Histoire
Un développeur a multiplié les push d'objets dans Vec sans définir la capacité, ce qui entraînait une croissance exponentielle des reallocations avec de grands volumes de données, ralentissant l'ensemble du traitement dans des "boucles lourdes". L'optimisation avec
with_capacitya réduit le temps par 10.
Histoire
L'équipe a tenté d'économiser de la mémoire en appelant régulièrement
shrink_to_fitaprès chaque pop(). Cela a finalement entraîné des boucles de reallocations/libérations constantes et une dégradation des performances, frôlant le service avec un DoS.
Histoire
Ils ont laissé Vec comme champ d'une structure avec des références internes à ses éléments. Après réallocation (push au-delà de la capacité), les références ont été invalidées — les bugs qui en ont résulté étaient difficiles à détecter jusqu'au déploiement en production.