Skip to content

Commit

Permalink
Cleaned up usages of messages and standardized returning to the cache…
Browse files Browse the repository at this point in the history
… via IDisposable interface.
  • Loading branch information
DJGosnell committed Aug 17, 2023
1 parent 388418f commit 4a8d1a3
Show file tree
Hide file tree
Showing 24 changed files with 342 additions and 223 deletions.
51 changes: 11 additions & 40 deletions src/NexNet.IntegrationTests/ConsoleLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,59 +7,30 @@ public class ConsoleLogger : INexusLogger
private readonly string _prefix;
private DateTime _startTime = DateTime.Now;
public bool LogEnabled = true;
public string? Category { get; }

public ConsoleLogger(string prefix)
{
_prefix = prefix;
}
public void Log(INexusLogger.LogLevel logLevel, Exception? exception, string message)
{
if (!LogEnabled)
return;

Console.WriteLine($"[{DateTime.Now - _startTime:c}]{_prefix}: {message} {exception}");
}
}


public class StreamLogger : INexusLogger
{
public Stream? BaseStream { get; }
private readonly string _prefix;
//private DateTime _startTime = DateTime.Now;
private readonly Stopwatch _sw;
private readonly StreamWriter _logFile;

public StreamLogger(Stream? baseStream = null)
private ConsoleLogger(string prefix, string? category)
{
_prefix = "";
baseStream ??= new MemoryStream(new byte[1024 * 1024]);
BaseStream = baseStream;
_sw = Stopwatch.StartNew();
_logFile = new StreamWriter(baseStream);
}

private StreamLogger(string prefix, StreamWriter sw, Stopwatch stopwatch)
{
_sw = stopwatch;
_logFile = sw;
_prefix = prefix;
}
public void Log(INexusLogger.LogLevel logLevel, Exception? exception, string message)
{
lock (_logFile)
{
_logFile.WriteLine($"[{_sw.ElapsedTicks:000000000}]{_prefix}: {message} {exception}");
}
Category = category;
}

public void Flush()

public void Log(INexusLogger.LogLevel logLevel, string? category, Exception? exception, string message)
{
_logFile.Flush();
if (!LogEnabled)
return;

Console.WriteLine($"[{DateTime.Now - _startTime:c}]{_prefix} [{category}]: {message} {exception}");
}

public StreamLogger CreateSubLogger(string prefix)
public INexusLogger CreateLogger(string? category)
{
return new StreamLogger(prefix, _logFile, _sw);
return new ConsoleLogger(_prefix, category);
}
}
61 changes: 30 additions & 31 deletions src/NexNet/Cache/CacheManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,71 @@ namespace NexNet.Cache;

internal class CacheManager
{

/// <summary>
/// MessageCacheOffsetModifier is a constant used in the CacheManager class to offset the index of the _messageCaches array.
/// This offset is applied when accessing the cache for a specific message type. The offset reduces the staring offset of the array by 100.
/// </summary>
private const int MessageCacheOffsetModifier = 100;

public readonly CachedResettableItem<RegisteredInvocationState> RegisteredInvocationStateCache = new();
public readonly CachedPipeManager PipeManagerCache = new();
public readonly CachedCts CancellationTokenSourceCache = new();
public readonly CachedDuplexPipe NexusDuplexPipeCache = new();
public readonly CachedRentedDuplexPipe NexusRentedDuplexPipeCache = new();

private readonly ICachedDeserializer?[] _cachedMessageDeserializers = new ICachedDeserializer?[50];
private readonly ICachedMessage?[] _messageCaches = new ICachedMessage?[50];

public CacheManager()
{
// This is an integer modifier to reduce the maximum array needed.
const int modifier = 100;

_cachedMessageDeserializers[((int)ClientGreetingMessage.Type - modifier)] =
new CachedDeserializer<ClientGreetingMessage>();
//
_messageCaches[((int)ClientGreetingMessage.Type - MessageCacheOffsetModifier)] =
new CachedCachedMessage<ClientGreetingMessage>();

_cachedMessageDeserializers[((int)ServerGreetingMessage.Type - modifier)] =
new CachedDeserializer<ServerGreetingMessage>();
_messageCaches[((int)ServerGreetingMessage.Type - MessageCacheOffsetModifier)] =
new CachedCachedMessage<ServerGreetingMessage>();

_cachedMessageDeserializers[((int)InvocationMessage.Type - modifier)] =
new CachedDeserializer<InvocationMessage>();
_messageCaches[((int)InvocationMessage.Type - MessageCacheOffsetModifier)] =
new CachedCachedMessage<InvocationMessage>();

_cachedMessageDeserializers[((int)InvocationCancellationMessage.Type - modifier)] =
new CachedDeserializer<InvocationCancellationMessage>();
_messageCaches[((int)InvocationCancellationMessage.Type - MessageCacheOffsetModifier)] =
new CachedCachedMessage<InvocationCancellationMessage>();

_cachedMessageDeserializers[((int)InvocationResultMessage.Type - modifier)] =
new CachedDeserializer<InvocationResultMessage>();
_messageCaches[((int)InvocationResultMessage.Type - MessageCacheOffsetModifier)] =
new CachedCachedMessage<InvocationResultMessage>();

_cachedMessageDeserializers[((int)DuplexPipeUpdateStateMessage.Type - modifier)] =
new CachedDeserializer<DuplexPipeUpdateStateMessage>();
_messageCaches[((int)DuplexPipeUpdateStateMessage.Type - MessageCacheOffsetModifier)] =
new CachedCachedMessage<DuplexPipeUpdateStateMessage>();
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public CachedDeserializer<T> Cache<T>()
where T : IMessageBase, new()
public CachedCachedMessage<T> Cache<T>()
where T : class, IMessageBase, new()
{
// Offset the messages -100 for a smaller array.
return Unsafe.As<CachedDeserializer<T>>(_cachedMessageDeserializers[((int)T.Type) - 100])!;
return Unsafe.As<CachedCachedMessage<T>>(_messageCaches[((int)T.Type) - MessageCacheOffsetModifier])!;
}

public ICachedDeserializer Cache(MessageType type)
public ICachedMessage Cache(MessageType type)
{
return _cachedMessageDeserializers[((int)type) - 100]!;
return _messageCaches[((int)type) - MessageCacheOffsetModifier]!;
}

public T Rent<T>()
where T : IMessageBase, new()
where T : class, IMessageBase, new()
{
return Cache<T>().Rent();
}

public void Return<T>(T message)
where T : IMessageBase, new()
{
Cache<T>().Return(message);
}

public IMessageBase Deserialize(MessageType type, ReadOnlySequence<byte> sequence)
{
return _cachedMessageDeserializers[((int)type) - 100]!.DeserializeInterface(sequence);
return _messageCaches[((int)type) - MessageCacheOffsetModifier]!.DeserializeInterface(sequence);
}

public virtual void Clear()
{
for (int i = 0; i < _cachedMessageDeserializers.Length; i++)
_cachedMessageDeserializers[i]?.Clear();
foreach (var t in _messageCaches)
t?.Clear();

RegisteredInvocationStateCache.Clear();
CancellationTokenSourceCache.Clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@

namespace NexNet.Cache;

internal class CachedDeserializer<T> : ICachedDeserializer
where T : IMessageBase, new()
internal class CachedCachedMessage<T> : ICachedMessage
where T : class, IMessageBase, new()
{
private readonly ConcurrentBag<T> _cache = new();

public T Rent()
{
if (!_cache.TryTake(out var cachedItem))
cachedItem = new T();
cachedItem = new T() { MessageCache = this };

return cachedItem;
}
Expand All @@ -23,7 +23,7 @@ public T Rent()
public T? Deserialize(in ReadOnlySequence<byte> bodySequence)
{
if (!_cache.TryTake(out var cachedItem))
cachedItem = new T();
cachedItem = new T() { MessageCache = this };

MemoryPackSerializer.Deserialize(bodySequence, ref cachedItem);

Expand All @@ -34,28 +34,22 @@ public T Rent()
public IMessageBase DeserializeInterface(in ReadOnlySequence<byte> bodySequence)
{
if (!_cache.TryTake(out var cachedItem))
cachedItem = new T();
cachedItem = new T() { MessageCache = this };

MemoryPackSerializer.Deserialize(bodySequence, ref cachedItem);

return cachedItem!;
}

public void Return(T item)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Return(IMessageBase item)
{
item.Reset();
_cache.Add(item);

item.MessageCache = null;
_cache.Add(Unsafe.As<T>(item));
}

public void Clear()
{
_cache.Clear();
}
}

internal interface ICachedDeserializer
{
void Clear();
IMessageBase DeserializeInterface(in ReadOnlySequence<byte> bodySequence);
}
29 changes: 29 additions & 0 deletions src/NexNet/Cache/ICachedMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System.Buffers;
using NexNet.Messages;

namespace NexNet.Cache;

/// <summary>
/// Defines the operations for a cache that stores and manages messages.
/// </summary>
internal interface ICachedMessage
{
/// <summary>
/// Clears all the messages from the cache.
/// </summary>
void Clear();

/// <summary>
/// Deserializes the given sequence of bytes into a message.
/// </summary>
/// <param name="bodySequence">The sequence of bytes to be deserialized.</param>
/// <returns>The deserialized message.</returns>
IMessageBase DeserializeInterface(in ReadOnlySequence<byte> bodySequence);


/// <summary>
/// Returns the specified message item back to the cache.
/// </summary>
/// <param name="item">The message item to be returned to the cache.</param>
void Return(IMessageBase item);
}
43 changes: 32 additions & 11 deletions src/NexNet/INexusLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ namespace NexNet;
/// </summary>
public interface INexusLogger
{
/// <summary>
/// Category for the log event.
/// </summary>
public string? Category { get; }

/// <summary>
/// Level for the log event.
Expand Down Expand Up @@ -55,19 +59,36 @@ public enum LogLevel
}

/// <summary>
/// Log event invoked on each log occurrence.
/// Logs a message with a specified level, category, and associated exception.
/// </summary>
/// <param name="logLevel">The severity level of the log message.</param>
/// <param name="category">The optional category of the log message.</param>
/// <param name="exception">The exception related to this log event, if any.</param>
/// <param name="message">The log message to be written.</param>
void Log(LogLevel logLevel, string? category, Exception? exception, string message);

/// <summary>
/// Creates a new instance of INexusLogger with the specified category.
/// </summary>
/// <param name="logLevel">Level of the log event.</param>
/// <param name="exception">Optional exception associated with this event.</param>
/// <param name="message">Message for this log event.</param>
void Log(LogLevel logLevel, Exception? exception, string message);
/// <param name="category">The category name for the logger. This value is used to organize and filter log messages.</param>
/// <returns>A new instance of INexusLogger with the specified category.</returns>
INexusLogger CreateLogger(string? category);
}

/// <summary>
/// Common logging extensions.
/// </summary>
public static class NexusLoggerExtensions
{
/// <summary>
/// Creates a new instance of INexusLogger with the category name derived from the type parameter.
/// </summary>
/// <typeparam name="T">The type from which the category name is derived.</typeparam>
/// <returns>A new instance of INexusLogger with the category name derived from the type parameter.</returns>
public static INexusLogger CreateLogger<T>(this INexusLogger logger)
{
return logger.CreateLogger(typeof(T).Name);
}

/// <summary>
/// Log a trace event.
Expand All @@ -87,7 +108,7 @@ public static void LogTrace(this INexusLogger logger, string message)
/// <param name="message">Log message.</param>
public static void LogTrace(this INexusLogger logger, Exception? ex, string message)
{
logger.Log(INexusLogger.LogLevel.Trace, ex, message);
logger.Log(INexusLogger.LogLevel.Trace, logger.Category, ex, message);
}

/// <summary>
Expand All @@ -109,7 +130,7 @@ public static void LogDebug(this INexusLogger logger, string message)
/// <param name="message">Log message.</param>
public static void LogDebug(this INexusLogger logger, Exception? ex, string message)
{
logger.Log(INexusLogger.LogLevel.Debug, ex, message);
logger.Log(INexusLogger.LogLevel.Debug, logger.Category, ex, message);
}


Expand All @@ -131,7 +152,7 @@ public static void LogInfo(this INexusLogger logger, string message)
/// <param name="message">Log message.</param>
public static void LogInfo(this INexusLogger logger, Exception? ex, string message)
{
logger.Log(INexusLogger.LogLevel.Information, ex, message);
logger.Log(INexusLogger.LogLevel.Information, logger.Category, ex, message);
}

/// <summary>
Expand All @@ -152,7 +173,7 @@ public static void LogWarning(this INexusLogger logger, string message)
/// <param name="message">Log message.</param>
public static void LogWarning(this INexusLogger logger, Exception? ex, string message)
{
logger.Log(INexusLogger.LogLevel.Warning, ex, message);
logger.Log(INexusLogger.LogLevel.Warning, logger.Category, ex, message);
}

/// <summary>
Expand All @@ -173,7 +194,7 @@ public static void LogError(this INexusLogger logger, string message)
/// <param name="message">Log message.</param>
public static void LogError(this INexusLogger logger, Exception? ex, string message)
{
logger.Log(INexusLogger.LogLevel.Error, ex, message);
logger.Log(INexusLogger.LogLevel.Error, logger.Category, ex, message);
}

/// <summary>
Expand All @@ -194,7 +215,7 @@ public static void LogCritical(this INexusLogger logger, string message)
/// <param name="message">Log message.</param>
public static void LogCritical(this INexusLogger logger, Exception? ex, string message)
{
logger.Log(INexusLogger.LogLevel.Critical, ex, message);
logger.Log(INexusLogger.LogLevel.Critical, logger.Category, ex, message);
}

}
Loading

0 comments on commit 4a8d1a3

Please sign in to comment.