Ожидается ли, что Direct NIO ByteBuffer будет превосходить Direct Netty ByteBuf при записи байтов?

#netty

#netty

Вопрос:

Я написал тест JMH для диагностики таких странных проблем с пропускной способностью, которые я наблюдал при использовании буферов Netty вместо буферов NIO. Netty direct ByteBuf значительно медленнее при записи байт за байтом, чем у его аналога NIO ByteBuffer. Еще более интересным является то, что если я получу NIO ByteBuffer из Netty ByteBuf, производительность будет на одном уровне с NIO ByteBuffer. Поэтому я могу быть уверен, что это не базовая прямая память или внутренний байтбуфер, а что-то в слоях ByteBuf. Ожидается ли это? Я неправильно его использую?

Вот необработанные результаты.

 Benchmark                                               Mode  Cnt       Score   Error  Units
ByteBufferBenchmark.directByteBuffer                   thrpt    2  206815.012          ops/s
ByteBufferBenchmark.heapByteBuffer                     thrpt    2  159197.697          ops/s
ByteBufferBenchmark.pooledDirectByteBuf                thrpt    2  120753.217          ops/s
ByteBufferBenchmark.pooledDirectByteBufAsByteBuffer    thrpt    2  204986.976          ops/s
ByteBufferBenchmark.pooledHeapByteBuf                  thrpt    2  121846.543          ops/s
ByteBufferBenchmark.pooledHeapByteBufAsByteBuffer      thrpt    2  159503.425          ops/s
ByteBufferBenchmark.unpooledDirectByteBuf              thrpt    2  121781.355          ops/s
ByteBufferBenchmark.unpooledDirectByteBufAsByteBuffer  thrpt    2  208623.215          ops/s
ByteBufferBenchmark.unpooledHeapByteBuf                thrpt    2  158904.532          ops/s
ByteBufferBenchmark.unpooledHeapByteBufAsByteBuffer    thrpt    2  160171.685          ops/s


directByteBuffer = ByteBuffer.allocateDirect
heapByteBuffer = ByteBuffer.allocate
*DirectByteBuf = ByteBufAllocator.allocateDirect
*HeapByteBuf = ByteBufAllocator.allocateHeap
pool* = PooledByteBufAllocator.DEFAULT
unpool* = PooledByteBufAllocator.DEFAULT
*AsByteBuffere = ByteBuffer.nioBuffer
  

Ответ №1:

Пожалуйста, поделитесь всем кодом (и версией jdk), если это возможно, или я не могу понять, в каких операциях буферы Netty работают медленнее.

Как общее эмпирическое правило: классы JDK могут (и многие из них, скорее всего, выиграют от того, что будут «хорошими гражданами» с самой JVM, т.Е. Их операции интегрированы (см. Общую концепцию на https://en.m.wikipedia.org/wiki/Intrinsic_function ) и, как следствие, их оптимизированный встроенный код (см. http://normanmaurer.me/blog/2014/05/15/Inline-all-the-Things /). Короче говоря, NIO ByteBuffer играет «грязно» против Netty ByteBuf, в зависимости от версии JVM, благодаря нескольким оптимизациям, которые просто недоступны для обычных пользовательских типов данных. Возвращаясь к вашему вопросу: можно ожидать, что да, в зависимости от операций и контекста вызова (которые влияют на встраивание операций ByteBuf, вероятность векторизации и устранения связанных проверок). Недавно я исправил проблему с Netty, связанную с этим https://github.com/netty/netty/pull/10368 : не стесняйтесь погрузиться в длинный список комментариев, я уверен, это поможет ответить на ваш вопрос.