Надеюсь, у меня здесь есть все грязные детали, они немного тонкие.
По умолчанию Netty обычно устанавливает io.netty.maxDirectMemory=MaxDirectMemorySize
и включает буферы «без очистки», если это возможно. Если используются «чистые» буферы, прямая память Netty и «собственная» прямая память Java отслеживаются независимо - потому что Netty необходимо вести собственный учет для отслеживания памяти, выделенной Unsafe.allocateMemory
в «чистых» буферах.
Это означает, что теоретический максимальный объем памяти, выделенный для данных вне кучи, в службе Netty, на которой запущена конфигурация по умолчанию, часто по умолчанию приблизительно равен io.netty.maxDirectMemory+MaxDirectMemorySize
- или 2 x MaxDirectMemorySize
. Это вроде тихо задокументировано здесь:
https://github.com/netty/netty/blob/6cebb6069b3f30eedaddb12d2d22a6dd66277047/common/src/main/java/io/netty/util/internal/PlatformDependent.java#L132-L139
Так что это хорошо, даже если это немного удивительно.
Но вещи кажутся немного странными, когда вы пытаетесь явно установить io.netty.maxDirectMemory и MaxDirectSize в разные значения. Например, мы пытались немного ограничить наш теоретический потолок памяти, чтобы поиграть с cgroups: рассматриваемая служба убивала OOM, поэтому мы стали немного агрессивными и, как только поняли связь между MDMS / inmdm, установили MaxDirectMemorySize и io.netty.maxDirectMemory явным образом минимизируют наш потолок - -XX:MaxDirectMemorySize=1g
и задайте -Dio.netty.maxDirectMemory=3221225472
с включенными прямыми буферами «не чище».
Я ожидал, что это фактически будет неактивным изменением в отношении Netty, поскольку у нас было -XX:MaxDirectMemorySize=3g
до того, как мы явно установили io.netty.maxDirectMemory
. Тем не менее, мы наблюдали значительно меньшее использование прямой памяти. Подозревая, что это, вероятно, связано с уменьшенным размером MaxDirectMemory, я в конце концов нашел это, что, я думаю, могло бы объяснить разницу.
https://github.com/netty/netty/blob/6cebb6069b3f30eedaddb12d2d22a6dd66277047/buffer/src/main/java/io/netty/buffer/PooledByteBufAllocator.java#L92-L97
Зачем здесь использовать PlatformDependent.maxDirectMemory()
(для которого будет установлено значение MaxDirectMemorySize
вместо логического io.netty.maxDirectMemory
) вместо, например. DIRECT_MEMORY_LIMIT
(который имеет значение , установленное в явное или предполагаемое значение io.netty.maxDirectMemory
)?
Возможно, я что-то неправильно понял по пути, и я не обязательно жалуюсь, просто пытаюсь понять: это намеренное поведение? Недосмотр / ошибка? Что-то, что трудно изменить, потому что люди теперь полагаются на существующую семантику? Что-то еще?