首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ConcurrentDictionary:超慢?

ConcurrentDictionary:超慢?
EN

Stack Overflow用户
提问于 2010-10-13 05:12:01
回答 2查看 3.4K关注 0票数 0

我想解析一个文件,我就是这样做的:

代码语言:javascript
复制
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(...)返回一个.Count为4,100个RirStatFileLine对象的RirStatFileLine,其中每个RirStatFileLine都有一个.Range,其值通常在32768到100万之间。

如上面的片段所示,在我的这本可怜的上网本上运行大约45秒。

编辑:双核上网本.

使用新的并行任务库的好地方,对吗?我就是这么想的,所以我把代码改为:

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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();
    }
}
EN

回答 2

Stack Overflow用户

发布于 2010-10-13 05:33:53

这里没什么好惊讶的。您正在进行一些非常廉价的操作(向字典中添加一个条目),并将其封装在一些昂贵的并行化代码中。

您应该并行计算昂贵的代码,而不是琐碎的代码。

另外,您使用的是ReadAllLines而不是ReadLines,因此没有任何处理与读取文件重叠的机会。

MSDN“ReadLines和ReadAllLines方法的不同之处如下:当使用ReadLines时,可以在返回整个集合之前开始枚举字符串集合;当使用ReadAllLines时,必须等待返回整个字符串数组才能访问数组。因此,当您处理非常大的文件时,ReadLines可能会更高效。”

票数 4
EN

Stack Overflow用户

发布于 2010-10-13 05:39:27

这里的问题是您的上网本只有一个CPU/核心/硬件线程。瘫痪在这里根本帮不上忙。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3920949

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档