7.8 MB की Keys जिन्हें मैंने सिर्फ बर्बाद करने के लिए एलोकेट किया था
एक profiler ने मेरे कोड में एक छिपी हुई लागत (hidden cost) को उजागर किया।
मेरा request handler एक बहुत बड़ी string से tokens पढ़ता है और उनके weights का योग करता है। लॉजिक तो काम कर रहा था, लेकिन मेमोरी नहीं।
एक hot loop के अंदर, मैंने 7.8 MB की strings एलोकेट कीं—हर dictionary lookup के लिए एक नई key—और फिर तुरंत उस key को फेंक दिया।
इसका मुख्य कारण Substring था। हर slice एक नया string object बना रहा था।
200,000 tokens
- Method A (Substring): 23.4 ms, 7,812 KB एलोकेट हुए।
- Method B (Span Lookup): 14.9 ms, 0 KB एलोकेट हुए।
Method B 1.5× तेज़ चलता है और कोई garbage जनरेट नहीं करता।
.NET 9 में आप GetAlternateLookup को कॉल कर सकते हैं। एक नई string के बजाय, आप ReadOnlySpan<char> पास करते हैं, जो मूल string पर केवल एक window की तरह है—इसमें कोई copying नहीं होती।
Dictionary सीधे existing keys के खिलाफ span को hash करती है, जिससे बिना किसी allocation के वही परिणाम मिलता है।
याद रखने योग्य बातें
StringComparer.OrdinalऔरStringComparer.OrdinalIgnoreCaseके साथ काम करता है।- यदि आप किसी ऐसे custom comparer का उपयोग करते हैं जिसमें alternate lookup सपोर्ट नहीं है, तो यह runtime पर exception throw करेगा।
- Parsers, log processors, या CSV scanners जैसे hot paths के लिए आदर्श है।
- केवल कुछ ही keys वाले साधारण lookups के लिए इसका उपयोग न करें।
अब मैं अपने कोड में Substring के बाद TryGetValue के पैटर्न को ढूंढता हूँ। वह पैटर्न भारी मात्रा में मेमोरी बर्बाद करता है।
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
