StackExchange.Redis icon indicating copy to clipboard operation
StackExchange.Redis copied to clipboard

performance advise

Open pianoman4873 opened this issue 1 year ago • 3 comments

Hello, Assuming funcAsync are mainly readAsync / writeAsync calls to Redis using the StackExchange.Redis client - which implementation of BatchExecuteAsync would be preferrable for better throughput / efficiency etc. ( especially when considering nature of the multiplexing going on behind the scenes ) ?

Thanks

public static async Task BatchedExecuteAsync<TItem>(this List<TItem> items, Func<TItem, Task> funcAsync, int amountOfParallelism)
{
    
    var tasks = new List<Task>(amountOfParallelism);
    int index = 0;
    for (var i = 0; i < amountOfParallelism; i++)
    {
        tasks.Add(Task.Run(async () =>
        {
            while (true)
            {
                TItem item;
                lock (tasks)
                {
                    if (index >= items.Count)
                    {
                        break;
                    }

                    item = items[index];
                    index++;
                }

                await funcAsync(item);
            }
        }));
    }

    await Task.WhenAll(tasks);
}


 public static async Task BatchedExecuteAsync<TItem>(this IEnumerable<TItem> items, Func<TItem,Task> funcAsync, int amountOfParallelism)
        {

            var tasks = new List<Task>(amountOfParallelism);
            foreach (var item in items)
            {
                tasks.Add(funcAsync ( item));
                if (tasks.Count == amountOfParallelism)
                {
                    await Task.WhenAll(tasks);
                    tasks.Clear();
                }
            }
            if (tasks.Count > 0)
            {
                await Task.WhenAll(tasks);
                
            }
     }

pianoman4873 avatar Oct 31 '23 09:10 pianoman4873

What are you trying to accomplish in your batching here? Why are you batching? (We need more context to answer this - looking immediately I couldn't recommend either implementation as there's extra async and allocation overhead happening when you can likely avoid it)

NickCraver avatar Nov 23 '23 00:11 NickCraver

Hi, I'm trying to process many requests ( for example read requests for various keys ) - I assume sending them all and await them all together would incur too much load , so batching is used.

pianoman4873 avatar Dec 10 '23 08:12 pianoman4873

There's no significant difference between those two scenarios (with/without batch), except that when using the batch API you're delaying the first send by a few picoseconds (until you call execute). However: if your use case is reading multiple keys, then: a multi-key fetch already exists - maybe just use that? (if the key volume is huge you may want to split this into chunks so you don't block competing clients)

mgravell avatar Dec 10 '23 11:12 mgravell