பெரிய பஃபர்களை (buffers) அரிதான பிரிப்பான்களைத் (sparse delimiters) தேடி ஸ்கேன் செய்யும் போது, .NET 10-இல் SearchValues<T> ஒரு குறிப்பிடத்தக்கச் சாதகத்தைக் காட்டுகிறது; 32 MB தரவில் SearchValues 3.3 ms-இல் முடிவடைய, IndexOfAny 5.6 ms எடுத்துக்கொள்கிறது.

SearchValues ஏன் அறிமுகப்படுத்தப்பட்டது

ஒரு குறிப்பிட்ட எழுத்துக்களின் (அல்லது பைட்டுகளின்) தொகுப்பை முன்கூட்டியே கணக்கிட்டு (pre-compute), அந்தத் தொகுப்பிற்குத் தேவையான மிக வேகமான ஸ்கேனிங் அல்காரிதத்தை (scanning algorithm) ரன்டைம் (runtime) தேர்ந்தெடுக்க அனுமதிப்பதற்காக .NET 8-இல் SearchValues<T> அறிமுகப்படுத்தப்பட்டது. ஒருமுறை இந்த ஆப்ஜெக்ட்டை உருவாக்கிவிட்டால், ஒரு ஸ்பானில் (span) உள்ள மதிப்புகளைத் தேட வேண்டிய போதெல்லாம் அதை மீண்டும் பயன்படுத்திக்கொள்ளலாம். ரன்டைம், வெக்டரைஸ்டு இன்ஸ்ட்ரக்ஷன்கள் (vectorized instructions), பிரான்ச்-ஃப்ரீ லூப்கள் (branch-free loops) அல்லது கைமுறையாக எழுதப்பட்ட மாற்று வழிகளால் எளிதில் ஈடுசெய்ய முடியாத பிற குறைந்த நிலை நுட்பங்களைப் (low-level tricks) பயன்படுத்தக்கூடும்.

முக்கியமான பெஞ்ச்மார்க் முடிவுகள் (Benchmarks)

விவாதத்தைத் தூண்டிய இந்தச் சோதனைகளில், ஐந்து பிரிப்பான் எழுத்துக்களைக் கொண்ட 32 MB பஃபர் பயன்படுத்தப்பட்டது. .NET 10-இல் மூன்று அணுகுமுறைகள் சோதிக்கப்பட்டன:

  • IndexOfAny(char[]) – 10.2 ms
  • ஸ்பானில் கைமுறையாகச் செய்யப்படும் foreach லூப் (Manual foreach loop over the span) – 19.4 ms
  • SearchValues – 9.7 ms

SearchValues, உள்ளமைக்கப்பட்ட (built-in) IndexOfAny-ஐ விட வெறும் அரை மில்லிசெகண்ட் மட்டுமே வேகமாகச் செயல்பட்டது. இணையதளங்களில் (forums) பரவும் "ஐந்து மடங்கு வேகமானது" என்ற அதீதக் கூற்று இதுவல்ல; நவீன .NET ஏற்கனவே சிறிய தொகுப்புகளுக்கு IndexOfAny-ஐ மேம்படுத்தி (optimize) இருப்பதால், இந்த இடைவெளி குறைவாகவே உள்ளது.

பிரிப்பான்கள் அரிதாக இருக்கும்போது—அதாவது ஒவ்வொரு 60 பைட்டிற்கும் ஒருமுறை தோன்றுவதற்குப் பதிலாக, ஒவ்வொரு 40 KB-க்கும் ஒருமுறை தோன்றும் போது—நிலைமை மாறுகிறது:

  • IndexOfAny(char[]) – 5.6 ms
  • SearchValues – 3.3 ms

இப்போது SearchValues 1.7 × வேகமானது; ஏனெனில், IndexOfAny குறைந்த வேகமான பாதையைத் தேர்ந்தெடுக்கும் நிலையில், SearchValues இன்ஜின் வெக்டரைஸ்டு படிகள் (vectorized steps) மூலம் பொருந்தாத தரவுகளின் நீண்ட தொடர்களை மிக வேகமாகத் தாண்டிச் செல்கிறது.

மறைந்திருக்கும் செலவு (The hidden cost)

SearchValues என்பது இலவசமானது அல்ல. இந்த ஆப்ஜெக்ட்டை உருவாக்குவது நினைவகத்தை (memory) ஒதுக்குவதோடு, உட்புறத் தேடல் அட்டவணைகளையும் (internal lookup tables) உருவாக்குகிறது. ஒவ்வொரு முறையும் மெத்தட் அழைப்பின் போது (method call) இதை நீங்கள் உருவாக்கினால், அதன் கூடுதல் சுமை (overhead) ரன்டைமில் கிடைக்கும் எந்தப் பயனையும் விட அதிகமாக இருக்கும். குறுகிய வரிகளில் ஒரு மில்லியன் முறை ஸ்கேனிங் முறையை அழைத்த பெஞ்ச்மார்க் முடிவுகள் இதோ:

  • Static (மீண்டும் பயன்படுத்தப்படும்) SearchValues – மொத்தம் 25.1 ms
  • ஒவ்வொரு அழைப்பிற்கும் புதிய SearchValues – மொத்தம் 70.2 ms

ஒவ்வொரு அழைப்பிற்கும் ஆப்ஜெக்ட்டை உருவாக்குவது, SearchValues-ஐப் பயன்படுத்தாமல் இருப்பதை விட முழுச் செயல்பாட்டையும் மூன்று மடங்கு மெதுவாக்குகிறது. எனவே, அந்த இன்ஸ்டன்ஸ் (instance)-ஐ ஒரு static readonly ஃபீல்டில் சேமித்து வைத்து அல்லது பிற வழிகளில் மீண்டும் பயன்படுத்திக் கொள்ளுங்கள்.

எப்போது SearchValues-ஐப் பயன்படுத்த வேண்டும்

  • பெரிய உள்ளீடுகள், குறைவான பொருத்தங்கள் (Large inputs, few matches) – ஸ்கேனர் ஒரு பிரிப்பானைச் சந்திக்காமல் நீண்ட பகுதிகளைத் தாண்டிச் செல்ல முடியும் போது, வெக்டரைஸ்டு பாதை சிறப்பாகச் செயல்படும்.
  • ஒரே தொகுப்பைக் கொண்டு மீண்டும் மீண்டும் ஸ்கேன் செய்தல் – ஒரே எழுத்துக்கள் பலமுறை தேடப்பட வேண்டியிருந்தால், ஒருமுறை செய்யும் தயாரிப்பு (setup) பலன் தரும்.

எப்போது IndexOfAny-யையே பயன்படுத்த வேண்டும்

  • குறுகிய சரங்கள் அல்லது அதிக பொருத்தங்கள் (Short strings or many matches) – கூடுதல் தயாரிப்புச் செலவு (setup cost), கிடைக்கும் சிறிய வேக அதிகரிப்பை விட அதிகமாக இருக்கும்.
  • ஏற்கனவே IndexOfAny பயன்படுத்தும் குறியீடு – நவீன .NET-இன் செயலாக்கம் ஏற்கனவே சிறிய எழுத்துத் தொகுப்புகளுக்கு மிகச்சிறப்பாகச் செதுக்கப்பட்டுள்ளது (tuned), எனவே SearchValues-க்கு மாறுவது பெரிய மாற்றத்தைக் கொடுக்காது.

பொதுவான தவறுகள்

  • Hot loops-க்குள் ஆப்ஜெக்ட் உருவாக்கத்தை இணைப்பது – இது மேலே காட்டப்பட்டுள்ளபடி செயல்பாட்டை மூன்று மடங்கு மெதுவாக்கும்.
  • கைமுறை லூப்கள் மூலம் ரன்டைமை விட "புத்திசாலித்தனமாக" செயல்பட முயல்வது – கைமுறையாகச் செய்யப்பட்ட foreach பதிப்பு, இரண்டு உள்ளமைக்கப்பட்ட முறைகளையும் விட இரண்டு மடங்கு மெதுவாக இருந்தது. இது SIMD இன்ஸ்ட்ரக்ஷன்கள் பற்றிய ஆழமான அறிவு இல்லாமல் .NET லைப்ரரிகளைத் தோற்கடிப்பது கடினம் என்பதை உறுதிப்படுத்துகிறது.
  • அனைத்து இடங்களிலும் வேகம் அதிகரிக்கும் என்று கருதுவது – அடர்த்தியான தரவுகளில் (dense data) கிடைத்த அரை மில்லிசெகண்ட் வெற்றி, SearchValues என்பது எல்லா இடங்களிலும் பயன்படும் ஒரு மந்திரக் குறியீடு (cheat code) அல்ல என்பதை நிரூபிக்கிறது; அதன் பயன்கள் தரவைப் பொறுத்தே அமையும்.

சுருக்கம் (Takeaway)

அரிதான எழுத்துக்களைத் தேட பெரிய பஃபர்களை ஸ்கேன் செய்யும் போது மற்றும் ஒருமுறை ஆப்ஜெக்ட்டை உருவாக்கும் செலவைச் சுமக்க முடியும் போது மட்டுமே SearchValues<T> தெளிவான நன்மையைத் தருகிறது. அன்றாடத் தேவைப்படும் பெரும்பாலான ஸ்ட்ரிங்-தேடல் சூழல்களுக்கு—குறுகிய உள்ளீடுகள், அடிக்கடி ஏற்படும் பொருத்தங்கள் அல்லது ஏற்கனவே IndexOfAny-ஐச் சார்ந்திருக்கும் குறியீடுகள்—உள்ளமைக்கப்பட்ட முறையே எளிமையான மற்றும் வேகமான தேர்வாக இருக்கும். SearchValues-ஐத் தேர்ந்தெடுத்துப் பயன்படுத்துங்கள், அதன் இன்ஸ்டன்ஸை கேச் (cache) செய்யுங்கள்; இதன் மூலம் மறைந்திருக்கும் இழப்புகளைத் தவிர்த்து உண்மையான செயல்திறன் பலனைப் பெறலாம்.

மூலக் குறியீடு மற்றும் முழுமையான சோதனைத் தொகுப்பு: https://dev.to/ssukhpinder/when-searchvalues-actually-pays-off-310l