Я пытаюсь вставить большое (не очень) количество элементов в кратчайшие сроки, и я пробовал эти две альтернативы:
1) Конвейерная обработка:
List<Task> addTasks = new List<Task>();
for (int i = 0; i < table.Rows.Count; i++)
{
DataRow row = table.Rows[i];
Task<bool> addAsync = redisDB.SetAddAsync(string.Format(keyFormat, row.Field<int>("Id")), row.Field<int>("Value"));
addTasks.Add(addAsync);
}
Task[] tasks = addTasks.ToArray();
Task.WaitAll(tasks);
2) Дозирование:
List<Task> addTasks = new List<Task>();
IBatch batch = redisDB.CreateBatch();
for (int i = 0; i < table.Rows.Count; i++)
{
DataRow row = table.Rows[i];
Task<bool> addAsync = batch.SetAddAsync(string.Format(keyFormat, row.Field<int>("Id")), row.Field<int>("Value"));
addTasks.Add(addAsync);
}
batch.Execute();
Task[] tasks = addTasks.ToArray();
Task.WaitAll(tasks);
Я не замечаю какой-либо значительной разницы во времени (на самом деле я ожидал, что пакетный метод будет быстрее): для примерно 250K вставок я получаю примерно 7 секунд для конвейерной обработки против примерно 8 секунд для пакетной обработки.
Читая документацию по конвейеризации,
«Использование конвейерной обработки позволяет нам немедленно получить оба запроса в сети, устраняя большую часть задержки. Кроме того, это также помогает уменьшить фрагментацию пакетов: 20 запросов, отправленных по отдельности (ожидающих каждого ответа), потребуют как минимум 20 пакетов, но отправлено 20 запросов. в конвейере может поместиться гораздо меньшее количество пакетов (возможно, даже один) ».
Для меня это звучит очень похоже на пакетное поведение. Интересно, есть ли за кадром какая-то большая разница между ними, потому что при простой проверке с помощью procmon
я вижу почти одинаковое количество TCP Send
в обеих версиях.