Мы экспериментируем с изменением встроенной системы баз данных SQLite , чтобы использовать mmap() вместо обычных вызовов read() и write() для доступа к базе данных файл на диске. Использование одного большого отображения для всего файла . Предположим, что файл достаточно мал, что у нас нет проблем найти место для этого в виртуальной памяти.Как переносить файл, доступный с помощью mmap()
Пока все хорошо. Во многих случаях использование mmap() кажется немного быстрее чем read() и write(). А в некоторых случаях гораздо быстрее.
Изменение размера отображения, чтобы зафиксировать транзакцию записи, которую расширяет файл базы данных, кажется, является проблемой. Для того, чтобы расширить файл базы данных, код может сделать что-то вроде этого:
ftruncate(); // extend the database file on disk
munmap(); // unmap the current mapping (it's now too small)
mmap(); // create a new, larger, mapping
затем скопировать новые данные в конце нового отображения памяти. Однако munmap/mmap нежелательно, так как это означает, что в следующий раз при каждой странице файла базы данных происходит обращение к второстепенной ошибке страницы и системе необходимо выполнить поиск в кеше страницы ОС для правильного кадра до , связанного с виртуальным адрес памяти. Другими словами, он замедляет вниз по последующим считываниям базы данных.
В Linux мы можем использовать нестандартный системный вызов mremap() вместо munmap()/mmap(), чтобы изменить размер отображения. Это, по-видимому, позволяет избежать ошибок .
ВОПРОС: Как это должно быть рассмотрено в других системах, таких как OSX, , у которых нет mremap()?
У нас есть две идеи в настоящее время. И вопрос относительно каждого:
1) Создавайте сопоставления, большие, чем файл базы данных. Затем, расширяя файл базы данных, просто вызовите ftruncate(), чтобы расширить файл на диске и продолжить использование того же сопоставления.
Это было бы идеально и, кажется, работает на практике. Тем не менее, мы обеспокоены этим предупреждением на странице человека:
«Влияние изменения размера основного файла в отображения на страницах, которые соответствуют добавлены или удалены регионов файл не определен «.
ВОПРОС: Это что-то, о чем мы должны беспокоиться? Или анахронизм в этот момент?
2) При расширении файла базы данных, использовать первый аргумент MMAP() запросить отображение, соответствующее новых страницы файла базы данных , расположенный непосредственно после текущего отображения в виртуальной памяти . Эффективное расширение исходного отображения. Если система не может выполнить запрос на размещение нового картографирования сразу после , сначала вернитесь к munmap/mmap.
На практике мы обнаружили, что OSX очень хорош в размещении картинок таким образом, поэтому этот трюк работает там.
ВОПРОС: если система не выделит вторую отображение сразу вслед за первым в виртуальной памяти, это то безопасно, в конечном счете Unmap их обоих, используя один большой вызов munmap()?
Я делаю то же самое. В Solaris 10 'munmap' выполняет синхронный' msync', если я правильно помню. Фактически 'msync' всегда был синхронным на Solaris 10, даже когда был задан параметр' MS_ASYNC'. Это были пара последних гвоздей в гробу Солярис. –
Я не думаю, что №1 выполнимо. Создание сопоставления, большего, чем файл, приводит к тому, что конец файла недоступен (хотя он может быть «отображен»), а 'ftruncate()' не будет обновлять сопоставление. – twalberg