java 线程 开销,最小化Java线程上下文切换开销 | 所有编程讨论 | zhouni.net

问题 最小化Java线程上下文切换开销

我有一个在Sun 1.6 32位VM / Solaris 10(x86)/ Nahelem 8核(每个核心2个线程)上运行的Java应用程序。

应用程序中的特定用例是响应某些外部消息。在我的性能测试环境中,当我准备并在接收外部输入的同一线程中发送响应时,我获得了大约50美元的优势,而不是将消息传递给单独的线程来发送响应。我用了一个 ThreadPoolExecutor 用一个 SynchronousQueue 做切换。

在你的经历中是什么 接受 在将一个任务安排到一个线程池之间的预期延迟以及它被选中执行?过去有什么想法可以改善这一点?

7887

2018-05-28 05:57

起源

答案:

“可接受的延迟”完全取决于您的申请。如果您有非常严格的延迟要求,处理同一线程上的所有内容确实会有所帮助。幸运的是,大多数应用程序没有那么严格的要求。

当然,如果只有一个线程能够 接收 请求,然后绑定该线程以计算响应将意味着您不能接受任何其他请求。根据您正在做的事情,您可以使用异步IO(etc)来避免“每个请求的线程”模型,但它会更加困难IMO,并且仍然最终会进行线程上下文切换。

有时候排队请求是合适的,以避免过多的线程处理它们:如果你的处理是CPU限制的,那么拥有数百个线程没有多大意义 - 最好有一个生产者/消费者的任务队列并在每个核心大约一个线程。那基本上是什么 ThreadPoolExecutor 如果你正确地设置它会做的。如果您的请求花费大量时间等待外部服务(包括磁盘,但主要是其他网络服务),那么这也不会有效......此时您需要使用异步执行模型,无论何时您可能会创建一个使用阻塞调用进行核心空闲,或者你采用线程上下文切换命中并拥有大量线程,依靠线程调度程序使其运行良好。

最重要的是延迟要求可能很难 - 根据我的经验,它们比吞吐量要求更加困难,因为它们更难以扩展。它确实取决于上下文。

12

2018-05-28 06:08

谢谢!我的意思是,“预期”而不是“可接受”。我想知道50 us是否太大或是否可以降低。是的,我想尽快释放接收线程,以便能够接收下一条消息。此外,我的请求处理是CPU绑定的。 - Binil Thomas

答案:

“可接受的延迟”完全取决于您的申请。如果您有非常严格的延迟要求,处理同一线程上的所有内容确实会有所帮助。幸运的是,大多数应用程序没有那么严格的要求。

当然,如果只有一个线程能够 接收 请求,然后绑定该线程以计算响应将意味着您不能接受任何其他请求。根据您正在做的事情,您可以使用异步IO(etc)来避免“每个请求的线程”模型,但它会更加困难IMO,并且仍然最终会进行线程上下文切换。

有时候排队请求是合适的,以避免过多的线程处理它们:如果你的处理是CPU限制的,那么拥有数百个线程没有多大意义 - 最好有一个生产者/消费者的任务队列并在每个核心大约一个线程。那基本上是什么 ThreadPoolExecutor 如果你正确地设置它会做的。如果您的请求花费大量时间等待外部服务(包括磁盘,但主要是其他网络服务),那么这也不会有效......此时您需要使用异步执行模型,无论何时您可能会创建一个使用阻塞调用进行核心空闲,或者你采用线程上下文切换命中并拥有大量线程,依靠线程调度程序使其运行良好。

最重要的是延迟要求可能很难 - 根据我的经验,它们比吞吐量要求更加困难,因为它们更难以扩展。它确实取决于上下文。

12

2018-05-28 06:08

谢谢!我的意思是,“预期”而不是“可接受”。我想知道50 us是否太大或是否可以降低。是的,我想尽快释放接收线程,以便能够接收下一条消息。此外,我的请求处理是CPU绑定的。 - Binil Thomas

50us听起来有点高,IME(Solaris 10 / Opteron)LBQ通常在30-35us范围内,而LTQ(LinkedTransferQueue)比那快5us。如其他回复中所述 SynchronousQueue 可能会略微变慢,因为在另一个线程采取之前,报价不会返回。

根据我的结果,Solaris 10在这方面明显慢于Linux,其时间<10us。

在峰值负载下,它真的取决于一些事情

你服务的每秒请求数是多少?

处理请求通常需要多长时间?

如果您知道这些Q的答案,那么在性能方面,它应该是相当清楚的,您是应该处理接收线程还是切换到处理线程。

2

2018-06-10 07:45

有没有理由不使用 LinkedBlockingQueue 所以你的制作人可以排队几个项而不是一个 SynchronousQueue?至少有一个包含1个项目的队列,这样你就可以获得更好的并行性。

“准备”过程的速度与“响应”的速度是多少?您是否可以使用线程池让多个线程处理响应,如果它们太昂贵?

1

2018-06-02 22:12

不是同一个任务,但是“是” - 队列通常用于时间关键任务。我们集中精力避免同步处理事件。查看以下提示

不要使用同步容器(数组,列表,映射......)。想想每个线程的容器。

我们使用了循环线程池。此池由预先分配的线程组成,并且(!)只有一个侦听事件没有任何队列。当事件引发时,线程从循环中删除,另一个成为监听器。处理完成后,线程返回池中。

0

2018-05-28 06:07

我不认为为每个传入的事件创建一个新线程是最好的方法。我宁愿有一个固定的线程池(甚至可能是扩展)来处理由一个或多个侦听器线程放入列表的传入事件 - RecursiveExceptionException

“......每个传入事件的新线程是最好的方式” - 你在我的帖子中看到了这一点,而我写道:“......循环线程”? - Dewfy

哦。我误解了那个。只看到“删除线程”并思考:“是的,那不好”:p - RecursiveExceptionException

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值