mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-07 16:06:15 +00:00
Performance improvements
This commit is contained in:
parent
db9fba4cf2
commit
e86713e949
@ -46,7 +46,7 @@ namespace CryptoExchange.Net.UnitTests
|
|||||||
{
|
{
|
||||||
var stream = new MemoryStream(Encoding.UTF8.GetBytes(data));
|
var stream = new MemoryStream(Encoding.UTF8.GetBytes(data));
|
||||||
var accessor = CreateAccessor();
|
var accessor = CreateAccessor();
|
||||||
var valid = accessor.Read(stream, true);
|
var valid = accessor.Read(stream, true).Result;
|
||||||
if (!valid)
|
if (!valid)
|
||||||
return new CallResult<T>(new ServerError(data));
|
return new CallResult<T>(new ServerError(data));
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ namespace CryptoExchange.Net.Authentication
|
|||||||
public ApiCredentials(Stream inputStream, string? identifierKey = null, string? identifierSecret = null)
|
public ApiCredentials(Stream inputStream, string? identifierKey = null, string? identifierSecret = null)
|
||||||
{
|
{
|
||||||
var accessor = new SystemTextJsonStreamMessageAccessor();
|
var accessor = new SystemTextJsonStreamMessageAccessor();
|
||||||
if (!accessor.Read(inputStream, false))
|
if (!accessor.Read(inputStream, false).Result)
|
||||||
throw new ArgumentException("Input stream not valid json data");
|
throw new ArgumentException("Input stream not valid json data");
|
||||||
|
|
||||||
var key = accessor.GetValue<string>(MessagePath.Get().Property(identifierKey ?? "apiKey"));
|
var key = accessor.GetValue<string>(MessagePath.Get().Property(identifierKey ?? "apiKey"));
|
||||||
|
@ -248,7 +248,7 @@ namespace CryptoExchange.Net.Authentication
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// HMACSHA512 sign the data and return the hash
|
/// HMACSHA256 sign the data and return the hash
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="data">Data to sign</param>
|
/// <param name="data">Data to sign</param>
|
||||||
/// <param name="outputType">String type</param>
|
/// <param name="outputType">String type</param>
|
||||||
@ -270,7 +270,7 @@ namespace CryptoExchange.Net.Authentication
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// HMACSHA512 sign the data and return the hash
|
/// HMACSHA384 sign the data and return the hash
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="data">Data to sign</param>
|
/// <param name="data">Data to sign</param>
|
||||||
/// <param name="outputType">String type</param>
|
/// <param name="outputType">String type</param>
|
||||||
|
@ -323,7 +323,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
if (!response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
// Error response
|
// Error response
|
||||||
accessor.Read(responseStream, true);
|
await accessor.Read(responseStream, true).ConfigureAwait(false);
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
if (response.StatusCode == (HttpStatusCode)418 || response.StatusCode == (HttpStatusCode)429)
|
if (response.StatusCode == (HttpStatusCode)418 || response.StatusCode == (HttpStatusCode)429)
|
||||||
@ -341,7 +341,7 @@ namespace CryptoExchange.Net.Clients
|
|||||||
// Success status code and expected empty response, assume it's correct
|
// Success status code and expected empty response, assume it's correct
|
||||||
return new WebCallResult<T>(statusCode, headers, sw.Elapsed, 0, null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, null);
|
return new WebCallResult<T>(statusCode, headers, sw.Elapsed, 0, null, request.RequestId, request.Uri.ToString(), request.Content, request.Method, request.GetHeaders(), default, null);
|
||||||
|
|
||||||
var valid = accessor.Read(responseStream, outputOriginalData);
|
var valid = await accessor.Read(responseStream, outputOriginalData).ConfigureAwait(false);
|
||||||
if (!valid)
|
if (!valid)
|
||||||
{
|
{
|
||||||
// Invalid json
|
// Invalid json
|
||||||
|
@ -7,7 +7,9 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Converters.JsonNet
|
namespace CryptoExchange.Net.Converters.JsonNet
|
||||||
{
|
{
|
||||||
@ -222,26 +224,32 @@ namespace CryptoExchange.Net.Converters.JsonNet
|
|||||||
public override bool OriginalDataAvailable => _stream?.CanSeek == true;
|
public override bool OriginalDataAvailable => _stream?.CanSeek == true;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool Read(Stream stream, bool bufferStream)
|
public async Task<bool> Read(Stream stream, bool bufferStream)
|
||||||
{
|
{
|
||||||
if (bufferStream && stream is not MemoryStream)
|
if (bufferStream && stream is not MemoryStream)
|
||||||
{
|
{
|
||||||
|
// We need to be buffer the stream, and it's not currently a seekable stream, so copy it to a new memory stream
|
||||||
_stream = new MemoryStream();
|
_stream = new MemoryStream();
|
||||||
stream.CopyTo(_stream);
|
stream.CopyTo(_stream);
|
||||||
_stream.Position = 0;
|
_stream.Position = 0;
|
||||||
}
|
}
|
||||||
else
|
else if (bufferStream)
|
||||||
{
|
{
|
||||||
|
// We need to buffer the stream, and the current stream is seekable, store as is
|
||||||
_stream = stream;
|
_stream = stream;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We don't need to buffer the stream, so don't bother keeping the reference
|
||||||
|
}
|
||||||
|
|
||||||
var length = _stream.CanSeek ? _stream.Length : 4096;
|
var length = stream.CanSeek ? stream.Length : 4096;
|
||||||
using var reader = new StreamReader(_stream, Encoding.UTF8, false, (int)Math.Max(2, length), true);
|
using var reader = new StreamReader(stream, Encoding.UTF8, false, (int)Math.Max(2, length), true);
|
||||||
using var jsonTextReader = new JsonTextReader(reader);
|
using var jsonTextReader = new JsonTextReader(reader);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_token = JToken.Load(jsonTextReader);
|
_token = await JToken.LoadAsync(jsonTextReader).ConfigureAwait(false);
|
||||||
IsJson = true;
|
IsJson = true;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@ -284,8 +292,12 @@ namespace CryptoExchange.Net.Converters.JsonNet
|
|||||||
public bool Read(ReadOnlyMemory<byte> data)
|
public bool Read(ReadOnlyMemory<byte> data)
|
||||||
{
|
{
|
||||||
_bytes = data;
|
_bytes = data;
|
||||||
using var stream = new MemoryStream(data.ToArray());
|
|
||||||
using var reader = new StreamReader(stream, Encoding.UTF8, false, (int)Math.Max(2, data.Length), true);
|
// Try getting the underlying byte[] instead of the ToArray to prevent creating a copy
|
||||||
|
using var stream = MemoryMarshal.TryGetArray(data, out var arraySegment)
|
||||||
|
? new MemoryStream(arraySegment.Array, arraySegment.Offset, arraySegment.Count)
|
||||||
|
: new MemoryStream(data.ToArray());
|
||||||
|
using var reader = new StreamReader(stream, Encoding.UTF8, false, Math.Max(2, data.Length), true);
|
||||||
using var jsonTextReader = new JsonTextReader(reader);
|
using var jsonTextReader = new JsonTextReader(reader);
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -303,7 +315,13 @@ namespace CryptoExchange.Net.Converters.JsonNet
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string GetOriginalString() => Encoding.UTF8.GetString(_bytes.ToArray());
|
public override string GetOriginalString() =>
|
||||||
|
// Netstandard 2.0 doesn't support GetString from a ReadonlySpan<byte>, so use ToArray there instead
|
||||||
|
#if NETSTANDARD2_0
|
||||||
|
Encoding.UTF8.GetString(_bytes.ToArray());
|
||||||
|
#else
|
||||||
|
Encoding.UTF8.GetString(_bytes.Span);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OriginalDataAvailable => true;
|
public override bool OriginalDataAvailable => true;
|
||||||
|
@ -192,9 +192,14 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
[return: NotNullIfNotNull("enumValue")]
|
[return: NotNullIfNotNull("enumValue")]
|
||||||
public static string? GetString<T>(T enumValue) => GetString(typeof(T), enumValue);
|
public static string? GetString<T>(T enumValue) => GetString(typeof(T), enumValue);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the string value for an enum value using the MapAttribute mapping. When multiple values are mapped for a enum entry the first value will be returned
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="objectType"></param>
|
||||||
|
/// <param name="enumValue"></param>
|
||||||
|
/// <returns></returns>
|
||||||
[return: NotNullIfNotNull("enumValue")]
|
[return: NotNullIfNotNull("enumValue")]
|
||||||
private static string? GetString(Type objectType, object? enumValue)
|
public static string? GetString(Type objectType, object? enumValue)
|
||||||
{
|
{
|
||||||
objectType = Nullable.GetUnderlyingType(objectType) ?? objectType;
|
objectType = Nullable.GetUnderlyingType(objectType) ?? objectType;
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Converters.SystemTextJson
|
namespace CryptoExchange.Net.Converters.SystemTextJson
|
||||||
{
|
{
|
||||||
@ -197,22 +198,28 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
public override bool OriginalDataAvailable => _stream?.CanSeek == true;
|
public override bool OriginalDataAvailable => _stream?.CanSeek == true;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool Read(Stream stream, bool bufferStream)
|
public async Task<bool> Read(Stream stream, bool bufferStream)
|
||||||
{
|
{
|
||||||
if (bufferStream && stream is not MemoryStream)
|
if (bufferStream && stream is not MemoryStream)
|
||||||
{
|
{
|
||||||
|
// We need to be buffer the stream, and it's not currently a seekable stream, so copy it to a new memory stream
|
||||||
_stream = new MemoryStream();
|
_stream = new MemoryStream();
|
||||||
stream.CopyTo(_stream);
|
stream.CopyTo(_stream);
|
||||||
_stream.Position = 0;
|
_stream.Position = 0;
|
||||||
}
|
}
|
||||||
|
else if (bufferStream)
|
||||||
|
{
|
||||||
|
// We need to buffer the stream, and the current stream is seekable, store as is
|
||||||
|
_stream = stream;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_stream = stream;
|
// We don't need to buffer the stream, so don't bother keeping the reference
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_document = JsonDocument.Parse(_stream);
|
_document = await JsonDocument.ParseAsync(stream).ConfigureAwait(false);
|
||||||
IsJson = true;
|
IsJson = true;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@ -271,7 +278,13 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string GetOriginalString() => Encoding.UTF8.GetString(_bytes.ToArray());
|
public override string GetOriginalString() =>
|
||||||
|
// Netstandard 2.0 doesn't support GetString from a ReadonlySpan<byte>, so use ToArray there instead
|
||||||
|
#if NETSTANDARD2_0
|
||||||
|
Encoding.UTF8.GetString(_bytes.ToArray());
|
||||||
|
#else
|
||||||
|
Encoding.UTF8.GetString(_bytes.Span);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool OriginalDataAvailable => true;
|
public override bool OriginalDataAvailable => true;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Security;
|
using System.Security;
|
||||||
@ -411,6 +413,22 @@ namespace CryptoExchange.Net
|
|||||||
|
|
||||||
return ub.Uri;
|
return ub.Uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Decompress using Gzip
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static ReadOnlyMemory<byte> DecompressGzip(this ReadOnlyMemory<byte> data)
|
||||||
|
{
|
||||||
|
using var decompressedStream = new MemoryStream();
|
||||||
|
using var dataStream = MemoryMarshal.TryGetArray(data, out var arraySegment)
|
||||||
|
? new MemoryStream(arraySegment.Array, arraySegment.Offset, arraySegment.Count)
|
||||||
|
: new MemoryStream(data.ToArray());
|
||||||
|
using var deflateStream = new GZipStream(new MemoryStream(data.ToArray()), CompressionMode.Decompress);
|
||||||
|
deflateStream.CopyTo(decompressedStream);
|
||||||
|
return new ReadOnlyMemory<byte>(decompressedStream.GetBuffer(), 0, (int)decompressedStream.Length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ using CryptoExchange.Net.Objects;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CryptoExchange.Net.Interfaces
|
namespace CryptoExchange.Net.Interfaces
|
||||||
{
|
{
|
||||||
@ -83,7 +84,7 @@ namespace CryptoExchange.Net.Interfaces
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stream"></param>
|
/// <param name="stream"></param>
|
||||||
/// <param name="bufferStream"></param>
|
/// <param name="bufferStream"></param>
|
||||||
bool Read(Stream stream, bool bufferStream);
|
Task<bool> Read(Stream stream, bool bufferStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -38,7 +38,7 @@ namespace CryptoExchange.Net.Interfaces
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Type? GetMessageType(IMessageAccessor messageAccessor);
|
Type? GetMessageType(IMessageAccessor messageAccessor);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deserialize a message int oobject of type
|
/// Deserialize a message into object of type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="accessor"></param>
|
/// <param name="accessor"></param>
|
||||||
/// <param name="type"></param>
|
/// <param name="type"></param>
|
||||||
|
@ -377,7 +377,8 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
|
|
||||||
// 2. Read data into accessor
|
// 2. Read data into accessor
|
||||||
_accessor.Read(data);
|
_accessor.Read(data);
|
||||||
try {
|
try
|
||||||
|
{
|
||||||
if (ApiClient.ApiOptions.OutputOriginalData ?? ApiClient.ClientOptions.OutputOriginalData)
|
if (ApiClient.ApiOptions.OutputOriginalData ?? ApiClient.ClientOptions.OutputOriginalData)
|
||||||
{
|
{
|
||||||
originalData = _accessor.GetOriginalString();
|
originalData = _accessor.GetOriginalString();
|
||||||
@ -400,7 +401,7 @@ namespace CryptoExchange.Net.Sockets
|
|||||||
lock (_listenersLock)
|
lock (_listenersLock)
|
||||||
processors = _listeners.Where(s => s.ListenerIdentifiers.Contains(listenId) && s.CanHandleData).ToList();
|
processors = _listeners.Where(s => s.ListenerIdentifiers.Contains(listenId) && s.CanHandleData).ToList();
|
||||||
|
|
||||||
if (!processors.Any())
|
if (processors.Count == 0)
|
||||||
{
|
{
|
||||||
if (!ApiClient.UnhandledMessageExpected)
|
if (!ApiClient.UnhandledMessageExpected)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user