У меня проблема с медленным "построением" списка, и у меня нет идеи, как его ускорить. Вот мой код:
private static ConcurrentBag<Classe<PojedynczeSlowa>> categoryClasses = new ConcurrentBag<Classe<PojedynczeSlowa>>();
private const int howManyStudents = 20;
private static int howManyClasses;
private static EventWaitHandle[] ewhClass;
private static List<Classe<Words>> deserializeClasses;
//...
public static void CreateCategoryClasses()
{
deserializeClasses = Deserialize();
howManyClasses = deserializeClasses.Count;
ewhClass = new EventWaitHandle[howManyClasses];
for (var i = 4; i >= 0; --i)
{
categoryClasses.Add(new Classe<PojedynczeSlowa>(((Categories) i).ToString()));
}
WaitCallback threadMethod = ParseCategories;
ThreadPool.SetMaxThreads(howManyStudents, howManyClasses);
for (var i = 0; i < howManyClasses; ++i)
{
ewhClass[i] = new EventWaitHandle(false, EventResetMode.AutoReset);
ThreadPool.QueueUserWorkItem(threadMethod, i);
}
for (var i = 0; i < howManyClasses; ++i)
{
ewhClass[i].WaitOne();
}
var xmls = new XmlSerializer(typeof(List<Classe<PojedynczeSlowa>>)); //poprawić!!
using (var sw = new StreamWriter(@"categoryClasses.xml"))
{
xmls.Serialize(sw, categoryClasses.ToList());
}
}
private static void ParseCategories(object index)
{
int sum;
var i = index as int?;
if (deserializeClasses[i.Value].Category == Categories.PEOPLE.ToString())
{
foreach (var word in deserializeClasses[i.Value].Bag)
{
sum =
deserializeClasses.Count(
clas =>
clas.Bag.Where(x => clas.Category == deserializeClasses[i.Value].Category)
.Contains(word));
if (!categoryClasses.ElementAt(0).Bag.Contains(new PojedynczeSlowa(word.Word, sum)))
{
categoryClasses.ElementAt(0)
.Bag.Add(new PojedynczeSlowa(word.Word,
Convert.ToDouble(sum)/
Convert.ToDouble(deserializeClasses.Count(x => x.Category == deserializeClasses[i.Value].Category))));
}
}
}
//rest of the code which adds elements to the list on other indexes.
ewhClass[(i).Value].Set();
}
Я мог бы добавить, что:
deserializeClasses содержит около 18550 элементов класса "Слово",
и любой из этих элементов ("Word") содержит список строк и int, средний размер этого списка составляет около 200-250 элементов. Я использую.net 4.5.1 Спасибо за помощь!
Пара вещей (у меня недостаточно комментариев, чтобы комментировать, поэтому мои комментарии здесь тоже)...
1) Определения классов будут очень полезными. Например, у вас есть if (!categoryClasses.ElementAt(0).Bag.Contains(new PojedynczeSlowa(word.Word, sum)))
который никогда не будет прав, если вы не переопределили object.Equals (не так ли?). Кроме того, гораздо труднее узнать, что происходит с неполным образцом.
2) Ваш код sum = deserializeClasses.Count(clas => clas.Bag.Where(x => clas.Category == deserializeClasses[i.Value].Category).Contains(word));
вообще не использует x. Рассматривать sum = deserializeClasses.Count(clas => clas.Category == deserializeClasses[i.Value].Category && clas.Bag.Contains(word));
Это позволяет избежать большого количества потенциальных перерасчетов и может ускорить среднюю стоимость, даже несмотря на то, что стоимость наихудшего случая остается неизменной.
3) Словари - ваш друг. Подумайте о том, чтобы сделать некоторые временные словари, индексированные тем, что вы проверяете. Мне сложно определить, что именно вы пытаетесь сделать (см. Комментарий 1), но я предполагаю, что вы могли бы сэкономить немало стоимости исполнения, в частности вызов Contains(), используя словарь.
4) Я не уверен, что многопоточность поможет вам сэкономить. Я предполагаю, что это замедлит работу, так как это выглядит как CPU, и вы добавляете накладные расходы процессора с переключением потоков.
Я бы помог с некоторым кодом, но я немного тороплюсь и не успеваю догадаться о остальном недостающем коде, чтобы получить все, чтобы скомпилировать.