Commit 4f182469 authored by Marc Gravell's avatar Marc Gravell

intermediate commit

parent 15319500
......@@ -14,6 +14,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<PackageReference Include="System.Reflection.Emit.Lightweight" Version="4.3.0" />
<PackageReference Include="System.IO.Pipelines" Version="$(CoreFxVersion)" />
<PackageReference Include="System.Diagnostics.PerformanceCounter" Version="$(CoreFxVersion)" />
......
using System;
using System.Globalization;
using System.Net;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
namespace StackExchange.Redis
{
......@@ -137,6 +140,50 @@ internal static bool TryParseDouble(string s, out double value)
return double.TryParse(s, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out value);
}
internal static bool TryParseDouble(ReadOnlySpan<byte> s, out double value)
{
if (s.IsEmpty)
{
value = 0;
return false;
}
if (s.Length == 1 && s[0] >= '0' && s[0] <= '9')
{
value = (int)(s[0] - '0');
return true;
}
// need to handle these
if (CaseInsensitiveASCIIEqual("+inf", s) || CaseInsensitiveASCIIEqual("inf", s))
{
value = double.PositiveInfinity;
return true;
}
if (CaseInsensitiveASCIIEqual("-inf", s))
{
value = double.NegativeInfinity;
return true;
}
var ss = DecodeUtf8(s);
return double.TryParse(ss, NumberStyles.Any, NumberFormatInfo.InvariantInfo, out value);
}
internal static unsafe string DecodeUtf8(ReadOnlySpan<byte> s)
{
if (s.IsEmpty) return "";
fixed(byte* ptr = &MemoryMarshal.GetReference(s))
{
return Encoding.UTF8.GetString(ptr, s.Length);
}
}
static bool CaseInsensitiveASCIIEqual(string xLowerCase, ReadOnlySpan<byte> y)
{
if (y.Length != xLowerCase.Length) return false;
for(int i = 0; i < y.Length; i++)
{
if (char.ToLower((char)y[i]) != xLowerCase[i]) return false;
}
return true;
}
internal static EndPoint TryParseEndPoint(string endpoint)
{
if (string.IsNullOrWhiteSpace(endpoint)) return null;
......@@ -159,5 +206,31 @@ internal static EndPoint TryParseEndPoint(string endpoint)
return ParseEndPoint(host, port);
}
static readonly Vector<ushort> NonAsciiMask = new Vector<ushort>(0xFF80);
internal static unsafe int GetEncodedLength(string value)
{
if (value.Length == 0) return 0;
int offset = 0;
if (Vector.IsHardwareAccelerated && value.Length >= Vector<ushort>.Count)
{
var vecSpan = MemoryMarshal.Cast<char, Vector<ushort>>(value.AsSpan());
var nonAscii = NonAsciiMask;
int i;
for (i = 0; i < vecSpan.Length; i++)
{
if ((vecSpan[i] & nonAscii) != Vector<ushort>.Zero) break;
}
offset = Vector<ushort>.Count * i;
}
int remaining = value.Length - offset;
if (remaining == 0) return offset; // all ASCII (nice round length, and Vector support)
// handles a) no Vector support, b) anything from the fisrt non-ASCII chunk, c) tail end
fixed (char* ptr = value)
{
return offset + Encoding.UTF8.GetByteCount(ptr + offset, remaining);
}
}
}
}
......@@ -697,7 +697,7 @@ private void WriteUnified(PipeWriter writer, byte[] prefix, string value)
{
// ${total-len}\r\n 3 + MaxInt32TextLen
// {prefix}{value}\r\n
int encodedLength = Encoding.UTF8.GetByteCount(value),
int encodedLength = Format.GetEncodedLength(value),
prefixLength = prefix == null ? 0 : prefix.Length,
totalLength = prefixLength + encodedLength;
......@@ -719,7 +719,7 @@ private void WriteUnified(PipeWriter writer, byte[] prefix, string value)
}
}
}
private unsafe void WriteRaw(PipeWriter writer, string value, int encodedLength)
{
const int MaxQuickEncodeSize = 512;
......
......@@ -255,7 +255,7 @@ internal static byte[] ConcatenateBytes(byte[] a, object b, byte[] c)
int aLen = a?.Length ?? 0,
bLen = b == null ? 0 : (b is string
? Encoding.UTF8.GetByteCount((string)b)
? Format.GetEncodedLength((string)b)
: ((byte[])b).Length),
cLen = c?.Length ?? 0;
......@@ -294,4 +294,4 @@ internal static byte[] ConcatenateBytes(byte[] a, object b, byte[] c)
/// <param name="suffix">The suffix to append.</param>
public RedisKey Append(RedisKey suffix) => WithPrefix(this, suffix);
}
}
\ No newline at end of file
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment