hangc0276 opened a new issue #2729:
URL: https://github.com/apache/bookkeeper/issues/2729


   **BUG REPORT**
   
   ***Describe the bug***
   When running hundreds of bookie in BookKeeper cluster, and auditor triggered 
to check ledgers, it throw OOM
   ```
   18:12:03.200 [bookkeeper-io-44-2] ERROR 
org.apache.bookkeeper.common.allocator.impl.ByteBufAllocatorImpl - Unable to 
allocate memory
   java.lang.OutOfMemoryError: Direct buffer memory
           at java.nio.Bits.reserveMemory(Bits.java:187) ~[?:?]
           at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123) ~[?:?]
           at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:310) ~[?:?]
           at 
io.netty.buffer.PoolArena$DirectArena.allocateDirect(PoolArena.java:755) 
~[io.netty-netty-buffer-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.buffer.PoolArena$DirectArena.newChunk(PoolArena.java:731) 
~[io.netty-netty-buffer-4.1.51.Final.jar:4.1.51.Final]
           at io.netty.buffer.PoolArena.allocateNormal(PoolArena.java:247) 
~[io.netty-netty-buffer-4.1.51.Final.jar:4.1.51.Final]
           at io.netty.buffer.PoolArena.allocate(PoolArena.java:215) 
~[io.netty-netty-buffer-4.1.51.Final.jar:4.1.51.Final]
           at io.netty.buffer.PoolArena.allocate(PoolArena.java:147) 
~[io.netty-netty-buffer-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:356)
 ~[io.netty-netty-buffer-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:187)
 ~[io.netty-netty-buffer-4.1.51.Final.jar:4.1.51.Final]
           at 
org.apache.bookkeeper.common.allocator.impl.ByteBufAllocatorImpl.newDirectBuffer(ByteBufAllocatorImpl.java:164)
 [org.apache.bookkeeper-bookkeeper-common-allocator-4.12.0.jar:4.12.0]
           at 
org.apache.bookkeeper.common.allocator.impl.ByteBufAllocatorImpl.newDirectBuffer(ByteBufAllocatorImpl.java:158)
 [org.apache.bookkeeper-bookkeeper-common-allocator-4.12.0.jar:4.12.0]
           at 
io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:187)
 [io.netty-netty-buffer-4.1.51.Final.jar:4.1.51.Final]
           at 
org.apache.bookkeeper.proto.BookieProtoEncoding.serializeProtobuf(BookieProtoEncoding.java:366)
 [org.apache.bookkeeper-bookkeeper-server-4.12.0.jar:4.12.0]
           at 
org.apache.bookkeeper.proto.BookieProtoEncoding.access$100(BookieProtoEncoding.java:54)
 [org.apache.bookkeeper-bookkeeper-server-4.12.0.jar:4.12.0]
           at 
org.apache.bookkeeper.proto.BookieProtoEncoding$RequestEnDecoderV3.encode(BookieProtoEncoding.java:328)
 [org.apache.bookkeeper-bookkeeper-server-4.12.0.jar:4.12.0]
           at 
org.apache.bookkeeper.proto.BookieProtoEncoding$RequestEncoder.write(BookieProtoEncoding.java:400)
 [org.apache.bookkeeper-bookkeeper-server-4.12.0.jar:4.12.0]
           at 
io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:717)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:764)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:808)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
org.apache.bookkeeper.proto.AuthHandler$ClientSideHandler$AuthHandshakeCompleteCallback.operationComplete(AuthHandler.java:437)
 [org.apache.bookkeeper-bookkeeper-server-4.12.0.jar:4.12.0]
           at 
org.apache.bookkeeper.proto.AuthHandler$ClientSideHandler$AuthHandshakeCompleteCallback.operationComplete(AuthHandler.java:423)
 [org.apache.bookkeeper-bookkeeper-server-4.12.0.jar:4.12.0]
           at 
org.apache.bookkeeper.auth.AuthProviderFactoryFactory$NullClientAuthProviderFactory.newProvider(AuthProviderFactoryFactory.java:102)
 [org.apache.bookkeeper-bookkeeper-server-4.12.0.jar:4.12.0]
           at 
org.apache.bookkeeper.proto.AuthHandler$ClientSideHandler.channelActive(AuthHandler.java:258)
 [org.apache.bookkeeper-bookkeeper-server-4.12.0.jar:4.12.0]
           at 
io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:230)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:216)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.AbstractChannelHandlerContext.fireChannelActive(AbstractChannelHandlerContext.java:209)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.DefaultChannelPipeline$HeadContext.channelActive(DefaultChannelPipeline.java:1398)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:230)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.AbstractChannelHandlerContext.invokeChannelActive(AbstractChannelHandlerContext.java:216)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.DefaultChannelPipeline.fireChannelActive(DefaultChannelPipeline.java:895)
 [io.netty-netty-transport-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.fulfillConnectPromise(AbstractEpollChannel.java:620)
 [io.netty-netty-transport-native-epoll-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.finishConnect(AbstractEpollChannel.java:653)
 [io.netty-netty-transport-native-epoll-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.epoll.AbstractEpollChannel$AbstractEpollUnsafe.epollOutReady(AbstractEpollChannel.java:529)
 [io.netty-netty-transport-native-epoll-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:465) 
[io.netty-netty-transport-native-epoll-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378) 
[io.netty-netty-transport-native-epoll-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
 [io.netty-netty-common-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) 
[io.netty-netty-common-4.1.51.Final.jar:4.1.51.Final]
           at 
io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
 [io.netty-netty-common-4.1.51.Final.jar:4.1.51.Final]
           at java.lang.Thread.run(Thread.java:844) [?:?]
   
   ```
   
   The code introduced by #2441 , and it change `serializeProtobuf` message 
from heap to direct memory. The code as follow
   ```Java
   private static ByteBuf serializeProtobuf(MessageLite msg, ByteBufAllocator 
allocator) {
           int size = msg.getSerializedSize();
           // Protobuf serialization is the last step of the netty pipeline. We 
used to allocate
           // a heap buffer while serializing and pass it down to netty library.
           // In AbstractChannel#filterOutboundMessage(), netty copies that 
data to a direct buffer if
           // it is currently in heap (otherwise skips it and uses it directly).
           // Allocating a direct buffer reducing unncessary CPU cycles for 
buffer copies in BK client
           // and also helps alleviate pressure off the GC, since there is less 
memory churn.
           // Bookies aren't usually CPU bound. This change improves READ_ENTRY 
code paths by a small factor as well.
           ByteBuf buf = allocator.directBuffer(size, size);
   
           try {
               
msg.writeTo(CodedOutputStream.newInstance(buf.nioBuffer(buf.readerIndex(), 
size)));
           } catch (IOException e) {
               // This is in-memory serialization, should not fail
               throw new RuntimeException(e);
           }
   
           // Advance writer idx
           buf.writerIndex(buf.capacity());
           return buf;
      }
   ```
   
   I doubt whether will casue direct memory leak due to not release.
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to