7,8 Mo de clés que j'ai allouées juste pour les jeter
Un profiler a révélé un coût caché dans mon code.
Mon gestionnaire de requêtes lit des jetons à partir d'une chaîne de caractères massive et additionne leurs poids. La logique fonctionnait, mais pas la mémoire.
À l'intérieur d'une boucle critique, j'ai alloué 7,8 Mo de chaînes de caractères — une nouvelle clé pour chaque recherche dans le dictionnaire — avant de la jeter immédiatement.
Le coupable était Substring. Chaque segment créait un nouvel objet string.
200 000 jetons
- Méthode A (Substring) : 23,4 ms, 7 812 Ko alloués.
- Méthode B (Span Lookup) : 14,9 ms, 0 Ko alloués.
La méthode B est 1,5× plus rapide et ne génère aucun déchet.
Dans .NET 9, vous pouvez appeler GetAlternateLookup. Au lieu d'une nouvelle chaîne, vous passez un ReadOnlySpan<char>, qui n'est qu'une fenêtre sur la chaîne d'origine — sans copie.
Le dictionnaire calcule le hash du span directement par rapport aux clés existantes, offrant le même résultat sans l'allocation.
Choses à retenir
- Fonctionne avec
StringComparer.OrdinaletStringComparer.OrdinalIgnoreCase. - Lève une exception à l'exécution si vous utilisez un comparateur personnalisé qui ne prend pas en charge l'alternate lookup.
- Idéal pour les chemins critiques (hot paths) tels que les parseurs, les processeurs de logs ou les scanners CSV.
- À éviter pour les recherches simples avec seulement quelques clés.
Je traque désormais dans mon code les Substring suivis de TryGetValue. Ce motif gaspille des quantités massives de mémoire.
Source: https://dev.to/ssukhpinder/78-mb-of-keys-i-allocated-just-to-throw-away-50mn
Optional learning community: https://github.com/ssukhpinder/dev-to-code-samples/tree/main/023-dictionary-alternate-lookup
