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.Ordinal et StringComparer.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