2014-01-23 1 views
0

У меня есть большая коллекция элементов. Я хочу вызвать ToString для каждого элемента и построить одну строку. Мой первый подход к медленномус использованием PLINQ или Parallel с сохранением первоначального заказа

 string str = ""; 
     list.ForEach(g => { 

      string s = g.ToString(); 
      if(s != "") 
       str = str + g.ToString() + "\n"; 
     }); 

Я попытался с помощью параллельного класса и PLINQ, как показано ниже, но тогда порядок элементов в конечной строке не было, как в оригинале.

Parallel

 System.Threading.Tasks.Parallel.ForEach(list, g => { 

      string s = g.ToString(); 
      if(s != "") 
       str = str + g.ToString() + "\n"; 
     }); 

PLINQ

 string str = ""; 
     list.AsParallel().AsOrdered().ForAll(g => { 

      string s = g.ToString(); 
      if(s != "") 
       str = str + g.ToString() + "\n"; 
     }); 

Как я могу улучшить производительность и сохранить первоначальный заказ? Thanks

+0

'AsOrdered()' только сохраняет заказ в отношении первоначального заказа. Так что, если заказ отличается от ForEach, тогда вам нужно его отсортировать. – Zache

+3

Я не знаю, как сохранить порядок (или даже если это возможно), но вы должны использовать StringBuilder вместо конкатенации строк. – krimog

+0

изменен на использование Stringbuilder без параллелизма, и он решил проблему. Спасибо всем – gerstla

ответ

0

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

В настоящее время, ваш код O (п), потому что каждый конкатенация создает совершенно новую строку и поэтому он должен скопировать всю предыдущую строку в новом.

Но вы можете сделать это om O (n), если вы используете изменчивый StringBuilder вместо неизменяемого string. Таким образом, вы можете просто добавить в конец существующего StringBuilder, и вам нечего копировать.

И вы также можете достичь той же производительности с меньшим количеством кода, используя специальный метод, только для соединения строк: string.Join().


Но может быть еще лучше решение: использовать StreamWriter. Например, если вы хотите записать результирующую строку в файл, это будет лучшее решение, потому что вся строка не обязательно должна быть в памяти.


Параллелизм - это не то, что волшебным образом решит все ваши проблемы с производительностью. Вам нужно подумать о том, что будут делать потоки, особенно если у вас есть общие данные (например, str в вашем коде). В вашем случае вы можете попытаться использовать параллелизм, но это было бы не так просто, и я не уверен, что это действительно улучшит производительность.

Он будет работать следующим образом: каждый поток будет получать ряд индексов в списке и объединить их. В конце основной поток затем объединяет результаты всех потоков вместе. Но для этого нет встроенного метода, поэтому вам нужно будет написать весь этот код самостоятельно. (Это будет работать, поскольку конкатенация строк равна associative.)