Я пытаюсь вставить большое (-ish) количество элементов в кратчайшие возможные сроки, и я попробовал эти две альтернативы:
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);
Я не замечаю существенной разницы во времени (на самом деле я ожидал, что пакетный метод будет более быстрым): для примерно 250 тыс. вставок я получаю около 7 сек для конвейерной обработки и около 8 сек для дозирования.
Чтение из документации по конвейерной обработке,
"Использование конвейерной обработки позволяет нам получить оба запроса в сети немедленно, устраняя большую часть задержки. Кроме того, он также помогает уменьшить фрагментацию пакетов: 20 запросов, отправленных индивидуально (ожидание каждого ответа) потребует не менее 20 пакетов, но 20 запросы, отправленные в конвейере, могут входить в гораздо меньшее количество пакетов (возможно, даже один).
Для меня это звучит очень похоже на поведение пакетной обработки. Интересно, есть ли за кулисами какая-то большая разница между ними, потому что при простой проверке с procmon
я вижу почти то же количество TCP Send
в обеих версиях.