Browse Source

Added Pool utility class

voice-allocs
RogueException 7 years ago
parent
commit
5005ddf98a
6 changed files with 90 additions and 26 deletions
  1. +3
    -3
      src/Discord.Net.Core/Discord.Net.Core.csproj
  2. +7
    -12
      src/Discord.Net.Rest/DiscordRestApiClient.cs
  3. +3
    -3
      src/Discord.Net.Rpc/DiscordRpcApiClient.cs
  4. +71
    -0
      src/Discord.Net.Serialization/Utils/Pool.cs
  5. +2
    -3
      src/Discord.Net.WebSocket/DiscordSocketApiClient.cs
  6. +4
    -5
      src/Discord.Net.WebSocket/DiscordVoiceApiClient.cs

+ 3
- 3
src/Discord.Net.Core/Discord.Net.Core.csproj View File

@@ -7,11 +7,11 @@
<TargetFrameworks>net45;netstandard1.1;netstandard1.3</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Buffers" Version="4.4.0-preview2-25405-01" />
<PackageReference Include="System.Collections.Immutable" Version="1.3.1" />
<PackageReference Include="System.Buffers" Version="4.4.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
<PackageReference Include="System.Interactive.Async" Version="3.1.1" />
<PackageReference Include="System.Memory" Version="4.4.0-preview2-25405-01" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0-preview2-25405-01" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Discord.Net.Serialization\Discord.Net.Serialization.csproj" />


+ 7
- 12
src/Discord.Net.Rest/DiscordRestApiClient.cs View File

@@ -4,8 +4,6 @@ using Discord.Net;
using Discord.Net.Queue;
using Discord.Net.Rest;
using Discord.Serialization;
using Discord.Serialization.Json;
using Discord.Serialization.Json.Converters;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -13,7 +11,6 @@ using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Formatting;
@@ -31,7 +28,7 @@ namespace Discord.API
protected readonly SemaphoreSlim _stateLock;
protected readonly Serializer _serializer;
protected readonly ConcurrentQueue<ArrayFormatter> _formatters;
protected readonly Pool<ArrayFormatter> _formatters;
private readonly RestClientProvider _restClientProvider;

protected bool _isDisposed;
@@ -56,7 +53,7 @@ namespace Discord.API

RequestQueue = new RequestQueue();
_stateLock = new SemaphoreSlim(1, 1);
_formatters = new ConcurrentQueue<ArrayFormatter>();
_formatters = new Pool<ArrayFormatter>(() => new ArrayFormatter(128, SymbolTable.InvariantUtf8));

SetBaseUrl(DiscordConfig.APIUrl);
}
@@ -190,9 +187,8 @@ namespace Discord.API
options.HeaderOnly = true;
options.BucketId = AuthTokenType == TokenType.User ? ClientBucket.Get(clientBucket).Id : bucketId;
options.IsClientBucket = AuthTokenType == TokenType.User;

if (!_formatters.TryDequeue(out var data))
data = new ArrayFormatter(128, SymbolTable.InvariantUtf8);
var data = _formatters.Rent();
try
{
var request = new JsonRestRequest(RestClient, method, endpoint, SerializeJson(data, payload), options);
@@ -201,7 +197,7 @@ namespace Discord.API
finally
{
data.Clear();
_formatters.Enqueue(data);
_formatters.Return(data);
}
}

@@ -244,8 +240,7 @@ namespace Discord.API
options.BucketId = AuthTokenType == TokenType.User ? ClientBucket.Get(clientBucket).Id : bucketId;
options.IsClientBucket = AuthTokenType == TokenType.User;

if (!_formatters.TryDequeue(out var data))
data = new ArrayFormatter(128, SymbolTable.InvariantUtf8);
var data = _formatters.Rent();
try
{
var request = new JsonRestRequest(RestClient, method, endpoint, SerializeJson(data, payload), options);
@@ -254,7 +249,7 @@ namespace Discord.API
finally
{
data.Clear();
_formatters.Enqueue(data);
_formatters.Return(data);
}
}



+ 3
- 3
src/Discord.Net.Rpc/DiscordRpcApiClient.cs View File

@@ -225,8 +225,7 @@ namespace Discord.API
private async Task<TResponse> SendRpcAsyncInternal<TResponse>(string cmd, object payload, Optional<string> evt, RequestOptions options)
where TResponse : class, new()
{
if (_formatters.TryDequeue(out var data))
data = new ArrayFormatter(128, SymbolTable.InvariantUtf8);
var data = _formatters.Rent();
try
{
var guid = Guid.NewGuid();
@@ -241,7 +240,8 @@ namespace Discord.API
}
finally
{
_formatters.Enqueue(data);
data.Clear();
_formatters.Return(data);
}
}



+ 71
- 0
src/Discord.Net.Serialization/Utils/Pool.cs View File

@@ -0,0 +1,71 @@
using System;
using System.Diagnostics;
using System.Threading;

namespace Discord.Serialization
{
//TODO: Replace pools in audio with this
public sealed class Pool<T>
where T : class
{
private const int DefaultMaxElementsPerBucket = 50;

private readonly T[] _buffer;
private readonly Func<T> _createFunc;

private SpinLock _lock;
private int _index;

public Pool(Func<T> createFunc)
: this(createFunc, DefaultMaxElementsPerBucket) { }
public Pool(Func<T> createFunc, int maxElementsPerBucket)
{
_createFunc = createFunc;
_lock = new SpinLock(Debugger.IsAttached);
_buffer = new T[maxElementsPerBucket];
}

public T Rent()
{
T result = null;
bool lockTaken = false;
try
{
_lock.Enter(ref lockTaken);

if (_index < _buffer.Length)
{
result = _buffer[_index];
_buffer[_index++] = null;
}
}
finally
{
if (lockTaken)
_lock.Exit(false);
}
if (result == null)
result = _createFunc();

return result;
}

public void Return(T obj)
{
bool lockTaken = false;
try
{
_lock.Enter(ref lockTaken);

if (_index != 0)
_buffer[--_index] = obj;
}
finally
{
if (lockTaken)
_lock.Exit(false);
}
}
}
}

+ 2
- 3
src/Discord.Net.WebSocket/DiscordSocketApiClient.cs View File

@@ -174,8 +174,7 @@ namespace Discord.API
{
CheckState();

if (!_formatters.TryDequeue(out var data))
data = new ArrayFormatter(128, SymbolTable.InvariantUtf8);
var data = _formatters.Rent();
try
{
var frame = new GatewaySocketFrame { Operation = opCode, Payload = payload };
@@ -185,7 +184,7 @@ namespace Discord.API
finally
{
data.Clear();
_formatters.Enqueue(data);
_formatters.Return(data);
}
}



+ 4
- 5
src/Discord.Net.WebSocket/DiscordVoiceApiClient.cs View File

@@ -41,7 +41,7 @@ namespace Discord.Audio
private readonly Serializer _serializer;
private readonly SemaphoreSlim _connectionLock;
private readonly MemoryStream _decompressionStream;
protected readonly ConcurrentQueue<ArrayFormatter> _formatters;
protected readonly Pool<ArrayFormatter> _formatters;

private CancellationTokenSource _connectCancelToken;
private IUdpSocket _udp;
@@ -61,7 +61,7 @@ namespace Discord.Audio
_udp = udpSocketProvider();
_udp.ReceivedDatagram += (data, index, count) => _receivedPacketEvent.InvokeAsync(data, index, count);
_serializer = serializer;
_formatters = new ConcurrentQueue<ArrayFormatter>();
_formatters = new Pool<ArrayFormatter>(() => new ArrayFormatter(128, SymbolTable.InvariantUtf8));

_decompressionStream = new MemoryStream(10 * 1024); //10 KB

@@ -114,8 +114,7 @@ namespace Discord.Audio

public async Task SendAsync(VoiceOpCode opCode, object payload, RequestOptions options = null)
{
if (!_formatters.TryDequeue(out var data))
data = new ArrayFormatter(128, SymbolTable.InvariantUtf8);
var data = _formatters.Rent();
try
{
var frame = new VoiceSocketFrame { Operation = opCode, Payload = payload };
@@ -125,7 +124,7 @@ namespace Discord.Audio
finally
{
data.Clear();
_formatters.Enqueue(data);
_formatters.Return(data);
}
}
public async Task SendAsync(byte[] data, int offset, int bytes)


Loading…
Cancel
Save