Skip to content

Commit

Permalink
Use pooled arrays instead of stack allocating
Browse files Browse the repository at this point in the history
  • Loading branch information
mgnsm committed Apr 6, 2023
1 parent f414dfd commit b873ab4
Show file tree
Hide file tree
Showing 2 changed files with 152 additions and 47 deletions.
62 changes: 45 additions & 17 deletions Source/Millistream.Streaming/MarketDataFeed.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Millistream.Streaming.Interop;
using System;
using System.Buffers;
using System.Collections.Immutable;
using System.Runtime.InteropServices;
using System.Text;
Expand Down Expand Up @@ -573,17 +574,26 @@ public bool Connect(string servers)
throw new ArgumentNullException(nameof(servers));

ThrowIfDisposed();
unsafe

int length = Encoding.UTF8.GetMaxByteCount(servers.Length);
byte[] bytes = ArrayPool<byte>.Shared.Rent(length + 1);
try
{
fixed (char* c = servers)
unsafe
{
int length = Encoding.UTF8.GetMaxByteCount(servers.Length);
byte* b = stackalloc byte[length + 1];
int bytesWritten = Encoding.UTF8.GetBytes(c, servers.Length, b, length);
b[bytesWritten] = 0;
return _nativeImplementation.mdf_connect(_feedHandle, (IntPtr)b) == 1;
fixed (char* c = servers)
fixed (byte* b = bytes)
{
int bytesWritten = Encoding.UTF8.GetBytes(c, servers.Length, b, length);
b[bytesWritten] = 0;
return _nativeImplementation.mdf_connect(_feedHandle, (IntPtr)b) == 1;
}
}
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
Expand Down Expand Up @@ -697,9 +707,19 @@ private string GetStringProperty(MDF_OPTION option)
int byteCount = 0;
while (*(p + byteCount++) != 0) ;
int charCount = Encoding.UTF8.GetCharCount(p, byteCount);
char* c = stackalloc char[charCount];
Encoding.UTF8.GetChars(p, byteCount, c, charCount);
return new string(c);
char[] chars = ArrayPool<char>.Shared.Rent(charCount);
try
{
fixed (char* c = chars)
{
Encoding.UTF8.GetChars(p, byteCount, c, charCount);
return new string(c);
}
}
finally
{
ArrayPool<char>.Shared.Return(chars);
}
}
}

Expand Down Expand Up @@ -740,17 +760,25 @@ private void SetProperty(MDF_OPTION option, string value)
int ret = 0;
if (value != null)
{
unsafe
int length = Encoding.UTF8.GetMaxByteCount(value.Length);
byte[] bytes = ArrayPool<byte>.Shared.Rent(length + 1);
try
{
fixed (char* c = value)
unsafe
{
int length = Encoding.UTF8.GetMaxByteCount(value.Length);
byte* b = stackalloc byte[length + 1];
int bytesWritten = Encoding.UTF8.GetBytes(c, value.Length, b, length);
b[bytesWritten] = 0;
ret = _nativeImplementation.mdf_set_property(_feedHandle, option, (IntPtr)b);
fixed (char* c = value)
fixed (byte* b = bytes)
{
int bytesWritten = Encoding.UTF8.GetBytes(c, value.Length, b, length);
b[bytesWritten] = 0;
ret = _nativeImplementation.mdf_set_property(_feedHandle, option, (IntPtr)b);
}
}
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}
else
{
Expand Down
137 changes: 107 additions & 30 deletions Source/Millistream.Streaming/Message.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Millistream.Streaming.Interop;
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Text;

Expand Down Expand Up @@ -32,7 +33,7 @@ public Message()
/// <exception cref="ArgumentNullException"><paramref name="nativeLibraryPath"/> is <see langword="null" /> or <see cref="string.Empty"/>.</exception>
/// <exception cref="DllNotFoundException">The native dependency can't be found.</exception>
/// <remarks>The corresponding native function is mdf_message_create.</remarks>
public Message(string nativeLibraryPath)
public Message(string nativeLibraryPath)
: this(nativeLibraryPath, true) { }

internal Message(NativeImplementation nativeImplementation)
Expand Down Expand Up @@ -214,10 +215,21 @@ public bool AddNumeric(uint tag, string value)
if (value == null)
return _nativeImplementation.mdf_message_add_numeric(Handle, tag, IntPtr.Zero) == 1;

byte* bytes = stackalloc byte[value.Length + 1];
if (!TryGetAsciiBytes(value, bytes))
return false;
return _nativeImplementation.mdf_message_add_numeric(Handle, tag, (IntPtr)bytes) == 1;
byte[] bytes = ArrayPool<byte>.Shared.Rent(value.Length + 1);
try
{
fixed (byte* b = bytes)
{
if (!TryGetAsciiBytes(value, b))
return false;
b[value.Length] = 0;
return _nativeImplementation.mdf_message_add_numeric(Handle, tag, (IntPtr)b) == 1;
}
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
Expand Down Expand Up @@ -305,13 +317,21 @@ public bool AddString(uint tag, string value)
if (value == null)
return _nativeImplementation.mdf_message_add_string(Handle, tag, IntPtr.Zero) == 1;

fixed (char* c = value)
int length = Encoding.UTF8.GetMaxByteCount(value.Length);
byte[] bytes = ArrayPool<byte>.Shared.Rent(length + 1);
try
{
fixed (char* c = value)
fixed (byte* b = bytes)
{
int bytesWritten = Encoding.UTF8.GetBytes(c, value.Length, b, length);
b[bytesWritten] = 0;
return _nativeImplementation.mdf_message_add_string(Handle, tag, (IntPtr)b) == 1;
}
}
finally
{
int length = Encoding.UTF8.GetMaxByteCount(value.Length);
byte* b = stackalloc byte[length + 1];
int bytesWritten = Encoding.UTF8.GetBytes(c, value.Length, b, length);
b[bytesWritten] = 0;
return _nativeImplementation.mdf_message_add_string(Handle, tag, (IntPtr)b) == 1;
ArrayPool<byte>.Shared.Return(bytes);
}
}

Expand All @@ -338,9 +358,19 @@ public bool AddString(uint tag, string value, int length)
fixed (char* c = value)
{
int byteCount = Encoding.UTF8.GetByteCount(c, length);
byte* b = stackalloc byte[byteCount + 1];
Encoding.UTF8.GetBytes(c, length, b, byteCount);
return _nativeImplementation.mdf_message_add_string2(Handle, tag, (IntPtr)b, byteCount) == 1;
byte[] bytes = ArrayPool<byte>.Shared.Rent(byteCount + 1);
try
{
fixed (byte* b = bytes)
{
Encoding.UTF8.GetBytes(c, length, b, byteCount);
return _nativeImplementation.mdf_message_add_string2(Handle, tag, (IntPtr)b, byteCount) == 1;
}
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}
}

Expand Down Expand Up @@ -382,10 +412,21 @@ public bool AddDate(uint tag, string value)
if (value == null)
return _nativeImplementation.mdf_message_add_date(Handle, tag, IntPtr.Zero) == 1;

byte* bytes = stackalloc byte[value.Length + 1];
if (!TryGetAsciiBytes(value, bytes))
return false;
return _nativeImplementation.mdf_message_add_date(Handle, tag, (IntPtr)bytes) == 1;
byte[] bytes = ArrayPool<byte>.Shared.Rent(value.Length + 1);
try
{
fixed (byte* b = bytes)
{
if (!TryGetAsciiBytes(value, b))
return false;
b[value.Length] = 0;
return _nativeImplementation.mdf_message_add_date(Handle, tag, (IntPtr)b) == 1;
}
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
Expand Down Expand Up @@ -445,10 +486,21 @@ public bool AddTime(uint tag, string value)
if (string.IsNullOrEmpty(value))
return false;

byte* bytes = stackalloc byte[value.Length + 1];
if (!TryGetAsciiBytes(value, bytes))
return false;
return _nativeImplementation.mdf_message_add_time(Handle, tag, (IntPtr)bytes) == 1;
byte[] bytes = ArrayPool<byte>.Shared.Rent(value.Length + 1);
try
{
fixed (byte* b = bytes)
{
if (!TryGetAsciiBytes(value, b))
return false;
b[value.Length] = 0;
return _nativeImplementation.mdf_message_add_time(Handle, tag, (IntPtr)b) == 1;
}
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
Expand Down Expand Up @@ -548,10 +600,22 @@ public bool AddList(uint tag, string value)
if (value == null)
return _nativeImplementation.mdf_message_add_list(Handle, tag, IntPtr.Zero) == 1;

byte* bytes = stackalloc byte[value.Length + 1];
if (!TryGetAsciiBytes(value, bytes))
return false;
return _nativeImplementation.mdf_message_add_list(Handle, tag, (IntPtr)bytes) == 1;
byte[] bytes = ArrayPool<byte>.Shared.Rent(value.Length + 1);
try
{
fixed (byte* b = bytes)
{
if (!TryGetAsciiBytes(value, b))
return false;
b[value.Length] = 0;
return _nativeImplementation.mdf_message_add_list(Handle, tag, (IntPtr)b) == 1;

}
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
Expand Down Expand Up @@ -646,10 +710,23 @@ public bool Deserialize(string data)

ThrowIfDisposed();
ThrowIfNativeFunctionIsMissing(_nativeImplementation.mdf_message_deserialize, nameof(_nativeImplementation.mdf_message_deserialize));
byte* bytes = stackalloc byte[data.Length + 1];
if (!TryGetAsciiBytes(data, bytes))
return false;
return _nativeImplementation.mdf_message_deserialize(Handle, (IntPtr)bytes) == 1;

byte[] bytes = ArrayPool<byte>.Shared.Rent(data.Length + 1);
try
{
fixed (byte* b = bytes)
{
if (!TryGetAsciiBytes(data, b))
return false;
b[data.Length] = 0;
return _nativeImplementation.mdf_message_deserialize(Handle, (IntPtr)b) == 1;

}
}
finally
{
ArrayPool<byte>.Shared.Return(bytes);
}
}

/// <summary>
Expand Down

0 comments on commit b873ab4

Please sign in to comment.