У меня есть файл, который я пытаюсь проанализировать, и вот как я это делаю:
var definitions = new Dictionary<int, string>();
foreach (var line in new RirStatFile("delegated-lacnic-latest.txt"))
{
for (var i = 0; i < line.Range; i ++)
{
definitions[line.StartIpAddress + i] = line.Iso3166CountryCode;
};
};
new RirStatFile(...)
возвращает IEnumerable<RirStatFileLine>()
с .Count
из 4 100 RirStatFileLine
объектов, где каждый RirStatFileLine
имеет .Range
, значение которого обычно составляет от 32768 до 1 миллиона.
Выполнение этого, как показано в фрагменте выше, занимает около 45 секунд на моем жалком нетбуке.
РЕДАКТИРОВАТЬ: двухъядерный нетбук.
Отличное место для использования новой библиотеки параллельных задач, верно? Я так и думал, поэтому я изменил код на:
var definitions = new ConcurrentDictionary<int, string>();
Parallel.ForEach(new RirStatFile("delegated-lacnic-latest.txt"), line =>
{
Parallel.For(0, line.Range, i =>
{
definitions[line.StartIpAddress + i] = line.Iso3166CountryCode;
});
});
И угадайте что? Программа занимает 200 секунд!
Что дает? Очевидно, я не понимаю, что здесь происходит. Просто для справки, вот RirStatFileLine
:
public class RirStatFileLine
{
public readonly string Iso3166CountryCode;
public readonly int StartIpAddress;
public readonly int Range;
public RirStatFileLine(string line)
{
var segments = line.Split('|');
// Line:
// lacnic|BR|ipv4|143.54.0.0|65536|19900828|assigned
// Translation:
// rir_name|ISO_countryCode|ipVersion|ipAddress|range|dateStamp|blah
this.Iso3166CountryCode = segments[1];
this.StartIpAddress =
BitConverter.ToInt32(IPAddress.Parse(segments[3]).GetAddressBytes(), 0);
this.Range = int.Parse(segments[4]);
}
}
И RirStatFile
:
public class RirStatFile : IEnumerable<RirStatFileLine>
{
private const int headerLineLength = 4;
private readonly IEnumerable<RirStatFileLine> lines;
public RirStatFile(string filepath)
{
this.lines = File.ReadAllLines(filepath)
.Skip(RirStatFile.headerLineLength)
.Select(line => new RirStatFileLine(line));
}
public IEnumerator<RirStatFileLine> GetEnumerator()
{
return this.lines.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.lines.GetEnumerator();
}
}