предисловие
Java представила классы, связанные с NIO, такие как ByteBuffer в JDK 1.4, что позволяет программистам Java отказаться от потоков на основе и, таким образом, использовать методы на основе блоков для чтения и записи файлов. скопируйте sendFile и mmap . Но как насчет их производительности? Насколько быстрее по сравнению с RandomAccessFile? Быстро при каких обстоятельствах? FileChannel быстрее или MappedByteBuffer быстрее...
(ссылка с нулевым копированиемZero Copy I: User-Mode Perspective)
Олег, столько вопросов! ! ! ! ! !
Давайте медленно проанализируем это.
Взгляните на MQ, которые хорошо справляются с нулевым копированием ввода-вывода.
Мы знаем, что в мире Java есть много MQ: ActiveMQ, kafka, RocketMQ, Qunar MQ, и они являются крупными пользователями нулевого копирования NIO в мире Java.
Тем не менее, их производительность одинакова.Помимо других факторов, таких как метод передачи по сети, дизайн структуры данных и метод хранения файлов, мы обсуждаем только чтение и запись файлов на стороне брокера и видим, чем они отличаются.
На следующем рисунке показаны методы чтения и записи файлов, используемые каждым MQ, обобщенные арендодателем для просмотра исходного кода.
- kafka: Чтение и запись записей основаны на FileChannel. Чтение и запись индекса основаны на MMAP (Medium Hints).
- RocketMQ: Диск чтения основан на MMAP, а диск записи использует MMAP по умолчанию. Его можно настроить как FileChannel, изменив конфигурацию. Причина в том, что автор хочет избежать конкуренции блокировок PageCache и реализовать разделение чтения и писать через двухуровневую архитектуру.
- QMQ: Где перейти к MQ, MMAP используется для чтения дисков, а FileChannel используется для записи дисков.
- ActiveMQ 5.15: чтение и запись основаны на RandomAccessFile, поэтому мы отказались от ActiveMQ.
Итак, что сильнее MMAP или FileChannel?
MMAP Как мы все знаем, основанная на технологии отображения памяти mmap операционной системы, MMU отображает файлы, делая случайные файлы чтения и записи, а также чтение и запись в память с одинаковой скоростью.
Как насчет FileChannel? Это нулевая копия? Извините но нет. FileChannel работает быстро только потому, что он основан на блоках.
Далее сравните все - Сюй Ма.
Ориентир?
Как провести бенчмаркинг? Какие тесты?
Поскольку речь идет о чтении и записи файлов, естественно смотреть на производительность чтения и записи, которая является самой базовой. Обратите внимание, однако, что MQ обычно использует сброс по времени для предотвращения потери данных.И MMAP, и FileChannel имеют принудительные методы для сброса данных pageCache на жесткий диск. Влияет ли сила на производительность? Ответ положительный. В какой степени это влияет? понятия не имею. Влияет ли размер данных на одну запись на производительность, несомненно, влияет, но каковы правила? Действительно ли FileOutputStream бесполезен? Ответ не обязательно.
Настройка файлов всегда была искусством, потому что на производительность влияет слишком много факторов.Во-первых, появление SSD поставило под вопрос традиционную древовидную структуру B+.Во-вторых, производительность каждой файловой системы различна. разница между Linux ext3 и ext4 огромна (примерно в 20 раз больше производительности при удалении файлов). Система HFS+ в ОС Max была названа Линусом «самой дрянной файловой системой из когда-либо существовавших». К счастью, в 2017 году Apple наконец-то выпустила системы macOS High Sierra и iOS 10.3, обе из которых отказались от HFS+ и заменили ее. Она стала APFS с более высоким представление. И каждая файловая система может устанавливать разные алгоритмы планирования, кроме того, существуют сбои производительности, вызванные прерываниями по ошибке страницы виртуальной памяти......
(советы: добросовестный RocketMQ предоставляет скрипт для настройки ввода-вывода Linux, и это хорошая работа :)
Не по теме.
Арендодатель написал небольшой проект для проверки производительности чтения и записи Java MappedByteBuffer, FileChannel, RandomAccessFile и FileXXXputStream. Вы также можете запустить и посмотреть на своей машине.
тестовая среда
Процессор: Intel i7 4 ядра 8 потоков 4,2 ГГц Память: 40 ГБ DDR4 Диск: SSD чтение и запись около 2 Гб/с JDK1.8 ОС: Mac OS 10.13.6 Виртуальная память: не отключается, размер 9GB
Примечания к тесту:
- Чтобы предотвратить эффект кэширования PageCache, каждый раз для чтения создается новый файл.
- Чтобы проверить влияние разных пакетов на производительность, требуется несколько тестов с пакетами разного размера.
- force сильно влияет на производительность и должна тестироваться отдельно.
- Протестируйте с файлом размером 1 ГБ (маленькие файлы не имеют справочного значения, большие файлы не могут быть сопоставлены с помощью mmap)
тест на чистое чтение
1 ГБ файл:
Протестируйте MappedByteBuffer, FileChannel, RandomAccessFile и FileInputStream.
Из этого графика видно, что mmap выигрывает, особенно в случае небольших объемов данных. Остальные потоки, только в случае 4кб, начинают убивать mmap.Поэтому для чтения данных менее 4 КБ используйте mmap.
Увеличьте масштаб, чтобы увидеть сравнение mmap и FileChannel:
По приведенному выше рисунку мы видим, что в случае записи пакетов данных размером более 4кб FileChannel и другие ненулевые копии в основном выигрывают у mmap, за исключением теста BT, который за раз читает файлы размером 1G.
Поэтому, если ваши пакеты больше 4 КБ, используйте FileChannel.
Просто пиши тесты
1 ГБ файл:
Протестируйте MappedByteBuffer, FileChannel, RandomAccessFile и FileInputStream.
Из приведенного выше рисунка видно, что производительность mmap осталась прежней. FileChannel тоже неплох, но с 32 байтами данных это не так уж и плохо.
Посмотрите еще раз на миниатюру:
Мы видим, что 64 байта — это водораздел производительности FileChannel и mmap.Начиная с 64 байт, FileChannel отбивается до тех пор, пока файл BT 1 ГБ немного не теряет.
Поэтому мы рекомендуем:Если размер вашего пакета превышает 64 байта, используйте FileChannel для записи.
Асинхронное силовое испытание
Мы знаем, что RocketMQ использует асинхронную очистку, поэтому влияет ли асинхронная сила на производительность? сравните все. Давайте использовать асинхронные потоки и обновлять каждые 16 КБ, чтобы увидеть, как это работает.
mmap отстает, и производительность очень плохая, за исключением небольшого джиттера на 2048 байт, он в основном поддерживается на уровне около 4000, а без форсирования - около 1500. И FileChannel совершенно не зависит от силы. В моих тестах файл размером 1 ГБ занимал около 800 мс для одной силы. Чем больше буфер, тем больше время, и наоборот.
В качестве отступления Кафка не рекомендовал применять силу, вероятно, по этой причине. Конечно, у Kafka также есть собственная стратегия многократного копирования для обеспечения безопасности данных.
Здесь мы приходим к выводу, что если вам нужно выполнять принудительно часто, даже асинхронно, не используйте mmap, используйте FileChannel.
Суммировать.
На основании вышеперечисленных тестов строим график:
Предполагая, что пакеты нашей системы составляют около 1024-2048, какую стратегию мы должны использовать?
A: Чтение с помощью mmap, просто запись с использованием FileChannel.
Оглядываясь назад на разработчиков MQ, кажется, что это делает только QMQ. Конечно, RocketMQ также предоставляет возможность записи для FileChannel. Но по умолчанию запись mmap и асинхронный флэш-диск должны быть виновниками занятости брокера.
А Kafka, поскольку он не принудительно по умолчанию, также использует FileChannel для записи, зачем использовать FileChannel для чтения? Вероятно потому, что размер сообщения больше 4кб.
Такое предположение, дизайн этих MQ кажется очень разумным.
Наконец, не применяйте силу, если можете. Если необходимо применить силу, используйте FileChannel.