పెద్ద బఫర్లలో అరుదుగా ఉండే డెలిమిటర్ల (delimiters) కోసం స్కాన్ చేసేటప్పుడు, .NET 10లో SearchValues<T> స్పష్టమైన ప్రయోజనాన్ని చూపుతోంది. 32 MB పేలోడ్పై SearchValues 3.3 msలో పూర్తయితే, IndexOfAny 5.6 ms సమయం తీసుకుంది.
SearchValues ఎందుకు పరిచయం చేయబడింది
ఒక సెట్ క్యారెక్టర్ల (లేదా బైట్ల) కోసం ముందే గణనలు (pre-compute) చేయడానికి మరియు ఆ సెట్కు తగిన అత్యంత వేగవంతమైన స్కానింగ్ అల్గారిథమ్ను రన్టైమ్ ఎంచుకునేలా చేయడానికి .NET 8 SearchValues<T>ను పరిచయం చేసింది. ఒకసారి ఆబ్జెక్ట్ను నిర్మించి, ఆ తర్వాత స్పాన్ (span)లో ఏదైనా విలువలను గుర్తించాల్సి వచ్చినప్పుడు దానిని మళ్లీ ఉపయోగించుకోవచ్చు. రన్టైమ్ వెక్టరైజ్డ్ ఇన్స్ట్రక్షన్స్ (vectorized instructions), బ్రాంచ్-ఫ్రీ లూప్స్ (branch-free loops) లేదా ఇతర లో-లెవల్ ట్రిక్స్ను ఉపయోగించవచ్చు, వీటిని మాన్యువల్గా రాసిన ప్రత్యామ్నాయాలతో సాధించడం చాలా కష్టం.
ముఖ్యమైన బెంచ్మార్క్లు
చర్చకు దారితీసిన పరీక్షల్లో ఐదు డెలిమిటర్ క్యారెక్టర్లు ఉన్న 32 MB బఫర్ను ఉపయోగించారు. .NET 10లో మూడు పద్ధతులను పరీక్షించారు:
- IndexOfAny(char[]) – 10.2 ms
- Manual foreach loop over the span – 19.4 ms
- SearchValues
– 9.7 ms
SearchValues, ఇన్-బిల్ట్ IndexOfAny కంటే కేవలం అర మిల్లీసెకండ్ మాత్రమే వేగంగా ఉంది. ఫోరమ్లలో వస్తున్న "ఐదు రెట్లు వేగవంతం" అనే భారీ ప్రకటనలు ఇక్కడ లేవు; ఆధునిక .NET ఇప్పటికే చిన్న సెట్ల కోసం IndexOfAnyను ఆప్టిమైజ్ చేస్తుంది, దీనివల్ల రెండింటి మధ్య వ్యత్యాసం తగ్గుతుంది.
డెలిమిటర్లు అరుదుగా ఉన్నప్పుడు—అంటే ప్రతి 60 బైట్లకు ఒకసారి కాకుండా ప్రతి 40 KBకి ఒకసారి కనిపించినప్పుడు—పరిస్థితి మారుతుంది:
- IndexOfAny(char[]) – 5.6 ms
- SearchValues
– 3.3 ms
ఇప్పుడు SearchValues 1.7 × వేగంగా ఉంది, ఎందుకంటే ఇంజిన్ వెక్టరైజ్డ్ స్టెప్స్తో సరిపోని డేటా యొక్క సుదీర్ఘ భాగాన్ని వేగంగా దాటగలుగుతుంది, అయితే IndexOfAny తక్కువ వేగవంతమైన మార్గాన్ని అనుసరిస్తుంది.
దాగి ఉన్న ఖర్చు
SearchValues ఉచితం కాదు. ఆబ్జెక్ట్ను నిర్మించడం వల్ల మెమరీ కేటాయించబడుతుంది మరియు అంతర్గత లుకప్ టేబుల్స్ (lookup tables) తయారవుతాయి. మీరు ప్రతి మెథడ్ కాల్పై దానిని ఇన్స్టాంటియేట్ చేస్తే, ఆ ఓవర్హెడ్ వల్ల వచ్చే వేగం ఏమాత్రం ఉపయోగపడదు. చిన్న లైన్లపై ఒక మిలియన్ సార్లు స్కానింగ్ రూటీన్ను పిలిచిన బెంచ్మార్క్ ఈ క్రింది విధంగా చూపింది:
- Static (reused) SearchValues – మొత్తం 25.1 ms
- Per-call SearchValues – మొత్తం 70.2 ms
ప్రతి కాల్కి ఆబ్జెక్ట్ను సృష్టించడం వల్ల, SearchValuesను అసలు ఉపయోగించకపోవడం కంటే మొత్తం ఆపరేషన్ మూడు రెట్లు నెమ్మదిగా మారుతుంది. ఆ ఇన్స్టన్స్ను static readonly ఫీల్డ్లో నిల్వ చేయండి లేదా కాల్ల మధ్య మళ్లీ ఉపయోగించుకోండి.
ఎప్పుడు SearchValuesని ఉపయోగించాలి
- పెద్ద ఇన్పుట్లు, తక్కువ మ్యాచ్లు – స్కానర్ డెలిమిటర్ను తాకకుండానే సుదీర్ఘ భాగాన్ని దాటగలిగినప్పుడు వెక్టరైజ్డ్ పాత్ (vectorized path) అద్భుతంగా పనిచేస్తుంది.
- ఒకే సెట్తో పదేపదే స్కాన్ చేయడం – ఒకే క్యారెక్టర్ల కోసం చాలాసార్లు వెతికినట్లయితే, ఒకసారి చేసే సెటప్ వల్ల లాభం ఉంటుంది.
ఎప్పుడు IndexOfAnyతోనే ఉండాలి
- చిన్న స్ట్రింగ్లు లేదా ఎక్కువ మ్యాచ్లు – అదనపు సెటప్ ఖర్చు వల్ల వచ్చే స్వల్ప వేగ ప్రయోజనం కంటే అది ఎక్కువగా ఉంటుంది.
- ఇప్పటికే IndexOfAnyని ఉపయోగిస్తున్న కోడ్ – ఆధునిక .NET ఇంప్లిమెంటేషన్ ఇప్పటికే చిన్న క్యారెక్టర్ సెట్ల కోసం బాగా ట్యూన్ చేయబడింది, కాబట్టి
SearchValuesని మార్చడం వల్ల పెద్దగా తేడా ఉండకపోవచ్చు.
సాధారణ పొరపాట్లు
- Hot loopsలో ఆబ్జెక్ట్ కన్స్ట్రక్షన్ను ఉంచడం – పైన చూపినట్లుగా ఇది మూడు రెట్లు నెమ్మదిగా మారుస్తుంది.
- మాన్యువల్ లూప్లతో రన్టైమ్ను "ఓడించాలని" ప్రయత్నించడం – మాన్యువల్
foreachవెర్షన్ రెండు ఇన్-బిల్ట్ మెథడ్ల కంటే రెండు రెట్లు నెమ్మదిగా ఉంది, ఇది SIMD ఇన్స్ట్రక్షన్స్ గురించి లోతైన అవగాహన లేకుండా .NET లైబ్రరీలను అధిగమించడం కష్టమని నిర్ధారిస్తుంది. - అన్ని చోట్లా వేగం పెరుగుతుందని అనుకోవడం – డెన్స్ డేటాపై వచ్చిన అర మిల్లీసెకండ్ విజయం,
SearchValuesఅనేది అన్నిటికీ పనిచేసే మ్యాజిక్ కోడ్ కాదని నిరూపిస్తుంది; దీని ప్రయోజనాలు డేటాపై ఆధారపడి ఉంటాయి.
ముగింపు
మీరు పెద్ద బఫర్లలో అరుదుగా ఉండే క్యారెక్టర్ల కోసం స్కాన్ చేస్తున్నప్పుడు మరియు ఒకసారి చేసే కన్స్ట్రక్షన్ ఖర్చును భరించగలిగినప్పుడు మాత్రమే SearchValues<T> స్పష్టమైన ప్రయోజనాన్ని అందిస్తుంది. రోజువారీ స్ట్రింగ్-సెర్చ్ సందర్భాలలో—చిన్న ఇన్పుట్లు, తరచుగా వచ్చే మ్యాచ్లు లేదా ఇప్పటికే IndexOfAnyపై ఆధారపడిన కోడ్—ఇన్-బిల్ట్ మెథడ్ సులభమైన మరియు వేగవంతమైన ఎంపికగా ఉంటుంది. SearchValuesను ఎంపిక చేసినప్పుడు మాత్రమే వాడండి, ఇన్స్టన్స్ను క్యాష్ (cache) చేయండి, తద్వారా మీరు దాగి ఉన్న నష్టాన్ని నివారించి, నిజమైన పనితీరు ప్రయోజనాన్ని పొందవచ్చు.
సోర్స్ కోడ్ మరియు పూర్తి టెస్ట్ సూట్: https://dev.to/ssukhpinder/when-searchvalues-actually-pays-off-310l
