11namespace Genbox . FastData . Benchmarks . Benchmarks ;
22
3+ [ DisassemblyDiagnoser ]
34public class StringEarlyExitBenchmarks
45{
56 private string _value = "hello world" ;
@@ -13,16 +14,158 @@ public class StringEarlyExitBenchmarks
1314 private ulong _stringMask = 0xFF93FF93FF9AFF97UL ;
1415
1516 [ Benchmark ] public bool LengthEqual ( ) => _value . Length != 49 ;
17+
18+ [ Benchmark ] public bool LengthEqualOpti ( )
19+ {
20+ int length = _value . Length ;
21+ return length != 49 ;
22+ }
23+
1624 [ Benchmark ] public bool LengthRange ( ) => _value . Length < _min || _value . Length > _max ;
25+
26+ [ Benchmark ] public bool LengthRangeOpti ( )
27+ {
28+ int length = _value . Length ;
29+ return ( uint ) ( length - _min ) > ( uint ) ( _max - _min ) ;
30+ }
31+
1732 [ Benchmark ] public bool LengthBitmap ( ) => ( _bitset [ _value . Length >> 6 ] & ( 1UL << ( ( _value . Length - 1 ) & 63 ) ) ) == 0 ;
33+
34+ [ Benchmark ] public bool LengthBitmapOpti ( )
35+ {
36+ int length = _value . Length ;
37+ return ( _bitset [ length >> 6 ] & ( 1UL << ( ( length - 1 ) & 63 ) ) ) == 0 ;
38+ }
39+
1840 [ Benchmark ] public bool LengthDivisor ( ) => _value . Length % 3 != 0 ;
41+
42+ [ Benchmark ] public bool LengthDivisorOpti ( )
43+ {
44+ int length = _value . Length ;
45+ return length % 3 != 0 ;
46+ }
47+
1948 [ Benchmark ] public bool CharEqualsFirst ( ) => _value [ 0 ] != 'h' ;
49+
50+ [ Benchmark ] public bool CharEqualsFirstOpti ( )
51+ {
52+ string value = _value ;
53+ return value . Length == 0 || value [ 0 ] != 'h' ;
54+ }
55+
2056 [ Benchmark ] public bool CharEqualsLast ( ) => _value [ ^ 1 ] != 'h' ;
57+
58+ [ Benchmark ] public bool CharEqualsLastOpti ( )
59+ {
60+ string value = _value ;
61+ int length = value . Length ;
62+ return length == 0 || value [ length - 1 ] != 'h' ;
63+ }
64+
2165 [ Benchmark ] public bool CharEqualsFirstLast ( ) => _value [ 0 ] != 'h' || _value [ ^ 1 ] != 'd' ;
66+
67+ [ Benchmark ] public bool CharEqualsFirstLastOpti ( )
68+ {
69+ string value = _value ;
70+ int length = value . Length ;
71+ if ( length == 0 )
72+ return true ;
73+
74+ if ( value [ 0 ] != 'h' )
75+ return true ;
76+
77+ return value [ length - 1 ] != 'd' ;
78+ }
79+
2280 [ Benchmark ] public bool CharRangeFirst ( ) => _value [ 0 ] < _min || _value [ 0 ] > _max ;
81+
82+ [ Benchmark ] public bool CharRangeFirstOpti ( )
83+ {
84+ string value = _value ;
85+ if ( value . Length == 0 )
86+ return true ;
87+
88+ int ch = value [ 0 ] ;
89+ return ( uint ) ( ch - _min ) > ( uint ) ( _max - _min ) ;
90+ }
91+
2392 [ Benchmark ] public bool CharRangeLast ( ) => _value [ ^ 1 ] < _min || _value [ ^ 1 ] > _max ;
93+
94+ [ Benchmark ] public bool CharRangeLastOpti ( )
95+ {
96+ string value = _value ;
97+ int length = value . Length ;
98+ if ( length == 0 )
99+ return true ;
100+
101+ int ch = value [ length - 1 ] ;
102+ return ( uint ) ( ch - _min ) > ( uint ) ( _max - _min ) ;
103+ }
104+
24105 [ Benchmark ] public bool CharBitmapFirst ( ) => ( ( 1UL << _value [ 0 ] ) & _firstLow ) == 0 ;
106+
107+ [ Benchmark ] public bool CharBitmapFirstOpti ( )
108+ {
109+ string value = _value ;
110+ if ( value . Length == 0 )
111+ return true ;
112+
113+ int ch = value [ 0 ] ;
114+ return ( ( 1UL << ch ) & _firstLow ) == 0 ;
115+ }
116+
25117 [ Benchmark ] public bool CharBitmapLast ( ) => ( ( 1UL << _value [ ^ 1 ] ) & _lastLow ) == 0 ;
118+
119+ [ Benchmark ] public bool CharBitmapLastOpti ( )
120+ {
121+ string value = _value ;
122+ int length = value . Length ;
123+ if ( length == 0 )
124+ return true ;
125+
126+ int ch = value [ length - 1 ] ;
127+ return ( ( 1UL << ch ) & _lastLow ) == 0 ;
128+ }
129+
26130 [ Benchmark ] public bool StringBitMask ( ) => ( ( _value [ 0 ] | ( ( ulong ) _value [ 1 ] << 16 ) | ( ( ulong ) _value [ 2 ] << 32 ) | ( ( ulong ) _value [ 3 ] << 48 ) ) & _stringMask ) != 0 ;
131+
132+ [ Benchmark ] public bool StringBitMaskOpti ( )
133+ {
134+ string value = _value ;
135+ if ( value . Length < 4 )
136+ return true ;
137+
138+ ulong packed = value [ 0 ] | ( ( ulong ) value [ 1 ] << 16 ) | ( ( ulong ) value [ 2 ] << 32 ) | ( ( ulong ) value [ 3 ] << 48 ) ;
139+ return ( packed & _stringMask ) != 0 ;
140+ }
141+
27142 [ Benchmark ] public bool PrefixSuffix ( ) => _value . StartsWith ( _prefix , StringComparison . Ordinal ) && _value . EndsWith ( _suffix , StringComparison . Ordinal ) ;
143+
144+ [ Benchmark ] public bool PrefixSuffixOpti ( )
145+ {
146+ string value = _value ;
147+ string prefix = _prefix ;
148+ string suffix = _suffix ;
149+ int length = value . Length ;
150+ int prefixLength = prefix . Length ;
151+ int suffixLength = suffix . Length ;
152+
153+ if ( length < prefixLength || length < suffixLength )
154+ return false ;
155+
156+ for ( int i = 0 ; i < prefixLength ; i ++ )
157+ {
158+ if ( value [ i ] != prefix [ i ] )
159+ return false ;
160+ }
161+
162+ int suffixStart = length - suffixLength ;
163+ for ( int i = 0 ; i < suffixLength ; i ++ )
164+ {
165+ if ( value [ suffixStart + i ] != suffix [ i ] )
166+ return false ;
167+ }
168+
169+ return true ;
170+ }
28171}
0 commit comments