2011-10-20 81 views
1

我正在分析运行不同数量的允许线程的多线程程序。以下是三次相同输入作业的性能结果。多线程资源争用

1 thread: 
    Total thread time: 60 minutes. 
    Total wall clock time: 60 minutes. 

10 threads: 
    Total thread time: 80 minutes. (Worked 33% longer) 
    Total wall clock time: 18 minutes. 3.3 times speed up 

20 threads 
    Total thread time: 120 minutes. (Worked 100% longer) 
    Total wall clock time: 12 minutes. 5 times speed up 

由于需要更多线程时间才能完成相同的工作,我觉得线程必须争夺资源。

我已经检查了应用程序机器和数据库服务器上的四个支柱(cpu,内存,diskIO,网络)。内存是原始的争用资源,但现在已经修复(所有时间都超过1G免费)。 20螺纹测试中CPU的徘徊在30%到70%之间,所以在那里有很多。 diskIO在应用程序机器上几乎没有,在数据库服务器上最少。网络真的很棒。

我也使用redgate进行代码配置,并且看到没有方法等待锁定。它有助于线程不共享实例。现在我正在检查更多细微的项目,例如数据库连接建立/池(如果20个线程试图连接到同一个数据库,他们是否必须相互等待?)。

我试图找出并解决资源争夺,从而使20线程运行是这样的:

20 threads 
    Total thread time: 60 minutes. (Worked 0% longer) 
    Total wall clock time: 6 minutes. 10 times speed up 

什么是最可能的来源(比大4除外),我应该在看着争夺?


每个线程执行的代码大约是:

Run ~50 compiled LinqToSql queries 
Run ILOG Rules 
Call WCF Service which runs ~50 compiled LinqToSql queries, returns some data 
Run more ILOG Rules 
Call another WCF service which uses devexpress to render a pdf, returns as binary data 
Store pdf to network 
Use LinqToSql to update/insert. DTC is involved: multiple databases, one server. 

的WCF服务在同一台机器上运行,并且是无状态的,能够同时处理多个请求。


机器有8个cpu。

+0

建议您发布您试图并行的代码/算法 –

+0

您的计算机有多少个CPU? –

+0

你的操作大多是IO绑定的,这些IO调用是异步的吗?如果不尝试使他们asyn,然后看看你是否得到任何好处 – Ankur

回答

3

你所描述的是,你想要一个100%的可伸缩性,它是线程s增加和wallcklock时间减少之间的1:1关系......这是一个目标,但难以达到。

例如,你写道没有内存争用,因为有1 GB免费...这是恕我直言一个错误的假设...内存争用也意味着如果两个线程试图分配内存,它可能发生那一个必须等待另一个...要牢记的是GC发生的中断会暂时冻结所有线程... GC可以通过配置(gcServer)进行定制 - 请参阅http://blogs.msdn.com/b/clyon/archive/2004/09/08/226981.aspx

另一点是WCF服务称为...如果它不能扩展 - 例如PDF渲染 - 那么这也是一种竞争形式,例如...

可能争用的列表是“无尽的” ......,几乎总是在你提到的明显区...

编辑 - 按评论:

几点检查:

  • 连接池
    提供什么你用?它是如何配置的?
  • PDF渲染
    可能会争你的地方使用这个库里面来衡量...
  • LINQ2SQL
    检查所有这些查询执行计划......可能有些采取任何类型的锁,因此可能创建一个争DB服务器端...

编辑2:

线程
从线程池这些线程?如果是这样,那么你将无法扩展:-(

编辑3:

线程池线程是坏的长时间运行的任务是在您的方案的情况下...详情见

http://www.yoda.arachsys.com/csharp/threads/printable.shtml

长时间运行的操作应该使用新创建的线程;短时间运行的操作可以利用线程池。

如果你想要极致的性能,则可能是值得一试CQRS并描述为LMAX真实世界的例子。

+0

只有50%加速(20个线程,10倍加速)。我很幸运,PDF渲染很快就会从这个过程中被删除。尽管如此,如果线程正在等待这个pdf渲染,那么应该有一些可衡量的资源,我可以查看它来确定它,对吧?我一定会找到一些方法来测量红帽的GC。我不是要求无尽的名单,只是“下一个要检查的项目”列表。 –

+0

要测量关于PDF渲染的资源,您必须检出用于渲染的库内部的东西......另一点是如何处理您的数据库连接/连接池 - 您使用的是哪种提供程序/配置?同样检查所有使用的Linq2SQL的执行计划(可以使用一些DB服务器端工具来完成) – Yahia

+0

我只需要在库中查看它是否锁定,正确?如果这是一个记忆猪,我不必在图书馆看 - 我会看看机器上的一个指标。我使用默认的连接池 - 无论LinqToSql的DataContext如何管理连接都会发生。我生活并呼吸执行计划 - 已经完成。 –

2

不是测量总线程时间,而是测量执行某种操作(数据库,磁盘,网络等)的I/O操作的每个操作的时间。

我怀疑你会发现这些操作是当你有更多的线程需要更长的时间,这是因为争用是在该I/O的另一端。例如,您的数据库可能会序列化数据一致性请求。

+0

+1用于数据库锁争用。我希望我知道衡量它的好方法。 –

+1

您可以运行您的单线程测试并测量所有单个数据库操作。然后将它们加在一起,让我们说在60分钟内总共有5分钟用于数据库访问。现在你知道,无论你如何有效地完成你的流程,你总会有5分钟的时间。因此,您应该将此视为M + N类型的事情,其中​​M表示处理时间,N表示访问您不能控制的共享资源的时间。你可以通过多线程来提高M,但是对于N你没有办法做到,这总是固定的。 – Miguel

2

是的,有资源争夺。例如,所有的线程都必须将数据读/写到同一个存储器总线,并指向相同的RAM模块。不管多少RAM都是免费的,重要的是读取/写入由相同RAM模块上的相同存储器控制器执行,并且数据通过相同总线传输。

如果有任何一种同步随时随地的,那么这也是一个争资源。如果有任何 I/O,那是一个争用资源。

从1线程到N线程时,您永远不会看到N x加速。这是不可能的,因为最终,中的所有内容都是共享资源,其中会存在某种程度的争用。

有很多因素阻止您获得完整的线性加速。你假设数据库,数据库运行的服务器,将它连接到客户端的网络,客户端计算机,操作系统和驱动程序两端,内存子系统,磁盘I/O和之间的所有内容当你从1到20个线程时,能够快20倍。

两个字:梦想。

这些瓶颈中的每一个只会让你减慢几个百分点,那么总体结果就会像你所看到的那样。

我相信你可以调整它以扩大一点,但不要期待奇迹。

但是您可能要查找的一件事是缓存行共享。线程是否访问非常接近其他线程使用的数据的数据?您多久可以避免发生这种情况?

+0

我目前在N/4加速,寻找N/2加速。线程向请求对象提交一批标识符 - 从那里他们使用这些标识符加载他们自己的数据来处理。 –

+0

关于数据库IO,数据库CPU,数据库内存,网络容量,网络ping,客户端CPU,客户端内存,客户端磁盘IO速度快20倍的问题:已经检查过这些东西 - 它们没有处理能力。我不指望他们的速度提高20倍,我希望通过不断地使用所有这些,而不是轮流使用更多。他们只是坐在那里低于容量。还有其他的东西在容量中,这就是我正在寻找的东西。 –

+0

@DavidB:即便如此,您仍然认为接近最大容量的成本为零。如果在添加流量时网络延迟增加(一点点)会怎样?它可能远远没有达到最大容量,但如果增加更多流量,您将获得小的perf perf。相同的数据库和其他一切。这不是一个二进制的“容量/没有容量”的东西。 – jalf