多线程是应用程序性能改进的答案

时间:2013-01-23 08:27:46

标签: c# multithreading

我有一个控制台应用程序,它执行以下操作:

  1. 读取输入文件。输入文件具有运行到数千行的行方式数据
  2. 预处理输入文件并转换为中间文件。中间文件的行数相同。
  3. 一次从中间文件中读取一行,形成一个Web请求并将其发送到网络服务器。
  4. 一次从Web服务器读取每个请求的响应,处理(解析)它并将其写入输出文件。输出也具有与输入文件相同的行数。
  5. 现在,应用程序工作正常,但速度非常慢。我想提高应用程序的性能,以使其更快。

    1. 有人可以告诉我在这种情况下可以使用的各种方法吗?

    2. 如果多线程是问题的答案,那么有人会提出一些启动指针吗?

    3. 编辑: 所有请求都将转到同一台服务器。就服务器而言,我对它的容忍度知之甚少或根本不知道(如果归结为此,我可能会将请求线程的数量限制在服务器上。)

3 个答案:

答案 0 :(得分:2)

要线程还是不线程?这就是问题......

对问题的多线程部分的一个简单而正确的答案是:是的,1)根据算法是可行的2)它或者涉及I / O绑定的操作,或者你在CPU中有几个核心-bound ops

第一点:可行性

  1. 要执行第2步,您必须完成第1步。暂无多线程
  2. 步骤3需要完成步骤2,涉及独立的行间活动(每行一个请求)。宾果!!
  3. 步骤4要求在步骤3完成所有请求。多线程终止于那里。
  4. 第二点:操作类型

    Web请求是I / O绑定的操作。你获得了最大的利益。由于您是否对同一服务器执行请求(容错或不容错),因此必须限制查询速率。需要对并发请求数进行适当的调整,但如果在代码中使用常量(如const int NUMBER_OF_THREADS = 4;),则有一个很好的起点。

    提案

    使用信号量来处理并发请求。

    通过读取文件并转换为中间文件来启动程序,就像之前一样。

    完成后,创建一个固定大小的数组(你说最终文件有相同的行数,所以你可以分配它),然后为每一行启动一个循环:

    1. 获取一个初始化为NUMBER_OF_THREADS常量的信号量,这将允许主线程激活4个并发线程
    2. 通过传递行,目标数组和索引来启动一个线程(实际上你不需要将所有这些作为参数传递,即如果列表是类成员)
    3. 在循环之后,等待我将要简要讨论的AutoResetEvent

      在主题中,执行以下操作:

      1. 执行网络请求
      2. 处理结果
      3. 将结果保存到相应的目标数组行
      4. 使用Interlocked.Increment()方法
      5. 增加跨线程共享的变量(此处未讨论)
      6. if共享变量equals行数then释放我提到的AutoResetEvent所以你将解锁主线程
      7. 调整

        从4个并发线程开始。尝试将它们增加到8并查看性能。我建议你不要超过12个主题,但是其他人可能会说这可能太多了......这只是尝试失败。

答案 1 :(得分:0)

在阅读文件时,您还在编写文件。首先想到的是以大块(BufferedReader)读取文件,以确保磁盘不会占用太多。

至于您的服务器,根据我的经验,大多数Web服务器都非常容忍每秒多个请求。如果您自己托管服务器,我会简单地使用异步Web请求并弄清楚会发生什么......但是,从它的声音中你创建了一个简单的Web爬虫,在这种情况下我强烈建议耐心:导致问题别人的服务器永远不是一个好主意。为了给您一个指示:我们的网络抓取工具总是每台服务器每秒限制为1个请求。

答案 2 :(得分:0)

我会根据内部消息队列和生产者 - 消费者链创建一个应用程序。

* -> * -> * -> *

其中每个*都是一个线程:读取,处理,查询WS,后处理。 *节点在生成队列已满或消耗队列为空时休眠。

如果需要,你可以在每个点(最有可能在WS处理程序中)创建几个消费者,如下所示:

         / * \ 
* -> * ->  *  -> *
         \ * /

架构准备就绪后,您可以通过更改每个点的队列大小来调整应用程序。

此外 - 您可以使用线程池来处理每个处理节点,因此请确保使用最多的处理器。