જ્યારે મોટા બફર્સમાં વિરલ (sparse) ડીલીમીટર્સ (delimiters) સ્કેન કરવાનો હોય, ત્યારે .NET 10 માં SearchValues<T> ખરેખર માપી શકાય તેવો ફાયદો બતાવે છે; 32 MB પેલોડ પર SearchValues 3.3 ms માં પૂર્ણ થાય છે, જ્યારે IndexOfAny ને 5.6 ms લાગે છે.

SearchValues શા માટે આવ્યું

.NET 8 એ અક્ષરો (અથવા બાઇટ્સ) ના સેટને પ્રી-કમ્પ્યુટ કરવા માટે અને રનટાઇમને તે સેટ માટે સૌથી ઝડપી સ્કેનિંગ અલ્ગોરિધમ પસંદ કરવા દેવા માટે SearchValues<T> રજૂ કર્યું હતું. ઓબ્જેક્ટ એકવાર બનાવો, અને પછી જ્યારે પણ તમારે સ્પેનમાં (span) કોઈપણ મૂલ્યો શોધવાની જરૂર હોય ત્યારે તેનો ફરીથી ઉપયોગ કરો. રનટાઇમ વેક્ટરાઇઝ્ડ ઇન્સ્ટ્રક્શન (vectorized instructions), બ્રાન્ચ-ફ્રી લૂપ્સ (branch-free loops), અથવા અન્ય લો-લેવલ ટ્રિક્સનો ઉપયોગ કરી શકે છે જે હાથથી લખવામાં આવેલા વિકલ્પો ઘણા પ્રયત્નો વિના મેચ કરી શકતા નથી.

મહત્વપૂર્ણ બેન્ચમાર્ક (Benchmarks)

ચર્ચા જગાવનારા પરીક્ષણોમાં પાંચ ડીલીમીટર અક્ષરો ધરાવતા 32 MB બફરનો ઉપયોગ કરવામાં આવ્યો હતો. .NET 10 પર ત્રણ અભિગમોનો સમય માપવામાં આવ્યો હતો:

  • IndexOfAny(char[]) – 10.2 ms
  • સ્પેન પર મેન્યુઅલ foreach લૂપ – 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 ઓછા એગ્રેસિવ માર્ગ પર જાય છે.

છુપો ખર્ચ (The hidden cost)

SearchValues મફત નથી. ઓબ્જેક્ટ બનાવવાથી મેમરી ફાળવવામાં આવે છે અને ઇન્ટરનલ લુકઅપ ટેબલ્સ (internal lookup tables) બને છે. જો તમે દરેક મેથડ કોલ પર તેને ઇન્સ્ટન્શિયેટ (instantiate) કરો છો, તો તેનો ઓવરહેડ રનટાઇમમાં મળતા કોઈપણ ફાયદા કરતા ઘણો વધારે હશે. ટૂંકી લાઇન પર એક મિલિયન વખત સ્કેનિંગ રૂટિનને કોલ કરતા કરાયેલા બેન્ચમાર્કે નીચે મુજબ દર્શાવ્યું:

  • Static (ફરીથી ઉપયોગમાં લેવાયેલ) SearchValues – કુલ 25.1 ms
  • Per-call SearchValues – કુલ 70.2 ms

દરેક કોલ દીઠ ઓબ્જેક્ટ બનાવવાથી આખી પ્રક્રિયા SearchValues નો ઉપયોગ ન કરવા કરતા ત્રણ ગણી ધીમી બને છે. ઇન્સ્ટન્સને static readonly ફિલ્ડમાં સ્ટોર કરો અથવા અન્યથા કોલ્સમાં તેનો ફરીથી ઉપયોગ કરો.

ક્યારે SearchValues નો ઉપયોગ કરવો

  • મોટા ઇનપુટ્સ, ઓછા મેચ – જ્યારે સ્કેનર ડીલીમીટરને અથડાયા વગર લાંબા ભાગોને સ્કીપ કરી શકે છે, ત્યારે વેક્ટરાઇઝ્ડ પાથ શ્રેષ્ઠ કામ કરે છે.
  • એક જ સેટ સાથે વારંવાર સ્કેનિંગ – જો એક જ અક્ષરો માટે ઘણી વખત શોધ કરવામાં આવે, તો એક વખતનો સેટઅપ ફાયદાકારક રહે છે.

ક્યારે IndexOfAny સાથે રહેવું

  • ટૂંકી સ્ટ્રિંગ્સ અથવા વધુ મેચ – વધારાનો સેટઅપ ખર્ચ ઝડપના નજીવા ફાયદા કરતા વધી જાય છે.
  • જે કોડમાં પહેલેથી જ IndexOfAny વપરાતું હોય – આધુનિક .NET નું ઇમ્પ્લીમેન્ટેશન નાના કેરેક્ટર સેટ માટે પહેલેથી જ હાઇલી ટ્યુન કરેલું છે, તેથી SearchValues માં બદલવાથી ખાસ ફરક પડી શકશે નહીં.

સામાન્ય ભૂલો (Common pitfalls)

  • Hot loops માં કન્સ્ટ્રક્શનને એમ્બેડ કરવું – જેનાથી ઉપર દર્શાવેલ ત્રણ ગણો ઘટાડો થાય છે.
  • મેન્યુઅલ લૂપ્સ દ્વારા રનટાઇમને "ઓવરસ્માર્ટ" બનાવવાનો પ્રયાસ કરવો – મેન્યુઅલ foreach વર્ઝન બંને બિલ્ટ-ઇન મેથડ કરતા બમણું ધીમું હતું, જે સાબિત કરે છે કે SIMD ઇન્સ્ટ્રક્શનના ઊંડા જ્ઞાન વિના .NET લાઇબ્રેરીઓને હરાવવી મુશ્કેલ છે.
  • સાર્વત્રિક સ્પીડઅપની ધારણા કરવી – ડેન્સ ડેટા પર અડધા મિલીસેકન્ડનો વિજય સાબિત કરે છે કે SearchValues એ કોઈ સાર્વત્રિક ચીટ કોડ નથી; તેના ફાયદા ડેટા પર આધારિત છે.

સારાંશ (Takeaway)

SearchValues<T> ત્યારે જ સ્પષ્ટ ફાયદો આપે છે જ્યારે તમે વિરલ અક્ષરો માટે મોટા બફર્સ સ્કેન કરો છો અને એક વખતનો કન્સ્ટ્રક્શન ખર્ચ ઉઠાવી શકો છો. રોજિંદા સ્ટ્રિંગ-સર્ચના મોટાભાગના કિસ્સાઓ માટે—ટૂંકા ઇનપુટ્સ, વારંવાર મેચ થતા અક્ષરો, અથવા જે કોડ પહેલેથી જ IndexOfAny પર આધારિત છે—બિલ્ટ-ઇન મેથડ સરળ અને ઝડપી પસંદગી રહે છે. SearchValues નો પસંદગીયુક્ત ઉપયોગ કરો, ઇન્સ્ટન્સને કેશ (cache) કરો, અને તમે વાસ્તવિક પર્ફોર્મન્સનો લાભ લેતા છુપા નુકસાનથી બચી શકશો.

સોર્સ કોડ અને સંપૂર્ણ ટેસ્ટ સૂટ: https://dev.to/ssukhpinder/when-searchvalues-actually-pays-off-310l