缓慢线程处理的缓解技术

时间:2017-09-01 05:17:39

标签: java multithreading

鉴于同步程序(Minecraft)需要在世界生成时处理x照明更新。一种提高性能的技术是修补Minecraft而不是对照明更新进行排队,然后异步处理它们,从队列中删除任何重复的计划照明更新。

这是为了提供一些重复删除,以及在接下来的几个滴答周期中分散世界一代的负载。

这个队列目前是无限制的,在重复位置检查之前,当队列变得荒谬时,会出现性能不佳或内存泄漏的原因。

如果队列增长得​​快,那么你可以做些什么来解决内存泄漏?是否存在强制线程获取更多时间或阻塞直到队列长度不足的技术?我们无法提供背压,因为这会导致丢失的照明更新,而这些更新不一定会被重新安排。在承诺处理之前可能还有最大排队时间可能是理想的。

我会提供代码,/用更抽象的术语提问,但我不确定具体细节。

2 个答案:

答案 0 :(得分:2)

除了将sleep语句放入其中之外,您不能减慢线程速度。您可以使用线程优先级,但这只会更改线程的计划顺序。这可能会降低线程的速度,但前提是有更高优先级的线程占用所有运行时间。

您需要的是某种工作量调节器,而不是工作率调节器。也就是说,尝试只执行底层机器可以执行的工作。你可能想看看ZeroMQ:这将是一个很大的架构变化(一开始是异步的!),但请坚持一下。

ZeroMQ编程是Actor模型;线程通过套接字进行通信,套接字的作用类似于消息队列。美丽的是,这些插座的方式多于简单的点对点链接;那里也有模式。例如,您可能有8个线程正在进行照明。您可以通过单个PUSH / PULL套接字向这些请求发送照明请求;可用的那个将获取该消息并进行处理。您还可以配置该套接字,以便在达到高水位标记时(照明线程不会跟上)新的照明请求消息将取代队列中的旧标记(照明线程只处理它们可以实际应对的数量) ,偏向于最新的)。

套接字也可以通过网络连接。您可以在几台计算机上分发它,几乎不需要更改任何代码。

我的这个建议存在一些问题:你要对对象进行序列化和反序列化非常多。你正在撕毁现有的架构。但是,您将利用一个通信框架来分发,扩展,并且已经以有用的方式进行负载平衡和队列管理。尝试会很有趣!

编辑以回应评论

我能想到的一件事是向照明请求添加提交时间字段,并让照明线程计算每个请求的初始提交和完成处理之间的时间。此执行时间测量可用于更新所有照明线程的平均完成时间值(将其置于由互斥锁保护的某些共享内存中,或类似的内容)。

提交照明请求的内容可以参考此平均值,如果它增加,它应该放宽速率。同样,如果平均处理时间正在减少,它可以提高速率。如果计算机本身开始忙于在后台执行其他操作,那么这将适应执行时间的短缺。

实际上,这是将照明处理分析到应用程序中,将其反馈给提交者,并在执行期间学习每秒可以提交多少照明请求而不会落后太多。

这会产生副作用,即确保队列本身不会太满并无限增长。它没有将队列限制到任何特定长度,但它限制了队列前后之间的时间。因此,在速度更快的机器上,队列平均会更长,而在较慢的机器上会更短。

CPU中的热管理

当然,a" fast"的定义和"慢"这些天电脑有点复杂。现代的Intel / AMD CPU(以及许多ARM)如果确定需要大量的运行时间,它将提高其时钟速率。因此,当CPU需要Turbo模式时,可以持续的照明请求率将会增加,提高时钟频率,运行速度更快。因此,通过适应在满足时间目标时可以维持的速率(即保持平均完成时间合理),您的代码将利用CPU的增加速度,因为它习惯了您要求的工作量它要做。

你需要小心一点;改变时钟速度不是瞬间的 - 我已经看到300毫秒的延迟,在整个机器的任何地方都没有发生任何事情 - 当它们发生时,看起来所有东西突然变得长300毫秒。这就是"平均值"完成时间是必需的 - 它可以平滑测量中的pertebation。

获得平均权限的长度也很重要,否则你将进入一个条件,你的代码对CPU的要求和CPU的时钟速率将会振荡:

  • 您的代码增加了工作量,
  • CPU通过提高时钟频率来响应,这需要300ms才能完成,
  • 您的代码检测到延迟意外跳跃并减少工作量,
  • CPU注意到需求下降并降低时钟频率,
  • 您的代码过度补偿,并进一步削减工作量
  • 延迟再次降低,
  • 重新开始...

即使平均完成时间达到稳定,您也希望增加工作量。如果这样做可以推动CPU提高其时钟频率,并且可以在不影响完成时间的情况下完成更多的照明请求。

基本上,您希望增加工作负载,并且只有在延迟实际增加时才减少工作负载,但这样做的时间比CPU自身的热管理/时钟管理周期慢。

答案 1 :(得分:1)

  

如果队列增长得​​快,那么你可以做些什么来解决内存泄漏?

在这种情况下,增加内存占用可能是你最小的问题。

  

是否存在强制线程获取更多时间或阻塞直到队列长度不足的技术?

可以优先考虑Java线程,但如果导致可观察到的影响,则它在很大程度上取决于底层操作系统。

除了上述内容之外,很难提供帮助 - 你知道,因为这在很大程度上取决于架构/实现的细节。我会研究诸如以下的问题:

  • 有足够的线程吗?
  • 是否足以满足预期流量的底层硬件?

您知道 - 您似乎无法影响流入系统的事件数量。因此,您只需为该流程设计工作的解决方案。这是一个特定的问题,需要您坐下来配置您的线程,例如:了解他们在哪里以及如何花费时间。结论可能是例如进行这些计算的机器没有足够的马力。但是必须做的事情。