PooledUnsafeDirectByteBuf не найден в DirectMemory

Я использую Netty 4.1.17-Final.

Я написал код для отправки и получения 100 МБ случайного ASCII. Декодер не читает, пока ByteBuf не станет 100 МБ.

@Override
public void decode(ByteBuffer _in, List<Object> _out) {
    if (_in.remaining() == size) {   // size = 100 * 1024 * 1024
        _in.get(new byte[size]);
    }
}

Следовательно, Netty буферизует 100 МБ, но это не было обнаружено даже при мониторинге Direct Memory.

System.out.println(sun.misc.SharedSecrets.getJavaNioAccess().getDirectBufferPool().getMemoryUsed());
ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class).forEach(buf -> {
    System.out.printf("%s: Used=%d, TotalCap=%d%n", buf.getName(), buf.getMemoryUsed(), buf.getTotalCapacity());
});

// Result
// 10
// direct: Used=9, TotalCap=8
// mapped: Used=0, TotalCap=0

Нетти использовала PooledUnsafeDirectByteBuf, но где вы буферизуете полученные данные? Или метод прямого контроля буфера некорректен?


person nikai    schedule 20.06.2018    source источник


Ответы (2)


Вы можете указать Netty не использовать Unsafe для прямых буферов, чтобы он снова отображался в JMX. К сожалению, это также будет иметь некоторое влияние на производительность.

Просто используйте -Dio.netty.maxDirectMemory=0.

См.: https://github.com/netty/netty/blob/4.1/common/src/main/java/io/netty/util/internal/PlatformDependent.java#L153

person Norman Maurer    schedule 20.06.2018
comment
Спасибо за ваш ответ. Мой код теперь использует DirectBuffer. Я нашел io.netty.noUnsafe и io.netty.noPreferDirect. В чем разница между ними и io.netty.maxDirectMemory = 0? - person nikai; 21.06.2018
comment
..noUnsafe полностью отключить использование sun.misc.Unsafe (что в целом приводит к снижению производительности). ...noPreferDirect заставит allocator.buffer() возвращать буфер кучи, а не прямой буфер. Это может привести к увеличению количества копий памяти. ...maxDirectMemory=0 просто гарантирует, что мы используем DirectByteBuffer под прикрытием, и поэтому JMX будет работать. Поэтому я бы посоветовал использовать то, что я предложил, если у вас нет других веских причин этого не делать. - person Norman Maurer; 21.06.2018
comment
Спасибо вежливо. Я буду использовать maxDirectMemory = 0, как вы говорите. - person nikai; 22.06.2018

Самостоятельный ответ. В моем коде Нетти приобрела DirectMemory, используя com.sun.Unsafe. Эта область не может быть захвачена с помощью BufferPoolMXBean или SharedSecrets.

Я пытался получить память с помощью Unsafe, но она не выводилась в результат мониторинга.

Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe) unsafeField.get(null);
unsafe.allocateMemory(1000);

Я нашел следующий запрос.
расширение для отслеживания использования памяти вне кучи для нетти · Выпуск №475 · Netflix/зритель

Скажите, пожалуйста, есть ли способ получить размер, полученный Unsafe.

person nikai    schedule 20.06.2018