મેં દરેક શબ્દને એકવાર ગણવા માટે બે વાર હેશ કર્યો

મેં ગયા અઠવાડિયે એક લોગ પાર્સરનું પ્રોફાઇલિંગ કર્યું. તે દૈનિક લોગમાં એરર કોડ્સ ગણે છે. તેનું મુખ્ય લોજિક એક સાદું ડિક્શનરી અપડેટ છે.

મોટાભાગના ડેવલપર્સ તેને આ રીતે લખે છે:

if (counts.TryGetValue(code, out int c))
    counts[code] = c + 1;
else
    counts[code] = 1;

આ કોડ કી (key) ને બે વાર હેશ કરે છે. TryGetValue હેશની ગણતરી કરીને અને બકેટ (bucket) માં શોધીને એન્ટ્રી શોધે છે. ત્યારબાદ ઇન્ડેક્સર (indexer) વેલ્યુ અપડેટ કરવા માટે ફરીથી એ જ કામ કરે છે. તમે દરેક ટોકન દીઠ એક જ કી અને એક જ હેશ પર બે વાર CPU સાયકલનો બગાડ કરો છો.

તમે બીજી વખતની પ્રક્રિયા ટાળી શકો છો. CollectionsMarshal.GetValueRefOrAddDefault નો ઉપયોગ કરો.

ref int slot = ref CollectionsMarshal.GetValueRefOrAddDefault(counts, code, out _);
slot++;

આ પદ્ધતિ એક જ સ્ટેપમાં સ્લોટ (slot) શોધે છે અથવા બનાવે છે. તે તમને સીધો સ્ટોરેજનો રેફરન્સ (reference) આપે છે. તમે એક જ વાર હેશ અને એક જ વાર બકેટ વોક કરો છો. ત્યારબાદ તમે તે જ જગ્યાએ વેલ્યુ બદલી શકો છો.

મેં 5 મિલિયન ટોકન્સ સાથે આનું પરીક્ષણ કર્યું.

પરિણામો: • TryGetValue + indexer: 160.0 ms • GetValueRefOrAddDefault: 95.0 ms

વન-લુકઅપ (one-lookup) વર્ઝન 1.7x ઝડપી છે.

મહત્વની વાત એ છે કે, મેમરી એલોકેશન (memory allocation) સમાન રહ્યું. આ ટ્રિક મેમરી બચાવતી નથી. તે ફક્ત CPU બચાવે છે. જો તમારો કોડ ગાર્બેજ કલેક્શન (garbage collection) ને કારણે ધીમો હોય, તો આ ફેરફાર કંઈ જ નહીં કરે. જો તમારો કોડ ભારે ગણતરીને કારણે ધીમો હોય, તો આ મદદરૂપ થશે.

જ્યારે તમારું લૂપ (loop) હાલની કીઝમાં ઘણા અપડેટ્સ કરે છે ત્યારે આનો ઉપયોગ કરો. જેમ જેમ ઇન્સર્ટ્સ (inserts) ની સરખામણીમાં અપડેટ્સનું પ્રમાણ વધશે તેમ તેમ તેનો ફાયદો વધશે.

એક ચેતવણી: રેફરન્સ ડિક્શનરીના આંતરિક સ્ટોરેજ તરફ નિર્દેશ કરે છે. તે આગામી સ્ટ્રક્ચરલ ફેરફાર (structural change) ન થાય ત્યાં સુધી જ માન્ય રહે છે. જો તમે કી ઉમેરો અથવા દૂર કરો છો, તો રેફરન્સને પકડી ન રાખો. રેફરન્સ લો, વેલ્યુ બદલો અને આગળ વધો.

મોટાભાગના કાર્યો માટે TryGetValue નો ઉપયોગ કરો. તે વાંચવામાં સરળ છે. ref વર્ઝનનો ઉપયોગ ત્યારે જ કરો જ્યારે તમારું ડિક્શનરી લૂપ પરફોર્મન્સ બોટલનેક (performance bottleneck) હોય.

સ્ત્રોત: https://dev.to/ssukhpinder/i-hashed-every-word-twice-to-count-it-once-1mg9