如何在不使用阻塞队列的情况下将消息传递到另一个线程?
我有一个非常简单的服务器(使用 kryonet)。客户端仅存储汽车的当前状态(x、y、角度等)并发送加速和转弯请求。
服务器正在接收请求并将它们添加到物理线程耗尽、读取和更新的 ArrayBlockingQueue 中。
当添加另一个玩家时,游戏速度几乎减慢一倍。我已经排除了很多事情(我将所有更新和包发送限制在 60Hz。)
我怀疑使用阻塞队列会阻塞太多,从而导致速度减慢。
如何在不出现阻塞问题的情况下将客户端请求发送到物理线程?
I have a pretty straight forward server (using kryonet). The clients are only storing the current state of the car (x,y,angle etc) and are sending requests of acceleration and turning.
The server is receiving the requests and adding them to a ArrayBlockingQueue that the physics thread drains and reads and updates.
When adding another player, the speed of the game slows down by almost double. I have ruled out a lot of things (I have all updates and package sending throttled at 60Hz.)
I am suspecting that using a blocking queue is blocking so much that it is causing the slowdown.
How can I send the client requests to the physics thread without blocking issues?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
你怀疑错了。以下测试程序通过 ArrayBlockingQueue 推送 100 万个整数:
在我的笔记本电脑上,它会在几秒钟内终止。因此,无论您的性能瓶颈在哪里,它都不是 ArrayBlockingQueue,它可以处理比您需要的吞吐量至少高 3 个数量级的吞吐量。换句话说,即使您找到了一种根本不需要执行时间的线程通信方法,最多也只能将您的程序加速 0.1%。
对于这个问题和所有其他性能问题,请吸取教训:解决现有代码中的任何性能问题时,第一步是测量代码的哪一部分速度慢,通常情况下,它不是人们所期望的。探查器极大地简化了这项任务。
You suspect wrong. The following test program pushes 1 million Integers through an ArrayBlockingQueue:
On my laptop, it terminates in a couple seconds. So wherever your performance bottleneck is, it is not the ArrayBlockingQueue, which could handle a throughput at least 3 orders of magnitude higher than you need. Put differently, even if you found a thread communication approach that takes no execution time at all, that would only speed up your program by at most 0.1%.
Take home lesson for this and all other performance problems: The first step when tackling any performance problem in existing code is to measure which part of the code is slow, as usually, it is not where one expects. Profilers simplify this task greatly.
您可以使用中断器(环形缓冲区),这是一种用于实现队列的无锁机制。请参阅:
You can use a disruptor (ring buffer), a lock-free mechanism for implementing a queue. See:
我已经找到了这个错误。我需要以不同的方式限制物理模拟(不是使用 world.step() 函数,而是限制调用的频率)。是这样的。
然后我需要调整所有物理数字,使它们在这种配置下感觉自然。
I have found the bug. I needed to throttle the physics simulation in a different way (not with the world.step() function, but limit how often that is called). It is something like this.
Then I need to adjust all the physics numbers so they feel natural with this configuration.
你的问题以实现为前提 - 你最好问“为什么我的代码这么慢?”。
阻塞队列是实现生产者/消费者模式最有效的方式。
我会添加更多的消费者线程 - 尝试添加与处理器核心一样多的消费者线程 - 即
Runtime.getRuntime().availableProcessors()
。Your question presupposes an implementation - you would be better to ask "why is my code so slow?".
The blocking queue is the most efficient way of implementing the producer/consumer pattern.
I would add more consumer threads - try adding as many consumer threads as there are processor cores - ie
Runtime.getRuntime().availableProcessors()
.确保您创建的队列具有足够的可用槽位以满足所有客户端的需求。如果队列因客户端过多而变满,则它们在尝试插入命令时会阻塞。如果这不是问题,则意味着您的物理(消费者)线程无法跟上请求,您需要确保它获得更多的处理时间。
Make sure you are creating the queue with enough slots available to satisfy all the clients. If the queue becomes full because there are too many clients, they will block when trying to insert commands. If that's not the problem it means your physics (consumer) thread is not keeping up with the requests and you need to make sure it gets more processing time.