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

我应该寻找哪些最有可能的来源(除了四大)来找到这种争用?


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

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。

4

3 回答 3

3

您所描述的是,您想要 100% 的可扩展性,即线程 s 的增加和 wallcklock 时间的减少之间的 1:1 关系......这通常是一个目标,但很难达到......

例如,您写道没有内存争用,因为有 1 GB 空闲空间......恕我直言,这是一个错误的假设......内存争用也意味着如果两个线程尝试分配内存,可能会发生一个必须等​​待其他...要记住的另一个要点是 GC 发生的中断,它会暂时冻结所有线程...可以通过配置(gcServer)对 GC 进行一些自定义 - 请参阅http://blogs.msdn.com/b/克莱昂/存档/2004/09/08/226981.aspx

另一点是称为的 WCF 服务......如果它不能按比例放大 - 例如 PDF 呈现 - 那么这也是一种争用形式,例如......

可能的争论列表是“无穷无尽的”......而且几乎总是在你提到的明显领域......

编辑 - 根据评论:

需要检查的几点:

  • 连接池
    你使用什么供应商?它是如何配置的?
  • PDF 呈现
    可能的争用将在您使用的库内的某处进行测量...
  • Linq2SQL
    检查所有这些查询的执行计划......可能有些人使用任何类型的锁,因此可能会创建争用 DB-server-side......

编辑2:

线程
这些线程来自 ThreadPool 吗?如果是这样,那么您将无法扩展:-(

编辑 3:

ThreadPool 线程不适合长时间运行的任务,在您的场景中就是这种情况......有关详细信息,请参阅

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

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

如果您想要极致性能,那么值得查看CQRS和描述为LMAX的真实示例。

于 2011-10-20T05:23:53.537 回答
2

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

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

于 2011-10-20T07:14:40.280 回答
2

是的,存在资源争用。例如,所有线程都必须将数据读/写到相同的内存总线,定向到相同的 RAM 模块。有多少可用 RAM 并不重要,重要的是读/写是由相同 RAM 模块上的相同内存控制器执行的,并且数据通过相同的总线传输。

如果任何地方都有任何类型的同步,那么这也是一个竞争资源。如果有任何I/O,那就是争用资源。

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

有很多因素会阻止您获得完整的线性加速。您假设数据库、运行数据库的服务器、将其连接到客户端的网络、客户端计算机、两端的操作系统和驱动程序、内存子系统、磁盘 I/O 以及介于两者之间的一切都可以当你从 1 到 20 个线程时,速度只会快 20 倍。

两个字:做梦。

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

我相信你可以调整它以更好地扩展,但不要指望奇迹。

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

于 2011-10-20T07:30:19.200 回答