Return-Path: X-Original-To: apmail-activemq-dev-archive@www.apache.org Delivered-To: apmail-activemq-dev-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 3FF681825B for ; Thu, 4 Feb 2016 16:53:47 +0000 (UTC) Received: (qmail 56852 invoked by uid 500); 4 Feb 2016 16:53:25 -0000 Delivered-To: apmail-activemq-dev-archive@activemq.apache.org Received: (qmail 56792 invoked by uid 500); 4 Feb 2016 16:53:25 -0000 Mailing-List: contact dev-help@activemq.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@activemq.apache.org Delivered-To: mailing list dev@activemq.apache.org Received: (qmail 56781 invoked by uid 99); 4 Feb 2016 16:53:25 -0000 Received: from Unknown (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 04 Feb 2016 16:53:25 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id A33E0C2237 for ; Thu, 4 Feb 2016 16:53:24 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 2.35 X-Spam-Level: ** X-Spam-Status: No, score=2.35 tagged_above=-999 required=6.31 tests=[RCVD_IN_DNSWL_NONE=-0.0001, SPF_SOFTFAIL=0.972, URI_HEX=1.313, URI_TRY_3LD=0.065] autolearn=disabled Received: from mx1-eu-west.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id zsa0pDubOfHc for ; Thu, 4 Feb 2016 16:53:22 +0000 (UTC) Received: from mwork.nabble.com (mwork.nabble.com [162.253.133.43]) by mx1-eu-west.apache.org (ASF Mail Server at mx1-eu-west.apache.org) with ESMTP id 98ABA31ACC for ; Thu, 4 Feb 2016 16:53:21 +0000 (UTC) Received: from mjoe.nabble.com (unknown [162.253.133.57]) by mwork.nabble.com (Postfix) with ESMTP id 3CB8211EFADF5 for ; Thu, 4 Feb 2016 08:46:47 -0800 (PST) Date: Thu, 4 Feb 2016 08:29:25 -0800 (PST) From: jim_b_o To: dev@activemq.apache.org Message-ID: <1454603365259-4706961.post@n4.nabble.com> Subject: Artemis use of PhantomReference impacting GC performance MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit I have observed a significant degradation in GC performance after upgrading from JBoss 4.2.3.GA to WildFly 10.0.0.Final. I'm 99% sure the difference is due to Artemis ActiveMQ making heavy use of PhantomReference objects (directly or indirectly). I'm raising this discussion to see if anyone else can observe the same behaviour and determine whether to raise an issue against Artemis or one of its dependencies. What's changed? I have JBoss 4.2.3.GA (with jboss-messaging-1.4.5.GA) and WildFly 10.0.0.Final running on identical hardware with identical JVMs (8u71) and GC settings (using G1GC). The application is only minimally changed as required by the API differences between the old and new servers. The application load is identical and results in near identical memory allocation rate and young GC frequency. *The difference is that on JBoss each young GC takes around 10-12ms whereas on WildFly they take 16-20ms.* The additional time is taken in the Object Copy and Ref Proc phases. This indicates that there are more Survivor objects on each GC and more References being processed. I'm pretty sure the additional Survivor objects are also the Reference objects. Running a Java Mission Control (JMC) Flight Recording on these two systems under identical production load, WildFly is showing around 11,000 PhantomReferences processed each GC versus a handful on JBoss. The number of PhantomReferences seems to approximately correspond to the number of JMS messages transmitted between GCs. Some evidence In a separate test environment I have WildFly running under a standard test load. It is emitting JMS messages at a consistent rate (lower than production) onto a non-durable Topic. The following image shows a 2 minute JMC recording when there is no subscriber on the Topic. We can see that there are very few PhantomReferences and the GCs take around 4ms. However once I start up an external JMS client subscribed to the Topic the PhantomReferences appear and the GCs slow down as shown in the next image. The messaging is non-XA with auto-ack. Where do the PhantomReferences come from? I used the debugger to capture where the PhantomReferences are being created. This seems to indicate they are generated by Artemis and/or the associated XNIO remoting... Thread [Thread-1 (ActiveMQ-server-org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl$2@788d198e-832298282)] (Suspended (breakpoint at line 80 in PhantomReference)) Cleaner(PhantomReference).(T, ReferenceQueue) line: 80 Cleaner.(Object, Runnable) line: 115 Cleaner.create(Object, Runnable) line: 133 DirectByteBuffer.(int) line: 139 ByteBuffer.allocateDirect(int) line: 311 UnpooledUnsafeDirectByteBuf.allocateDirect(int) line: 108 UnpooledUnsafeDirectByteBuf.(ByteBufAllocator, int, int) line: 69 UnpooledByteBufAllocator.newDirectBuffer(int, int) line: 50 UnpooledByteBufAllocator(AbstractByteBufAllocator).directBuffer(int, int) line: 155 UnpooledByteBufAllocator(AbstractByteBufAllocator).directBuffer(int) line: 146 NettyServerConnection.createTransportBuffer(int) line: 38 RemotingConnectionImpl(AbstractRemotingConnection).createTransportBuffer(int) line: 162 SessionReceiveMessage.encode(RemotingConnection) line: 59 ChannelImpl.send(Packet, boolean, boolean) line: 225 ChannelImpl.sendBatched(Packet) line: 205 CoreSessionCallback.sendMessage(ServerMessage, ServerConsumer, int) line: 84 ServerConsumerImpl.deliverStandardMessage(MessageReference, ServerMessage) line: 883 ServerConsumerImpl.proceedDeliver(MessageReference) line: 366 QueueImpl.proceedDeliver(Consumer, MessageReference) line: 2358 QueueImpl.deliver() line: 1873 QueueImpl.access$1400(QueueImpl) line: 97 QueueImpl$DeliverRunner.run() line: 2581 OrderedExecutorFactory$OrderedExecutor$ExecutorTask.run() line: 100 ThreadPoolExecutor.runWorker(ThreadPoolExecutor$Worker) line: 1142 ThreadPoolExecutor$Worker.run() line: 617 Thread.run() line: 745 Thread [default I/O-5] (Suspended (breakpoint at line 80 in PhantomReference)) Cleaner(PhantomReference).(T, ReferenceQueue) line: 80 Cleaner.(Object, Runnable) line: 115 Cleaner.create(Object, Runnable) line: 133 DirectByteBuffer.(int) line: 139 ByteBuffer.allocateDirect(int) line: 311 UnpooledUnsafeDirectByteBuf.allocateDirect(int) line: 108 UnpooledUnsafeDirectByteBuf.(ByteBufAllocator, int, int) line: 69 UnpooledByteBufAllocator.newDirectBuffer(int, int) line: 50 UnpooledByteBufAllocator(AbstractByteBufAllocator).directBuffer(int, int) line: 155 UnpooledByteBufAllocator(AbstractByteBufAllocator).directBuffer(int) line: 146 UnpooledByteBufAllocator(AbstractByteBufAllocator).ioBuffer(int) line: 107 AdaptiveRecvByteBufAllocator$HandleImpl.allocate(ByteBufAllocator) line: 104 AbstractXnioSocketChannel$ReadListener.handleEvent(ConduitStreamSourceChannel) line: 426 AbstractXnioSocketChannel$ReadListener.handleEvent(Channel) line: 371 ChannelListeners.invokeChannelListener(T, ChannelListener) line: 92 ReadReadyHandler$ChannelListenerHandler.readReady() line: 66 NioSocketConduit.handleReady(int) line: 88 WorkerThread.run() line: 559 Thread [default I/O-4] (Suspended (breakpoint at line 80 in PhantomReference)) Cleaner(PhantomReference).(T, ReferenceQueue) line: 80 Cleaner.(Object, Runnable) line: 115 Cleaner.create(Object, Runnable) line: 133 DirectByteBuffer.(int) line: 139 ByteBuffer.allocateDirect(int) line: 311 UnpooledUnsafeDirectByteBuf.allocateDirect(int) line: 108 UnpooledUnsafeDirectByteBuf.(ByteBufAllocator, int, int) line: 69 UnpooledByteBufAllocator.newDirectBuffer(int, int) line: 50 UnpooledByteBufAllocator(AbstractByteBufAllocator).directBuffer(int, int) line: 155 UnpooledByteBufAllocator(AbstractByteBufAllocator).directBuffer(int) line: 146 UnpooledByteBufAllocator(AbstractByteBufAllocator).ioBuffer(int) line: 107 AdaptiveRecvByteBufAllocator$HandleImpl.allocate(ByteBufAllocator) line: 104 AbstractXnioSocketChannel$ReadListener.handleEvent(ConduitStreamSourceChannel) line: 426 AbstractXnioSocketChannel$ReadListener.handleEvent(Channel) line: 371 ChannelListeners.invokeChannelListener(T, ChannelListener) line: 92 ReadReadyHandler$ChannelListenerHandler.readReady() line: 66 NioSocketConduit.handleReady(int) line: 88 WorkerThread.run() line: 559 Thread [default I/O-2] (Suspended (breakpoint at line 80 in PhantomReference)) Cleaner(PhantomReference).(T, ReferenceQueue) line: 80 Cleaner.(Object, Runnable) line: 115 Cleaner.create(Object, Runnable) line: 133 DirectByteBuffer.(int) line: 139 ByteBuffer.allocateDirect(int) line: 311 UnpooledUnsafeDirectByteBuf.allocateDirect(int) line: 108 UnpooledUnsafeDirectByteBuf.(ByteBufAllocator, int, int) line: 69 UnpooledByteBufAllocator.newDirectBuffer(int, int) line: 50 UnpooledByteBufAllocator(AbstractByteBufAllocator).directBuffer(int, int) line: 155 UnpooledByteBufAllocator(AbstractByteBufAllocator).directBuffer(int) line: 146 UnpooledByteBufAllocator(AbstractByteBufAllocator).ioBuffer(int) line: 107 AdaptiveRecvByteBufAllocator$HandleImpl.allocate(ByteBufAllocator) line: 104 AbstractXnioSocketChannel$ReadListener.handleEvent(ConduitStreamSourceChannel) line: 426 AbstractXnioSocketChannel$ReadListener.handleEvent(Channel) line: 371 ChannelListeners.invokeChannelListener(T, ChannelListener) line: 92 ReadReadyHandler$ChannelListenerHandler.readReady() line: 66 NioSocketConduit.handleReady(int) line: 88 WorkerThread.run() line: 559 What's next? So it's seems pretty certain that this is where the change is coming from. The total GC load is still low but we're aiming for consistent low latency and this is a backwards step. I'd be interested in any comments or questions. I can provide more info if required. Thanks. -- View this message in context: http://activemq.2283324.n4.nabble.com/Artemis-use-of-PhantomReference-impacting-GC-performance-tp4706961.html Sent from the ActiveMQ - Dev mailing list archive at Nabble.com.