这是我关于stackoverflow的第一篇文章...我希望有人可以帮助我
我对Java 6 LinkedBlockingQueue
进行了很大的性能回归。
在第一个线程中,我生成了一些我推入队列的对象
在第二个线程中,我将这些对象拉出来。当频繁调用take()
的{{1}}方法时,会发生性能回归。
我监控整个程序,LinkedBlockingQueue
方法总体上占据了最多的时间。
吞吐量从~58Mb / s到0.9Mb / s ......
队列弹出并使用此类
中的静态方法调用方法take()
如何调整public class C_myMessageQueue {
private static final LinkedBlockingQueue<C_myMessageObject> x_queue = new LinkedBlockingQueue<C_myMessageObject>( 50000 );
/**
* @param message
* @throws InterruptedException
* @throws NullPointerException
*/
public static void addMyMessage( C_myMessageObject message )
throws InterruptedException, NullPointerException {
x_queue.put( message );
}
/**
* @return Die erste message der MesseageQueue
* @throws InterruptedException
*/
public static C_myMessageObject getMyMessage() throws InterruptedException {
return x_queue.take();
}
}
方法以实现至少25Mb / s,或者是否有其他类可以使用,当“队列”已满或为空时将阻止该类。
亲切的问候
巴特
P.S。:对不起我的英语不好,我来自德国;)
答案 0 :(得分:16)
您的生产者线程只是放置的元素多于消费者消耗的元素,因此队列最终会达到其容量限制,因此生产者会等待。
巩固我原来的答案,因为现在我们基本上已经完整了:
LinkedBlockingQueue
来达到put()
(每个队列都有一个)的固有吞吐量限制,即使是连续take()s
,也没有进一步处理,无法跟上。 (顺便说一下,这表明在这个结构中,无论如何,在你的JVM和机器上,put()s至少比读取的成本稍高一些)。 SynchronousQueue
,ConcurrentLinkedQueue
以及jsr166即将来临的TransferQueue
。一些建议:
/更新了
答案 1 :(得分:3)
我通常建议不要在性能敏感的代码区域中使用LinkedBlockingQueue,使用ArrayBlockingQueue。它将提供更好的垃圾收集配置文件,并且比LinkedBlockingQueue更加缓存友好。
尝试使用ArrayBlockingQueue并测量性能。
LinkedBlockingQueue的唯一优势是它可以无限制,但这很少是你真正想要的。如果您遇到消费者失败并且队列开始备份的情况,那么拥有有界队列会使系统优雅地降级,而不会冒着队列无限制时可能出现的OutOfMemoryErrors的风险。
答案 2 :(得分:3)
以下是一些可以尝试的事情:
将LinkedBlockingQueue
替换为ArrayBlockingQueue
。它没有悬空引用,因此在队列填满时表现更好。具体来说,鉴于LinkedBlockingQueue的1.6实现,在队列实际变空之前,不会发生完整的GC元素。
如果生产者方面始终不在执行消费者方面,请考虑使用drain
或drainTo
执行“批量”接收操作。
或者,让队列获取消息对象的数组或列表。生成器使用消息对象填充List或数组,每个put或take移动具有相同锁定开销的多个消息。把它想象成一个秘书,递给你一堆“当你外出”的消息,而不是一次一个地交给你。
答案 3 :(得分:1)
很难说在不了解灌装过程的情况下会发生什么。
如果不经常调用addMyMessage
- 可能是因为应用程序的整个不同部分存在性能问题 - take
方法必须等待。
这样看起来take
是罪魁祸首,但实际上它是应用程序的填充部分。
答案 4 :(得分:1)
发现this interesting post有关队列大小和垃圾回收导致的性能问题。
答案 5 :(得分:0)
您的应用程序可能会受到Java 6中与锁定相关的更改的影响,尤其是“偏向锁定”功能。
尝试使用-XX:-UseBiasedLocking
开关禁用它,看看是否有所作为。
有关详细信息,请参阅此处:http://java.sun.com/performance/reference/whitepapers/6_performance.html
答案 6 :(得分:0)
不能肯定地告诉任何事情。但您可以尝试更改BlockingQueue
实施(就像实验一样)。
您将初始容量设置为50k并使用LinkedBlockingQueue
。尝试使用相同容量的ArrayBlockingQueue
,您也可以使用fair
参数。
答案 7 :(得分:0)
如果从阻塞队列中放置和获取对象的原始性能开销是您的瓶颈(而不是slow-producer/consumer problem),则可以通过批处理对象获得巨大的性能提升:例如,而不是放置或处理好 - 粒度对象,放置或获取粗粒度的对象列表。这是一段代码:
<?php include("./header.inc"); ?>
<div id="container">
<div class="grid-sizer"></div>
<?php if($page->numChildren(true)) {
echo "<ul class='project'>";
foreach($page->children as $childIndex => $child) {
if ($child->head_image) {
$image = $child->head_image;
echo "<li class='item'><a href='#' data-featherlight='#mylightbox" . $childIndex . "'><img id='mylightbox" . $childIndex . "' src='{$image->url}' class='image'></a></li>";
}
}
echo "</ul>";}
?>
<style>.featherlight-content:after {
content:"<?php echo nl2br($child->title); ?> <?php echo nl2br($child->image_description); ?> <?php echo $child->formaat; ?>";}
</style>
</div> <!-- END CONTAINER -->
<script src="//code.jquery.com/jquery-latest.js"></script>
<script src="/site/templates/scripts/lightbox/release/featherlight.min.js" type="text/javascript" charset="utf-8"></script>
批量处理可以将您的性能提升一个数量级。