Я пытаюсь узнать немного больше о LINQ, внедрив корректор орфографии Питера Норвига в C #.
Первая часть включает в себя большой файл слов (около 1 миллиона) и размещение его в словаре, где key
- это слово, а value
- это число вхождений.
Обычно я делаю это так:
foreach (var word in allWords)
{
if (wordCount.ContainsKey(word))
wordCount[word]++;
else
wordCount.Add(word, 1);
}
Где allWords
является IEnumerable<string>
В LINQ я сейчас делаю это так:
var wordCountLINQ = (from word in allWordsLINQ
group word by word
into groups
select groups).ToDictionary(g => g.Key, g => g.Count());
Я сравниваю 2 словаря, глядя на все <key, value>
, и они идентичны, поэтому они дают одинаковые результаты.
Цикл foreach
занимает 3,82 с , а запрос LINQ занимает 4,49 с
Я синхронизирую его, используя класс Секундомер, и я работаю в режиме РЕЛИЗ. Я не думаю, что производительность плохая, мне просто интересно, была ли причина для разницы.
Я выполняю запрос LINQ неэффективным способом или я что-то упускаю?
Обновление: вот полный пример кода теста:
public static void TestCode()
{
//File can be downloaded from http://norvig.com/big.txt and consists of about a million words.
const string fileName = @"path_to_file";
var allWords = from Match m in Regex.Matches(File.ReadAllText(fileName).ToLower(), "[a-z]+", RegexOptions.Compiled)
select m.Value;
var wordCount = new Dictionary<string, int>();
var timer = new Stopwatch();
timer.Start();
foreach (var word in allWords)
{
if (wordCount.ContainsKey(word))
wordCount[word]++;
else
wordCount.Add(word, 1);
}
timer.Stop();
Console.WriteLine("foreach loop took {0:0.00} ms ({1:0.00} secs)\n",
timer.ElapsedMilliseconds, timer.ElapsedMilliseconds / 1000.0);
//Make LINQ use a different Enumerable (with the exactly the same values),
//if you don't it suddenly becomes way faster, which I assmume is a caching thing??
var allWordsLINQ = from Match m in Regex.Matches(File.ReadAllText(fileName).ToLower(), "[a-z]+", RegexOptions.Compiled)
select m.Value;
timer.Reset();
timer.Start();
var wordCountLINQ = (from word in allWordsLINQ
group word by word
into groups
select groups).ToDictionary(g => g.Key, g => g.Count());
timer.Stop();
Console.WriteLine("LINQ took {0:0.00} ms ({1:0.00} secs)\n",
timer.ElapsedMilliseconds, timer.ElapsedMilliseconds / 1000.0);
}