-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathProgram.cs
150 lines (130 loc) Β· 4.69 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Made by Benjamin Abt - https://github.com/BenjaminAbt
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
BenchmarkRunner.Run<Benchmark>();
[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net90, baseline: true)]
[HideColumns(Column.Job)]
public class Benchmark
{
[Benchmark]
public bool HasUnicodeCharCheck()
{
return StringExtensions.HasUnicodeCharCheck("Hello π! This is a test: πππ
π½πΆ, Ξ², Ξ³, Ξ΄, Ξ΅, Ξ©, Ο, β, β€οΈ");
}
[Benchmark]
public bool HasUnicodeVector()
{
return StringExtensions.HasUnicodeVector("Hello π! This is a test: πππ
π½πΆ, Ξ², Ξ³, Ξ΄, Ξ΅, Ξ©, Ο, β, β€οΈ");
}
}
public static class StringExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool HasUnicodeCharCheck(string source)
{
if (RuntimeHelpers.IsReferenceOrContainsReferences<char>())
{
foreach (char c in source)
{
if (c > 255)
{
return true;
}
}
}
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool HasUnicodeVector(string source)
{
if (string.IsNullOrEmpty(source))
{
return false;
}
ReadOnlySpan<char> span = source;
ref char ptr = ref MemoryMarshal.GetReference(span);
if (Vector512.IsHardwareAccelerated && span.Length >= Vector512<ushort>.Count)
{
return HasUnicodeVector512(ref ptr, span.Length);
}
else if (Vector256.IsHardwareAccelerated && span.Length >= Vector256<ushort>.Count)
{
return HasUnicodeVector256(ref ptr, span.Length);
}
else if (Vector128.IsHardwareAccelerated && span.Length >= Vector128<ushort>.Count)
{
return HasUnicodeVector128(ref ptr, span.Length);
}
return HasUnicodeScalar(ref ptr, span.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool HasUnicodeVector512(ref char ptr, int length)
{
int vectorSize = Vector512<ushort>.Count;
int vectorCount = length / vectorSize;
Vector512<ushort> threshold = Vector512.Create((ushort)255);
for (int i = 0; i < vectorCount; i++)
{
Vector512<ushort> vector = Vector512.LoadUnsafe(ref Unsafe.As<char, ushort>(ref Unsafe.Add(ref ptr, i * vectorSize)));
if (Vector512.GreaterThanAny(vector, threshold))
{
return true;
}
}
int processed = vectorCount * vectorSize;
return HasUnicodeScalar(ref Unsafe.Add(ref ptr, processed), length - processed);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool HasUnicodeVector256(ref char ptr, int length)
{
int vectorSize = Vector256<ushort>.Count;
int vectorCount = length / vectorSize;
Vector256<ushort> threshold = Vector256.Create((ushort)255);
for (int i = 0; i < vectorCount; i++)
{
Vector256<ushort> vector = Vector256.LoadUnsafe(ref Unsafe.As<char, ushort>(ref Unsafe.Add(ref ptr, i * vectorSize)));
if (Vector256.GreaterThanAny(vector, threshold))
{
return true;
}
}
int processed = vectorCount * vectorSize;
return HasUnicodeScalar(ref Unsafe.Add(ref ptr, processed), length - processed);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool HasUnicodeVector128(ref char ptr, int length)
{
int vectorSize = Vector128<ushort>.Count;
int vectorCount = length / vectorSize;
Vector128<ushort> threshold = Vector128.Create((ushort)255);
for (int i = 0; i < vectorCount; i++)
{
Vector128<ushort> vector = Vector128.LoadUnsafe(ref Unsafe.As<char, ushort>(ref Unsafe.Add(ref ptr, i * vectorSize)));
if (Vector128.GreaterThanAny(vector, threshold))
{
return true;
}
}
int processed = vectorCount * vectorSize;
return HasUnicodeScalar(ref Unsafe.Add(ref ptr, processed), length - processed);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool HasUnicodeScalar(ref char ptr, int length)
{
for (int i = 0; i < length; i++)
{
if (Unsafe.Add(ref ptr, i) > 255)
{
return true;
}
}
return false;
}
}