Как правильно распараллеливать задания, сильно зависящие от ввода-вывода

Я создаю консольное приложение, которое должно обрабатывать кучу данных.

По сути, приложение получает ссылки из БД. Для каждой ссылки проанализируйте содержимое файла и внесите некоторые изменения. Файлы представляют собой файлы HTML, и в процессе выполняется тяжелая работа с заменами RegEx (поиск ссылок и преобразование их в ссылки). Затем результаты сохраняются в файловой системе и отправляются во внешнюю систему.

Если я возобновлю процесс, последовательно:

var refs = GetReferencesFromDB(); // ~5000 Datarow returned
foreach(var ref in refs)
{
    var filePath = GetFilePath(ref); // This method looks up in a previously loaded file list
    var html = File.ReadAllText(filePath); // Read html locally, or from a network drive
    var convertedHtml = ParseHtml(html);
    File.WriteAllText(destinationFilePath); // Copy the result locally, or a network drive
    SendToWs(ref, convertedHtml);
}

Моя программа работает правильно, но довольно медленно. Вот почему я хочу распараллелить процесс.

К настоящему времени я сделал простую параллелизацию, добавив AsParallel:

var refs = GetReferencesFromDB().AsParallel(); 
refs.ForAll(ref=>
{
    var filePath = GetFilePath(ref); 
    var html = File.ReadAllText(filePath); 
    var convertedHtml = ParseHtml(html);
    File.WriteAllText(destinationFilePath); 
    SendToWs(ref, convertedHtml);
});

Это простое изменение уменьшило продолжительность процесса (на 25% меньше времени). Однако я понимаю, что с распараллеливанием не будет больших преимуществ (или, что еще хуже, меньше преимуществ), если распараллеливать ресурсы, полагающиеся на ввод-вывод, потому что ввод-вывод волшебным образом не удваивается.

Вот почему я думаю, что мне следует изменить свой подход, чтобы не распараллеливать весь процесс, а создать зависимые задачи с цепочкой в ​​очереди.

То есть, мне нужно создать поток вроде:

Очередь чтения файла. Когда закончите, Queue ParseHtml. По завершении Queue отправляет на WS и записывает локально. Когда закончите, запишите результат.

Однако я не знаю, как реализовать такую ​​мысль.

Я думаю, что он закончится набором очередей потребителей / производителей, но я не нашел правильного образца.

И более того, я не уверен, будет ли польза.

спасибо за советы

[Edit] На самом деле, я идеальный кандидат для использования C # 4.5 ... если бы это был rtm :)

[Edit 2] Еще одна вещь, заставляющая меня думать, что она неправильно распараллеливается, заключается в том, что в мониторе ресурсов я вижу нестабильные графики ЦП, сетевого ввода-вывода и дискового ввода-вывода. когда один высокий, другие от низкого до среднего

22
задан Steve B 14 December 2011 в 14:07
поделиться