У меня есть постоянный поток определенных элементов, которые мне нужно обрабатывать параллельно, поэтому я использую TPL Dataflow
. Уловка состоит в том, что элементы, которые имеют один и тот же ключ (аналогично словарю), должны обрабатываться в порядке FIFO и не быть параллельными друг другу (они могут быть параллельны другим элементам с разными значениями).Hashed/Sharded ActionBlocks
Работы делается очень ЦП с минимальными асинхронными замками так что мое решением было создать массив ActionBlock<T>
сек размера Environment.ProcessorCount
, без параллельности и после них в соответствии с GetHashCode
значения этого ключом.
Создание:
_actionBlocks = new ActionBlock<Item>[Environment.ProcessorCount];
for (int i = 0; i < _actionBlocks.Length; i++)
{
_actionBlocks[i] = new ActionBlock<Item>(_ => ProcessItemAsync(_));
}
Использование:
bool ProcessItem(Key key, Item item)
{
var actionBlock = _actionBlocks[(uint)key.GetHashCode() % _actionBlocks.Length];
return actionBlock.Post(item);
}
Итак, мой вопрос, является ли это лучшим решением моей проблемы? Я ушибаю производительность/масштабируемость? Я что-то упускаю?
Мне это нравится. Я не могу придумать другой метод, который не требует хранения. Я думаю, что до тех пор, пока вы убедитесь, что ваши хэш-коды правильно распределены, это должно быть хорошо. – spender
Опираясь на значение 'GetHashCode', звучит очень странно, почему у вас это есть? Является ли фактическое требование «равными статьями» в порядке FIFO? – svick
@svick больше похоже. Элементы с одним и тем же ключом должны обрабатываться в порядке FIFO, аналогично тому, как вы будете использовать словарь (на самом деле не обязательно быть одним и тем же типом элемента). Я уточню вопрос, чтобы сделать это более ясным. – i3arnon