如何使用此代码使我的i7处理器达到100%的使用率(解析xml的最快方法)

时间:2012-05-02 20:48:47

标签: c# .net multithreading xml-parsing hyperthreading

如何使用此代码使我的i7处理器达到100%的使用率? XmlDocument中是否存在特殊情况?只是因为背景的变化?如果是这样,为什么增加线程不会让处理器充分利用它?什么是一次解析几个字符串的最佳方法?

修改

也许这段代码会更清晰,无论使用30%处理器的线程数是多少:

    private void Form1_Load(object sender, EventArgs e)
    {
        Action action = () =>
        {
            while (true)
            {
                XmlDocument xmlDocument = new XmlDocument();

                xmlDocument.LoadXml("<html><body><div>1111</div><div>222</div></body></html>");
                var nodes = xmlDocument.SelectNodes("//div");
            }
        };

        Parallel.For(0, 16, i => action());
    }

4 个答案:

答案 0 :(得分:3)

这是您正在运行的实际代码,还是从文件或其他URL加载xml?如果这是实际代码,那么它可能完成得太快并且CLR没有时间来优化线程计数,但是当你放置无限循环时它保证你将最大化CPU。

如果从实际源加载XML,则线程可以等待IO响应,并且在发生这种情况时不会占用任何CPU。为了加快这种情况,您可以使用大量线程(如20+)将所有XML预加载到内存中,然后使用8个线程进行XML解析。

答案 1 :(得分:3)

在您的代码示例中(您会看到使用分析器),您浪费了很多时间等待可用资源来运行这些线程。因为您不断要求越来越多Parallel.For(这是一个非阻塞调用) - 您的进程花费大量时间等待线程完成,然后选择下一个线程(越来越多的此类线程)所有请求运行的时间)。

考虑分析器的这个输出:

RED颜色是同步的!看一下内核要做多少工作让我的应用程序运行这么多线程!请注意,如果你有一个核心处理器,你肯定会看到100%

enter image description here

通过拆分字符串并单独解析它们(当然是从I / O加载后),你将有最好的时间读取这个xml。您可能看不到100%的CPU使用率,但这将是最佳选择。使用不同分区大小的字符串(即子字符串大小)进行播放。

关于并行模式的精彩阅读,我推荐Stephen Toub的这篇论文:http://download.microsoft.com/download/3/4/D/34D13993-2132-4E04-AE48-53D3150057BD/Patterns_of_Parallel_Programming_CSharp.pdf

编辑我做了一些搜索在多个线程中读取xml的智能方法。我最好的建议是:

  1. 如果可以,将xml文件拆分为较小的文件。
  2. 每个xml文件使用一个线程。
  3. 如果1&amp; 2不足以满足你的需求,可以考虑不要将它完全加载为xml,而是将字符串分区(拆分),然后手动解析(而不是XmlDocument)。如果1和2足以满足您的需求,我只会这样做。每个分区(子串)都可以在自己的线程上运行。还记得“更多threds”!=“更多cpu使用”,至少不适合你的应用。正如我们在分析器示例中看到的那样,太多线程会花费大量开销。保持简单。

答案 2 :(得分:0)

处理器是现代PC上最快的组件。瓶颈通常以RAM或硬盘的形式出现。在第一种情况下,您不断创建一个可能占用大量内存的变量。因此,直观的RAM会成为瓶颈,因为缓存很快就会枯竭。

在第二种情况下,你没有创建任何变量(我确信.NET在后台做得很多,虽然是以高度优化的方式)。因此,它直观地表明所有工作都停留在CPU上。

操作系统如何处理内存,中断等是不可能完全定义的。您可以使用有助于定义这些情况的工具,但上次我检查时甚至没有.NET代码的内存分析器。所以这就是为什么我说的给出答案的原因。

答案 3 :(得分:0)

任务并行库分发操作,因此在进程利用率方面会失去一些控制权。在大多数情况下这是件好事,因为我们不必担心创建太多线程,使我们的线程太大等等。如果你想显式创建线程,那么下面的代码应该推动你的处理器到最大:

Parallel.For(0, 16, index => new Thread(() =>
                {
                    while (true)
                        new Thread(() =>
                            {
                                XmlDocument xmlDocument = new XmlDocument();
                                xmlDocument.LoadXml("<html><body><div>1111</div><div>222</div></body></html>");
                                var nodes = xmlDocument.SelectNodes("//div");
                            }).Start();
                }).Start());

我并不是说我推荐这种方法,只是展示了将处理器推向最大的代码(AMD FX-6200)的工作示例。我也看到大约30%使用任务并行库。