3
3
4
4
using System ;
5
5
using System . Diagnostics ;
6
- using System . Linq ;
7
6
using System . Numerics ;
8
7
9
8
namespace Microsoft . AspNet . Server . Kestrel . Infrastructure
10
9
{
11
10
public struct MemoryPoolIterator2
12
11
{
13
- /// <summary>
14
- /// Array of "minus one" bytes of the length of SIMD operations on the current hardware. Used as an argument in the
15
- /// vector dot product that counts matching character occurrence.
16
- /// </summary>
17
- private static Vector < byte > _dotCount = new Vector < byte > ( Byte . MaxValue ) ;
18
-
19
- /// <summary>
20
- /// Array of negative numbers starting at 0 and continuing for the length of SIMD operations on the current hardware.
21
- /// Used as an argument in the vector dot product that determines matching character index.
22
- /// </summary>
23
- private static Vector < byte > _dotIndex = new Vector < byte > ( Enumerable . Range ( 0 , Vector < byte > . Count ) . Select ( x => ( byte ) - x ) . ToArray ( ) ) ;
24
-
25
12
private MemoryPoolBlock2 _block ;
26
13
private int _index ;
27
14
@@ -146,7 +133,6 @@ public int Seek(int char0)
146
133
}
147
134
148
135
var byte0 = ( byte ) char0 ;
149
- var vectorStride = Vector < byte > . Count ;
150
136
var ch0Vector = new Vector < byte > ( byte0 ) ;
151
137
152
138
var block = _block ;
@@ -169,27 +155,20 @@ public int Seek(int char0)
169
155
while ( block . End != index )
170
156
{
171
157
var following = block . End - index ;
172
- if ( following >= vectorStride )
158
+ if ( following >= Vector < byte > . Count )
173
159
{
174
160
var data = new Vector < byte > ( array , index ) ;
175
161
var ch0Equals = Vector . Equals ( data , ch0Vector ) ;
176
- var ch0Count = Vector . Dot ( ch0Equals , _dotCount ) ;
177
162
178
- if ( ch0Count == 0 )
163
+ if ( ch0Equals . Equals ( Vector < byte > . Zero ) )
179
164
{
180
- index += vectorStride ;
165
+ index += Vector < byte > . Count ;
181
166
continue ;
182
167
}
183
- else if ( ch0Count == 1 )
184
- {
185
- _block = block ;
186
- _index = index + Vector . Dot ( ch0Equals , _dotIndex ) ;
187
- return char0 ;
188
- }
189
- else
190
- {
191
- following = vectorStride ;
192
- }
168
+
169
+ _block = block ;
170
+ _index = index + FindFirstEqualByte ( ch0Equals ) ;
171
+ return char0 ;
193
172
}
194
173
while ( following > 0 )
195
174
{
@@ -215,7 +194,6 @@ public int Seek(int char0, int char1)
215
194
216
195
var byte0 = ( byte ) char0 ;
217
196
var byte1 = ( byte ) char1 ;
218
- var vectorStride = Vector < byte > . Count ;
219
197
var ch0Vector = new Vector < byte > ( byte0 ) ;
220
198
var ch1Vector = new Vector < byte > ( byte1 ) ;
221
199
@@ -239,40 +217,39 @@ public int Seek(int char0, int char1)
239
217
while ( block . End != index )
240
218
{
241
219
var following = block . End - index ;
242
- if ( following >= vectorStride )
220
+ if ( following >= Vector < byte > . Count )
243
221
{
244
222
var data = new Vector < byte > ( array , index ) ;
245
223
var ch0Equals = Vector . Equals ( data , ch0Vector ) ;
246
- var ch0Count = Vector . Dot ( ch0Equals , _dotCount ) ;
247
224
var ch1Equals = Vector . Equals ( data , ch1Vector ) ;
248
- var ch1Count = Vector . Dot ( ch1Equals , _dotCount ) ;
225
+ int ch0Index = int . MaxValue ;
226
+ int ch1Index = int . MaxValue ;
249
227
250
- if ( ch0Count == 0 && ch1Count == 0 )
228
+ if ( ! ch0Equals . Equals ( Vector < byte > . Zero ) )
251
229
{
252
- index += vectorStride ;
253
- continue ;
230
+ ch0Index = FindFirstEqualByte ( ch0Equals ) ;
254
231
}
255
- else if ( ch0Count < 2 && ch1Count < 2 )
232
+ if ( ! ch1Equals . Equals ( Vector < byte > . Zero ) )
256
233
{
257
- var ch0Index = ch0Count == 1 ? Vector . Dot ( ch0Equals , _dotIndex ) : byte . MaxValue ;
258
- var ch1Index = ch1Count == 1 ? Vector . Dot ( ch1Equals , _dotIndex ) : byte . MaxValue ;
259
- if ( ch0Index < ch1Index )
260
- {
261
- _block = block ;
262
- _index = index + ch0Index ;
263
- return char0 ;
264
- }
265
- else
266
- {
267
- _block = block ;
268
- _index = index + ch1Index ;
269
- return char1 ;
270
- }
234
+ ch1Index = FindFirstEqualByte ( ch1Equals ) ;
271
235
}
272
- else
236
+
237
+ if ( ch0Index == int . MaxValue && ch1Index == int . MaxValue )
238
+ {
239
+ index += Vector < byte > . Count ;
240
+ continue ;
241
+ }
242
+
243
+ _block = block ;
244
+
245
+ if ( ch0Index < ch1Index )
273
246
{
274
- following = vectorStride ;
247
+ _index = index + ch0Index ;
248
+ return char0 ;
275
249
}
250
+
251
+ _index = index + ch1Index ;
252
+ return char1 ;
276
253
}
277
254
while ( following > 0 )
278
255
{
@@ -306,7 +283,6 @@ public int Seek(int char0, int char1, int char2)
306
283
var byte0 = ( byte ) char0 ;
307
284
var byte1 = ( byte ) char1 ;
308
285
var byte2 = ( byte ) char2 ;
309
- var vectorStride = Vector < byte > . Count ;
310
286
var ch0Vector = new Vector < byte > ( byte0 ) ;
311
287
var ch1Vector = new Vector < byte > ( byte1 ) ;
312
288
var ch2Vector = new Vector < byte > ( byte2 ) ;
@@ -331,64 +307,68 @@ public int Seek(int char0, int char1, int char2)
331
307
while ( block . End != index )
332
308
{
333
309
var following = block . End - index ;
334
- if ( following >= vectorStride )
310
+ if ( following >= Vector < byte > . Count )
335
311
{
336
312
var data = new Vector < byte > ( array , index ) ;
337
313
var ch0Equals = Vector . Equals ( data , ch0Vector ) ;
338
- var ch0Count = Vector . Dot ( ch0Equals , _dotCount ) ;
339
314
var ch1Equals = Vector . Equals ( data , ch1Vector ) ;
340
- var ch1Count = Vector . Dot ( ch1Equals , _dotCount ) ;
341
315
var ch2Equals = Vector . Equals ( data , ch2Vector ) ;
342
- var ch2Count = Vector . Dot ( ch2Equals , _dotCount ) ;
316
+ int ch0Index = int . MaxValue ;
317
+ int ch1Index = int . MaxValue ;
318
+ int ch2Index = int . MaxValue ;
343
319
344
- if ( ch0Count == 0 && ch1Count == 0 && ch2Count == 0 )
320
+ if ( ! ch0Equals . Equals ( Vector < byte > . Zero ) )
345
321
{
346
- index += vectorStride ;
347
- continue ;
322
+ ch0Index = FindFirstEqualByte ( ch0Equals ) ;
323
+ }
324
+ if ( ! ch1Equals . Equals ( Vector < byte > . Zero ) )
325
+ {
326
+ ch1Index = FindFirstEqualByte ( ch1Equals ) ;
348
327
}
349
- else if ( ch0Count < 2 && ch1Count < 2 && ch2Count < 2 )
328
+ if ( ! ch2Equals . Equals ( Vector < byte > . Zero ) )
350
329
{
351
- var ch0Index = ch0Count == 1 ? Vector . Dot ( ch0Equals , _dotIndex ) : byte . MaxValue ;
352
- var ch1Index = ch1Count == 1 ? Vector . Dot ( ch1Equals , _dotIndex ) : byte . MaxValue ;
353
- var ch2Index = ch2Count == 1 ? Vector . Dot ( ch2Equals , _dotIndex ) : byte . MaxValue ;
330
+ ch2Index = FindFirstEqualByte ( ch2Equals ) ;
331
+ }
354
332
355
- int toReturn , toMove ;
356
- if ( ch0Index < ch1Index )
333
+ if ( ch0Index == int . MaxValue && ch1Index == int . MaxValue && ch2Index == int . MaxValue )
334
+ {
335
+ index += Vector < byte > . Count ;
336
+ continue ;
337
+ }
338
+
339
+ int toReturn , toMove ;
340
+ if ( ch0Index < ch1Index )
341
+ {
342
+ if ( ch0Index < ch2Index )
357
343
{
358
- if ( ch0Index < ch2Index )
359
- {
360
- toReturn = char0 ;
361
- toMove = ch0Index ;
362
- }
363
- else
364
- {
365
- toReturn = char2 ;
366
- toMove = ch2Index ;
367
- }
344
+ toReturn = char0 ;
345
+ toMove = ch0Index ;
368
346
}
369
347
else
370
348
{
371
- if ( ch1Index < ch2Index )
372
- {
373
- toReturn = char1 ;
374
- toMove = ch1Index ;
375
- }
376
- else
377
- {
378
- toReturn = char2 ;
379
- toMove = ch2Index ;
380
- }
349
+ toReturn = char2 ;
350
+ toMove = ch2Index ;
381
351
}
382
-
383
- _block = block ;
384
- _index = index + toMove ;
385
- return toReturn ;
386
352
}
387
353
else
388
354
{
389
- following = vectorStride ;
355
+ if ( ch1Index < ch2Index )
356
+ {
357
+ toReturn = char1 ;
358
+ toMove = ch1Index ;
359
+ }
360
+ else
361
+ {
362
+ toReturn = char2 ;
363
+ toMove = ch2Index ;
364
+ }
390
365
}
366
+
367
+ _block = block ;
368
+ _index = index + toMove ;
369
+ return toReturn ;
391
370
}
371
+
392
372
while ( following > 0 )
393
373
{
394
374
var byteIndex = block . Array [ index ] ;
@@ -417,6 +397,34 @@ public int Seek(int char0, int char1, int char2)
417
397
}
418
398
}
419
399
400
+ private static int FindFirstEqualByte ( Vector < byte > chEquals )
401
+ {
402
+ // Quasi-tree search
403
+ var vector64 = Vector . AsVectorInt64 ( chEquals ) ;
404
+ for ( var i = 0 ; i < Vector < long > . Count ; i ++ )
405
+ {
406
+ var longValue = vector64 [ i ] ;
407
+ if ( longValue == 0 ) continue ;
408
+
409
+ var shift = i << 1 ;
410
+ var offset = shift << 2 ;
411
+ var vector32 = Vector . AsVectorInt32 ( chEquals ) ;
412
+ if ( vector32 [ shift ] != 0 )
413
+ {
414
+ if ( chEquals [ offset ] != 0 ) return offset ;
415
+ if ( chEquals [ ++ offset ] != 0 ) return offset ;
416
+ if ( chEquals [ ++ offset ] != 0 ) return offset ;
417
+ return ++ offset ;
418
+ }
419
+ offset += 4 ;
420
+ if ( chEquals [ offset ] != 0 ) return offset ;
421
+ if ( chEquals [ ++ offset ] != 0 ) return offset ;
422
+ if ( chEquals [ ++ offset ] != 0 ) return offset ;
423
+ return ++ offset ;
424
+ }
425
+ throw new InvalidOperationException ( ) ;
426
+ }
427
+
420
428
/// <summary>
421
429
/// Save the data at the current location then move to the next available space.
422
430
/// </summary>
0 commit comments