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