У меня есть текстовый файл со 100 000 пар: слово и частота.
test.in файл со словами:
- 1 строка - общее количество всех пар слов-слов
- 2 строки до ~ 100 001 - пары слово-частота
- 100 002 строка - общее количество введенных пользователем слов
- от 100 003 до конца - вводные слова пользователя
Я разбираю этот файл и помещаю слова в
Dictionary<string,double> dictionary;
И я хочу выполнить некоторую логику поиска + порядка в следующем коде:
for(int i=0;i<15000;i++)
{
tempInputWord = //take data from file(or other sources)
var adviceWords = dictionary
.Where(p => p.Key.StartsWith(searchWord, StringComparison.Ordinal))
.OrderByDescending(ks => ks.Value)
.ThenBy(ks => ks.Key,StringComparer.Ordinal)
.Take(10)
.ToList();
//some output
}
Проблема: Этот код должен выполняться менее чем за 10 секунд.
На моем компьютере (ядро i5 2400, 8 гб RAM) с Parallel.For() - около 91 сек.
Можете ли вы дать мне несколько советов, как повысить производительность?
ОБНОВЛЕНИЕ:
Ура! Мы сделали это! Спасибо @CodesInChaos, @usr, @T_D и всем, кто принимал участие в решении проблемы.
Конечный код:
var kvList = dictionary.OrderBy(ks => ks.Key, StringComparer.Ordinal).ToList();
var strComparer = new MyStringComparer();
var intComparer = new MyIntComparer();
var kvListSize = kvList.Count;
var allUserWords = new List<string>();
for (int i = 0; i < userWordQuantity; i++)
{
var searchWord = Console.ReadLine();
allUserWords.Add(searchWord);
}
var result = allUserWords
.AsParallel()
.AsOrdered()
.Select(searchWord =>
{
int startIndex = kvList.BinarySearch(new KeyValuePair<string, int>(searchWord, 0), strComparer);
if (startIndex < 0)
startIndex = ~startIndex;
var matches = new List<KeyValuePair<string, int>>();
bool isNotEnd = true;
for (int j = startIndex; j < kvListSize ; j++)
{
isNotEnd = kvList[j].Key.StartsWith(searchWord, StringComparison.Ordinal);
if (isNotEnd) matches.Add(kvList[j]);
else break;
}
matches.Sort(intComparer);
var res = matches.Select(s => s.Key).Take(10).ToList();
return res;
});
foreach (var adviceWords in result)
{
foreach (var adviceWord in adviceWords)
{
Console.WriteLine(adviceWord);
}
Console.WriteLine();
}
6 секунд (9 секунд без ручного цикла (с linq)))