Skip to content

Commit

Permalink
Done (#602)
Browse files Browse the repository at this point in the history
  • Loading branch information
imperugo authored Jan 19, 2025
1 parent d21f699 commit 803fb2a
Show file tree
Hide file tree
Showing 14 changed files with 203 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static IServiceCollection AddStackExchangeRedisExtensions<T>(
RedisConfiguration redisConfiguration)
where T : class, ISerializer
{
return services.AddStackExchangeRedisExtensions<T>(sp => new[] { redisConfiguration });
return services.AddStackExchangeRedisExtensions<T>(sp => [redisConfiguration]);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class RedisConfiguration
private int syncTimeout = 1000;
private bool abortOnConnectFail;
private int database;
private RedisHost[] hosts = Array.Empty<RedisHost>();
private RedisHost[] hosts = [];
private ServerEnumerationStrategy serverEnumerationStrategy = new();
private uint maxValueLength;
private int poolSize = 5;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;

using StackExchange.Redis.Extensions.Core.Models;

namespace StackExchange.Redis.Extensions.Core.Extensions;

internal static class SpanExtensions
{
public static void EnumerateLines(this ReadOnlySpan<char> span, ref List<InfoDetail> data, ref string category)
{
var start = 0;

while (start < span.Length)
{
var end = span[start..].IndexOf('\n');
ReadOnlySpan<char> line;

if (end == -1)
{
line = span[start..].Trim();
start = span.Length; // Termina il loop
}
else
{
line = span[start..(start + end)].Trim();
start += end + 1;
}

// Gestisci ogni riga
if (line.IsEmpty)
continue;

if (line[0] == '#')
{
category = line[1..].Trim().ToString();
continue;
}

var idx = line.IndexOf(':');
if (idx > 0)
{
var key = line[..idx].Trim();
var infoValue = line[(idx + 1)..].Trim();

data.Add(new InfoDetail(category, key.ToString(), infoValue.ToString()));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ public static IEnumerable<KeyValuePair<string, byte[]>> OfValueInListSize<T>(thi
public static byte[] OfValueSize<T>(this T? value, ISerializer serializer, uint maxValueLength, string key)
{
return value == null
? Array.Empty<byte>()
? []
: serializer.Serialize(value).CheckLength(maxValueLength, key);
}

private static byte[] SerializeItem<T>(this T? item, ISerializer serializer)
{
return item == null
? Array.Empty<byte>()
? []
: serializer.Serialize(item);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace StackExchange.Redis.Extensions.Core.Helpers;

internal static class GenericsExtensions
{
public static void FastIteration<TSource>(this ICollection<TSource>? request, Action<TSource, int> action)
{
if (request == null)
return;

if (request is TSource[] sourceArray)
{
ref var searchSpace = ref MemoryMarshal.GetReference(sourceArray.AsSpan());

for (var i = 0; i < sourceArray.Length; i++)
{
ref var r = ref Unsafe.Add(ref searchSpace, i);

action.Invoke(r, i);
}
}
else
{
var i = 0;
foreach (var r in request)
action.Invoke(r, i++);
}
}

public static TResult[] ToFastArray<TSource, TResult>(this ICollection<TSource>? request, Func<TSource, TResult> action)
{
if (request == null)
return [];

var result = new TResult[request.Count];

if (request is TSource[] sourceArray)
{
ref var searchSpace = ref MemoryMarshal.GetReference(sourceArray.AsSpan());

for (var i = 0; i < sourceArray.Length; i++)
{
ref var r = ref Unsafe.Add(ref searchSpace, i);

result[i] = action.Invoke(r);
}
}
/*
This could be helpful when we drop old frameworks
else if (request is List<TSource> sourceList)
{
var span = CollectionsMarshal.AsSpan(sourceList);
ref var searchSpace = ref MemoryMarshal.GetReference(span);
for (var i = 0; i < span.Length; i++)
{
ref var r = ref Unsafe.Add(ref searchSpace, i);
result[i] = action.Invoke(r);
}
}
*/
else
{
var i = 0;
foreach (var r in request)
result[i++] = action.Invoke(r);
}

return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
Expand Down Expand Up @@ -36,9 +38,11 @@ public RedisClientFactory(IEnumerable<RedisConfiguration> configurations, ILogge
if (redisConfigurations.Length == 1)
redisConfigurations[0].IsDefault = true;

ref var searchSpace = ref MemoryMarshal.GetReference(redisConfigurations.AsSpan());

for (var i = 0; i < redisConfigurations.Length; i++)
{
var configuration = redisConfigurations[i];
ref var configuration = ref Unsafe.Add(ref searchSpace, i);

if (configuration.IsDefault && hasDefaultConfigured)
throw new ArgumentException("There is more than one default configuration. Only one default configuration is allowed.");
Expand Down Expand Up @@ -70,7 +74,7 @@ public RedisClientFactory(IEnumerable<RedisConfiguration> configurations, ILogge

for (var i = 0; i < redisConfigurations.Length; i++)
{
var configuration = redisConfigurations[i];
ref var configuration = ref Unsafe.Add(ref searchSpace, i);

var poolManager = new RedisConnectionPoolManager(configuration, poolManagerLogger);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
/* Unmerged change from project 'StackExchange.Redis.Extensions.Core(net6.0)'
Before:
Expand Down Expand Up @@ -107,7 +109,7 @@ var nextIdx
break;

case ConnectionSelectionStrategy.LeastLoaded:
connection = ValueLengthExtensions.MinBy(connections, x => x.TotalOutstanding());
connection = connections.MinBy(x => x.TotalOutstanding());
break;

default:
Expand All @@ -133,8 +135,12 @@ public ConnectionPoolInformation GetConnectionInformation()
var activeConnections = 0;
var invalidConnections = 0;

foreach (var connection in connections)
ref var searchSpace = ref MemoryMarshal.GetReference(connections.AsSpan());

for (var i = 0; i < connections.Length; i++)
{
ref var connection = ref Unsafe.Add(ref searchSpace, i);

if (!connection.IsConnected())
{
invalidConnections++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

using StackExchange.Redis.Extensions.Core.Helpers;

namespace StackExchange.Redis.Extensions.Core.Implementations;

public partial class RedisDatabase
Expand Down Expand Up @@ -65,8 +69,13 @@ await Parallel.ForEachAsync(keys, async (key, _) =>

var result = new Dictionary<string, T?>();

ref var searchSpace = ref MemoryMarshal.GetReference(tasks.AsSpan());

for (var i = 0; i < tasks.Length; i++)
result.Add(keys[i], tasks[i].Result);
{
ref var task = ref Unsafe.Add(ref searchSpace, i);
result.Add(keys[i], task.Result);
}

return result;
#endif
Expand All @@ -77,12 +86,7 @@ await Parallel.ForEachAsync(keys, async (key, _) =>
{
var luascript = "local results = {};local insert = table.insert;local rcall = redis.call;for i=1,table.getn(KEYS) do local value = rcall('HGET','" + hashKey + "', KEYS[i]) if value then insert(results, KEYS[i]) insert(results, value) end end; return results;";

var list = new List<RedisKey>();

foreach (var key in keys)
list.Add(new RedisKey(key));

var redisKeys = list.ToArray();
var redisKeys = keys.ToFastArray(key => new RedisKey(key));

var data = await Database.ScriptEvaluateAsync(luascript, redisKeys, flags: flag).ConfigureAwait(false);

Expand All @@ -93,12 +97,14 @@ await Parallel.ForEachAsync(keys, async (key, _) =>

var redisValues = ((RedisValue[]?)data);

if (redisValues == null || redisValues.Length <= 0)
ref var searchSpaceRedisValue = ref MemoryMarshal.GetReference(redisValues.AsSpan());

if (redisValues is not { Length: > 0 })
return dictionary;

for (var i = 0; i < redisValues.Length; i += 2)
{
var key = redisValues[i];
ref var key = ref Unsafe.Add(ref searchSpaceRedisValue, i);

if (key.HasValue == false)
continue;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Copyright (c) Ugo Lattanzi. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.

using System;
using System.Linq;
using System.Threading.Tasks;

using StackExchange.Redis.Extensions.Core.Helpers;

namespace StackExchange.Redis.Extensions.Core.Implementations;

public partial class RedisDatabase
Expand Down Expand Up @@ -31,7 +32,7 @@ public Task<long> ListAddToLeftAsync<T>(string key, T[] items, CommandFlags flag
if (items == null)
throw new ArgumentNullException(nameof(items), "item cannot be null.");

var serializedItems = items.Select(x => (RedisValue)Serializer.Serialize(x)).ToArray();
var serializedItems = items.ToFastArray(item => (RedisValue)Serializer.Serialize(item));

return Database.ListLeftPushAsync(key, serializedItems, flag);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using System.Collections.Generic;
using System.Threading.Tasks;

using StackExchange.Redis.Extensions.Core.Helpers;

namespace StackExchange.Redis.Extensions.Core.Implementations;

public partial class RedisDatabase
Expand Down Expand Up @@ -67,51 +69,27 @@ public async Task<bool> UpdateExpiryAsync(string key, TimeSpan expiresIn, Comman
/// <inheritdoc/>
public async Task<IDictionary<string, bool>> UpdateExpiryAllAsync(HashSet<string> keys, DateTimeOffset expiresAt, CommandFlags flag = CommandFlags.None)
{
var tasks = new Task<bool>[keys.Count];

var i = 0;
foreach (var key in keys)
{
tasks[i] = UpdateExpiryAsync(key, expiresAt.UtcDateTime, flag);
i++;
}
var tasks = keys.ToFastArray(key => UpdateExpiryAsync(key, expiresAt.UtcDateTime, flag));

await Task.WhenAll(tasks).ConfigureAwait(false);

var results = new Dictionary<string, bool>(keys.Count, StringComparer.Ordinal);

i = 0;
foreach (var key in keys)
{
results.Add(key, tasks[i].Result);
i++;
}
keys.FastIteration((key, i) => results.Add(key, tasks[i].Result));

return results;
}

/// <inheritdoc/>
public async Task<IDictionary<string, bool>> UpdateExpiryAllAsync(HashSet<string> keys, TimeSpan expiresIn, CommandFlags flag = CommandFlags.None)
{
var tasks = new Task<bool>[keys.Count];

var i = 0;
foreach (var key in keys)
{
tasks[i] = UpdateExpiryAsync(key, expiresIn, flag);
i++;
}
var tasks = keys.ToFastArray(key => UpdateExpiryAsync(key, expiresIn, flag));

await Task.WhenAll(tasks).ConfigureAwait(false);

var results = new Dictionary<string, bool>(keys.Count, StringComparer.Ordinal);

i = 0;
foreach (var key in keys)
{
results.Add(key, tasks[i].Result);
i++;
}
keys.FastIteration((key, i) => results.Add(key, tasks[i].Result));

return results;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using System.Threading.Tasks;

using StackExchange.Redis.Extensions.Core.Helpers;
using StackExchange.Redis.Extensions.Core.Models;

namespace StackExchange.Redis.Extensions.Core.Implementations;
Expand Down Expand Up @@ -59,14 +60,6 @@ public async Task<IEnumerable<ScoreRankResult<T>>> SortedSetRangeByRankWithScore
{
var result = await Database.SortedSetRangeByRankWithScoresAsync(key, start, stop, order, commandFlags).ConfigureAwait(false);

var list = new ScoreRankResult<T>[result.Length];

for (var i = 0; i < result.Length; i++)
{
var x = result[i];
list[i] = new ScoreRankResult<T>(Serializer.Deserialize<T>(x.Element!), x.Score);
}

return list;
return result.ToFastArray(x => new ScoreRankResult<T>(Serializer.Deserialize<T>(x.Element!), x.Score));
}
}
Loading

0 comments on commit 803fb2a

Please sign in to comment.