Распределение памяти ByteBuffer - PullRequest
0 голосов
/ 06 октября 2018

Я пытаюсь понять, как DirectByteBuffer работает в Linux, и написал следующую очень простую программу для работы в режиме strace:

public static void main(String[] args){
    while(true){
        ByteBuffer buffer = ByteBuffer.allocateDirect(8192);
    }
}

Я ожидал, что на самом деле некоторые mmap или sys_brk системные вызовывыделять память из операционной системы напрямую, но на самом деле она просто устанавливает защиту от чтения и записи запрошенных страниц.Я имею в виду что-то вроде:

mprotect(0x7fa9681ef000, 8192, PROT_READ|PROT_WRITE) = 0

Кажется, причина в том, что выделение прямого буфера медленнее, чем выделение буфера кучи, поскольку для каждого выделения требуется системный вызов.

Пожалуйста, исправьте меня, если я ошибаюсь, но выделение буфера кучи (если происходит внутри TLAB) эквивалентно возвращению указателя на предварительно выделенную память кучи.

ВОПРОС: Почему мы не можем сделать то же самое для прямой памяти?Вернуть указатель на заранее выделенную память?

1 Ответ

0 голосов
/ 06 октября 2018

В Oracle / OpenJDK ByteBuffer.allocateDirect(n) использует Unsafe.allocateMemory (n) , что в свою очередь вызывает malloc в Linux.

В Linux malloc выделяет из пула памяти меньшие выделения, например 8 КБ, однако для выделения 128 КБ или более добавляет новый mmap.

Iна самом деле ожидалось, что некоторые системные вызовы mmap или sys_brk будут выделять память непосредственно из операционной системы

Попробуйте выделить 128 << 10 или 128 КБ за раз.

Это кажется причиной того, чтовыделение прямого буфера медленнее, чем выделение буфера кучи, поскольку для каждого выделения требуется системный вызов.

Системный вызов добавляет около 2 микросекунд.Предполагается, что прямые байтовые буферы нередко выделяются и освобождаются.Вы должны найти способы повторно использовать эти буферы.

Пожалуйста, исправьте меня, если я ошибаюсь, но выделение буфера кучи (если происходит внутри TLAB) эквивалентно возвращению указателя на предварительно выделенную память кучи.

Правильно.Меньшее распределение в собственной памяти использует собственную кучу.

ВОПРОС: Почему мы не можем сделать то же самое для прямой памяти?

Да.

Вернуть указатель на предварительно выделенную память?

Это не делает это для 128 КБ + для освобожденияпамять обратно в ОС.

...