首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程、Coro、任何事件混淆

线程、Coro、任何事件混淆
EN

Stack Overflow用户
提问于 2012-07-31 02:45:08
回答 2查看 1.3K关注 0票数 4

我对perl比较陌生,甚至对perl中的线程也比较陌生。我有一个perl脚本,可以从3个不同的来源获取输入。(2个LDAP查询和一个并不总是存在的文件),因为某些部分可能比其他部分耗时更长,所以我决定使用线程和队列。在开发期间,测试脚本的各个组件工作得很好,但在将它们放在一起之后,性能似乎会下降。

基本结构是这两个线程:(读取文件或读取AD条目) -> Queue1 -> 2线程:(擦除数据) -> Queue2 -> 3-4个线程(与现有本地LDAP条目进行比较)。几个线程将统计数据报告回主脚本,一旦所有线程完成,就会发送一封电子邮件,其中包含该运行的所有统计数据和状态。

我正在使用dequeue_nb,我认为这会有帮助,但没有运气。

性能影响似乎出现在队列中。在寻找提高性能的技巧时,我遇到了几篇文章,说perl线程不好,并使用coro、POE、Anyevent、IO:async等。

这看起来不像是一个“事件”问题,所以我不认为AnyEvent或POE会是我所看到的那样,coros似乎一次只使用一个CPU,所以我也不确定这是否会起作用。我想使用它们的组合,但后来我的头开始痛。有没有人对如何修复/解决我的脚本或如何实现其他模块有任何建议?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-31 04:17:32

并行性的一个问题是同步。它是一个性能杀手,它是不好的,如果可能的话,它应该被避免。

运维架构

让我们来看看你的架构:

代码语言:javascript
复制
+--------------+--------------+
|   Input 1    |   Input 2    |
+--------------+--------------+
|           QUEUE A           |
+--------------+--------------+
|   Scrub 1    |   Scrub 2    |
+--------------+--------------+
|           QUEUE B           |
+---------+---------+---------+
| Compare | Compare | Compare |
+---------+---------+---------+

讨论

队列A必须跨四个线程进行同步;队列B跨5-6个线程。任何时候只有一个线程可以访问队列,所以大多数时候你的线程都是在等待,而不是在工作!

并行流水线架构

稍有不同的体系结构可能如下所示:

代码语言:javascript
复制
+-----------+    +-----------+
|  Input 1  |    |  Input 2  |
+-----------+    +-----------+
| QUEUE  1A |    | QUEUE  2A |
+-----------+    +-----------+
|  Scrub 1  |    |  Scrub 2  |
+-----------+    +-----------+
| QUEUE  1B |    | QUEUE  2B |
+-----+-----+    +-----+-----+
| Cmp | Cmp |    | Cmp | Cmp |
+-----+-----+    +-----+-----+

讨论

在这里,A队列只有两个线程(->less等待),B队列只有三个线程。对于相似的输入大小/复杂性,这种架构应该执行得更快。如果输入2相当短,整个流水线2甚至在流水线1完成一半之前就已经运行了。然而,这比对每个管道使用单个进程要好得多。

草坪喷水建筑

概念

更好的架构将尝试将进程的输出分布到多个队列中。(相反,当队列为空时,让线程从多个队列获取输入是不好的。)

每次队列写入都应该转到不同的队列:

代码语言:javascript
复制
  +-----------+   +-----------+
  |  Input 1  |   |  Input 2  |
  +-----------+   +-----------+
        |      \ /      |
  +-----------+   +-----------+
  | QUEUE  1A |   | QUEUE  2A |
  +-----------+   +-----------+
  |  Scrub 1  |   |  Scrub 2  |
  +-----------+   +-----------+
        / | \ \   / / | \      

+-------+-------+-------+-------+
| Q. 1B | Q. 2B | Q. 3B | Q. 4B |
+-------+-------+-------+-------+
|  Cmp  |  Cmp  |  Cmp  |  Cmp  |
+-------+-------+-------+-------+

这可确保每个线程具有相同的工作负载,但不能确保所有线程同时完成。

讨论

所有队列在3个线程之间共享。问题是两个线程在写入队列时会互相阻塞。如果队列写访问之间的时间明显长于写持续时间,这应该是没有问题的,否则第二种体系结构可以混合使用。

因此,这种架构是否有意义取决于您的确切需求。

对于均匀大小的输入,它的速度较慢,但对于不规则的输入,它的性能更好。

附录

在实现时:

所使用的框架是架构的次要部分。如果只传递文本字符串,我强烈建议使用管道。如果您必须传递Perl数据类型或对象,那么您可能不得不接受使用真实队列的额外开销:在向队列添加非共享变量时,除了所有同步开销之外,还必须进行深度复制(请参阅@Leon Timmermans )。

关于可伸缩性:

架构1和架构3的线程数量不是固定的。我强烈建议使用这种灵活性来对不同的组成进行基准测试。经验法则是,您应该使用n到2n个线程,其中n是处理器(或硬件线程)的数量。这可以看作是一个阶段的线程的最大可感知数量。除此之外,你只会得到内存损失,而不会加速。当阶段处理输入的速度比提供输入的速度更快时,性能饱和点可能会更早达到。

票数 5
EN

Stack Overflow用户

发布于 2012-07-31 05:51:07

您要在队列中放入哪种类型的数据?AFAIK简单数据比复杂结构更便宜,因为它需要克隆和复制至少两次。我一直在计划写一个更快的队列实现(大部分工作实际上已经完成了),但还没有发布。

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

https://stackoverflow.com/questions/11727655

复制
相关文章

相似问题

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