fpta: выпуск v0.3.18 Стабильный релиз с исправлением ошибок, мажорным обновлением libmdbx (опорного движка хранения) и изменением API функций связанных со справочником схемы. Исправления и доработки в libfpta: ================================== - Устранена проблема зацикливания читающих транзакций в процессах переполняющих БД: - Исправлена ошибка в логике обработке/отслеживания дескрипторов таблиц становящимися невалидными при асинхронном изменении схемы, из-за которой в ситуации прерывания транзакции из-за переполнения БД производилось ненужное обнуление дескриптора схемы и сброс кэша дескрипторов таблиц. Что являлось триггером для проявления следующей ошибки. - Исправлено упущение в логике инициализации транзакций при отсутствии схемы, что в совокупности с первой ошибкой приводило к циклическому рестарту читающей транзакции в попытках прочитать несуществующую версию схемы БД. - Добавлен юнит-тест воспроизводящий проблему и проверяющий исправление. - Изменение API для возможности использования `std::string_view` и `struct iovec` при получении и передачи имен элементов схемы: - Добавлены функции API принимающие имена объектов в `struct iovec`, что позволяет использовать `std::string_view`. - Изменен тип результата возвращаемого функциями API, связанными со справочником схемы и получения схемы БД в формате JSON. - Несущественные доработки юнит-тестов: - Исправление опечаток. - Установка affinity потоков для более быстрого воспроизведения целевых ситуаций и уменьшения внутренних итераций тестов, что существенно сокращает затрачиваемое время. - Устранены сбои при срабатывании таймаутов на максимальное время выполнения тестов, отдельных тестов. - Устранены несущественные предупреждения новых версий компиляторов и Coverity. - Мажорное обновление libmdbx с `0.11.13.0` на `0.12.6.6`. Исправления и доработки в libmdbx: ================================== Новое: ------ - Реализована prefault-запись при выделении страниц для read-write отображений. Это приводит к кратному снижению системных издержек и существенному увеличению производительности в соответствующих сценариях использования, когда: - размер БД и объём данных существенно больше ОЗУ; - используется режим `MDBX_WRITEMAP`; - не-мелкие транзакции (по ходу транзакции выделяется многие сотни или тысячи страниц). В режиме `MDBX_WRITEMAP` выделение/переиспользование страниц приводит к page-fault и чтению страницы с диска, даже если содержимое страницы не нужно (будет перезаписано). Это является следствием работы подсистемы виртуальной памяти, а штатный способ лечения через `MADV_REMOVE` работает не на всех ФС и обычно дороже получаемой экономии. Теперь в libmdbx используется "упреждающая запись" таких страниц, которая на системах с [unified page cache](https://www.opennet.ru/base/dev/ubc.txt.html) приводит к "вталкиванию" данных, устраняя необходимость чтения с диска при обращении к такой странице памяти. Новый функционал работает в согласованности с автоматическим управлением read-ahead и кэшем статуса присутствия страниц в ОЗУ, посредством [mincore()](https://man7.org/linux/man-pages/man2/mincore.2.html). - Добавлена опция `MDBX_opt_prefault_write_enable` для возможности принудительного включения/выключения prefault-записи. - Реализован динамический выбор между сквозной записью на диск и обычной записью с последующим [fdatasync()](https://man7.org/linux/man-pages/man3/fdatasync.3p.html) управляемый опцией `MDBX_opt_writethrough_threshold`. В долговечных (durable) режимах данные на диск могут быть сброшены двумя способами: - сквозной записью через файловый дескриптор открытый с `O_DSYNC`; - обычной записью с последующим вызовом `fdatasync()`. Первый способ выгоднее при записи малого количества страниц и/или если канал взаимодействия с диском/носителем имеет близкую к нулю задержку. Второй способ выгоднее если требуется записать много страниц и/или канал взаимодействия имеет весомую задержку (датацентры, облака). Добавленная опция `MDBX_opt_writethrough_threshold` позволяет во время выполнения задать порог для динамического выбора способа записи в зависимости от объема и конкретных условия использования. - Автоматическая установка `MDBX_opt_rp_augment_limit` в зависимости от размера БД. - Запрещение разного режима `MDBX_WRITEMAP` между процессами в режимах с отложенной/ленивой записью, так как в этом случае невозможно обеспечить сброс данных на диск во всех случаях на всех поддерживаемых платформах. - Добавлена опция сборки `MDBX_MMAP_USE_MS_ASYNC` позволяющая отключить использование системного вызова `msync(MS_ASYNC)`, в использовании которого нет необходимости на подавляющем большинстве актуальных ОС. По-умолчанию `MDBX_MMAP_USE_MS_ASYNC=0` (выключено) на Linux и других системах с unified page cache. Такое поведение (без использования `msync(MS_ASYNC)`) соответствует неизменяемой (hardcoded) логике LMDB. В результате, в простых/наивных бенчмарках, libmdbx опережает LMDB примерно также как при реальном применении. На всякий случай стоит еще раз отметить/напомнить, что на Windows предположительно libmdbx будет отставать от LMDB в сценариях с множеством мелких транзакций, так как libmdbx осознанно использует на Windows файловые блокировки, которые медленные (плохо реализованы в ядре ОС), но позволяют застраховать пользователей от массы неверных действий приводящих к повреждению БД. - Поддержка не-печатных имен для subDb. - Добавлен явный выбор `tls_model("local-dynamic")` для обхода проблемы `relocation R_X86_64_TPOFF32 against FOO cannot be used with -shared` из-за ошибки в CLANG приводящей к использованию неверного режима `ls_model`. - Изменение тактики слияния страниц при удалении. Теперь слияние выполняется преимущественно с уже измененной/грязной страницей. Если же справа и слева обе страницы с одинаковым статусом, то с наименее заполненной, как прежде. В сценариях с массивным удалением это позволяет увеличить производительность до 50%. - Добавлен контроль отсутствия LCK-файлов с альтернативным именованием. - Добавлена функция `mdbx_env_warmup()` для "прогрева" БД с возможностью закрепления страниц в памяти. В утилиты `mdbx_chk`, `mdbx_copy` и `mdbx_dump` добавлены опции `-u` и `-U` для активации соответствующего функционала. - Отключение учета «грязных» страниц в не требующих этого режимах (`MDBX_WRITEMAP` при `MDBX_AVOID_MSYNC=0`). Доработка позволяет снизить накладные расходы и была запланирована давно, но откладывалась так как требовала других изменений. - Вытеснение из памяти (спиллинг) «грязных» страниц с учетом размера large/overflow-страниц. Доработка позволяет корректно соблюдать политику задаваемую опциями `MDBX_opt_txn_dp_limit`, `MDBX_opt_spill_max_denominator`, `MDBX_opt_spill_min_denominator` и была запланирована давно, но откладывалась так как требовала других изменений. - В API добавлены функции `mdbx_limits_valsize4page_max()` и `mdbx_env_get_valsize4page_max()` возвращающие максимальный размер в байтах значения, которое может быть размещена в одной large/overflow-странице, а не последовательности из двух или более таких страниц. Для таблиц с поддержкой дубликатов вынос значений на large/overflow-страницы не поддерживается, поэтому результат совпадает с `mdbx_limits_valsize_max()`. - В API добавлены функции `mdbx_limits_pairsize4page_max()`и `mdbx_env_get_pairsize4page_max()` возвращающие в байтах максимальный суммарный размер пары ключ-значение для их размещения на одной листовой страницы, без выноса значения на отдельную large/overflow-страницу. Для таблиц с поддержкой дубликатов вынос значений на large/overflow-страницы не поддерживается, поэтому результат определяет максимальный/допустимый суммарный размер пары ключ-значение. - Реализовано использование асинхронной (overlapped) записи в Windows, включая использования небуфферизированного ввода-вывода и `WriteGather()`. Это позволяет сократить накладные расходы и частично обойти проблемы Windows с низкой производительностью ввода-вывода, включая большие задержки `FlushFileBuffers()`. Новый код также обеспечивает консолидацию записываемых регионов на всех платформах, а на Windows использование событий (events) сведено к минимум, одновременно с автоматических использованием `WriteGather()`. Поэтому ожидается существенное снижение накладных расходов взаимодействия с ОС, а в Windows это ускорение, в некоторых сценариях, может быть кратным в сравнении с LMDB. - Добавлена опция сборки `MDBX_AVOID_MSYNC`, которая определяет поведение libmdbx в режиме `MDBX_WRITE_MAP` (когда данные изменяются непосредственно в отображенных в ОЗУ страницах БД): * Если `MDBX_AVOID_MSYNC=0` (по умолчанию на всех системах кроме Windows), то (как прежде) сохранение данных выполняется посредством `msync()`, либо `FlushViewOfFile()` на Windows. На платформах с полноценной подсистемой виртуальной памяти и адекватным файловым вводом-выводом это обеспечивает минимум накладных расходов (один системный вызов) и максимальную производительность. Однако, на Windows приводит к значительной деградации, в том числе из-за того что после `FlushViewOfFile()` требуется также вызов `FlushFileBuffers()` с массой проблем и суеты внутри ядра ОС. * Если `MDBX_AVOID_MSYNC=1` (по умолчанию только на Windows), то сохранение данных выполняется явной записью в файл каждой измененной страницы БД. Это требует дополнительных накладных расходов, как на отслеживание измененных страниц (ведение списков "грязных" страниц), так и на системные вызовы для их записи. Кроме этого, с точки зрения подсистемы виртуальной памяти ядра ОС, страницы БД измененные в ОЗУ и явно записанные в файл, могут либо оставаться "грязными" и быть повторно записаны ядром ОС позже, либо требовать дополнительных накладных расходов для отслеживания PTE (Page Table Entries), их модификации и дополнительного копирования данных. Тем не менее, по имеющейся информации, на Windows такой путь записи данных в целом обеспечивает более высокую производительность. - Улучшение эвристики включения авто-слияния записей GC. - Изменение формата LCK и семантики некоторых внутренних полей. Версии libmdbx использующие разный формат не смогут работать с одной БД одновременно, а только поочередно (LCK-файл переписывается при открытии первым открывающим БД процессом). - В `C++` API добавлены методы фиксации транзакции с получением информации о задержках. - The `Big Foot` feature which significantly reduces GC overhead for processing large lists of retired pages from huge transactions. Now _libmdbx_ avoid creating large chunks of PNLs (page number lists) which required a long sequences of free pages, aka large/overflow pages. Thus avoiding searching, allocating and storing such sequences inside GC. - Improved hot/online validation and checking of database pages both for more robustness and performance. - New solid and fast method to latch meta-pages called `Troika`. The minimum of memory barriers, reads, comparisons and conditional transitions are used. - New `MDBX_VALIDATION` environment options to extra validation of DB structure and pages content for carefully/safe handling damaged or untrusted DB. - Accelerated ×16/×8/×4 by AVX512/AVX2/SSE2/Neon implementations of search page sequences. - Added the `gcrtime_seconds16dot16` counter to the "Page Operation Statistics" that accumulates time spent for GC searching and reclaiming. - Copy-with-compactification now clears/zeroes unused gaps inside database pages. - The `C` and `C++` APIs has been extended and/or refined to simplify using `wchar_t` pathnames. On Windows the `mdbx_env_openW()`, ``mdbx_env_get_pathW()`()`, `mdbx_env_copyW()`, `mdbx_env_open_for_recoveryW()` are available for now, but the `mdbx_env_get_path()` has been replaced in favor of `mdbx_env_get_pathW()`. - Added explicit error message for Buildroot's Microblaze toolchain maintainers. - Added `MDBX_MANAGE_BUILD_FLAGS` build options for CMake. - Speed-up internal `bsearch`/`lower_bound` implementation using branchless tactic, including workaround for CLANG x86 optimiser bug. - A lot internal refinement and micro-optimisations. - Internally counted volume of dirty pages (unused for now but for coming features). Исправления: ------------ - Поправлен экспорт из DSO/DLL устаревших функций, которые заменены на inline в текущем API. - Устранено использование неверного компаратора при создании или пересоздании `MainDB` с флагами/опциями предполагающим использование специфического компаратора (не по-умолчанию). - Добавлено ограничение размера отображения при коротком read-only файле, для предотвращения ошибки ERROR_NOT_ENOUGH_MEMORY в Windows, которая возникает в этом случае и совсем не информативна для пользователя. - Произведен рефакторинг `dxb_resize()`, в том числе, для устранения срабатывания assert-проверки `size_bytes == env->me_dxb_mmap.current` в специфических многопоточных сценариях использования. Проверка срабатывала только в отладочных сборках, при специфическом наложении во времени читающей и пишущей транзакции в разных потоках, одновременно с изменением размера БД. Кроме срабатывание проверки, каких-либо других последствий не возникало. - Устранена проблема в `put(MDBX_UPSERT+MDBX_ALLDUPS)` для случая замены всех значений единственного ключа в subDb. В ходе этой операции subDb становится полностью пустой, без каких-либо страниц и именно эта ситуация не была учтена в коде, что приводило к повреждению БД при фиксации такой транзакции. - Устранена излишняя assert-проверка внутри `override_meta()`. Что в отладочных сборках могло приводить к ложным срабатываниям при восстановлении БД, в том числе при автоматическом откате слабых мета-страниц. - Изменение размера отображения если это требуется для сброса данных на диск при вызове `mdbx_env_sync()` из параллельного потока выполнения вне работающей транзакции. - Исправление регресса после коммита db72763de049d6e4546f838277fe83b9081ad1de от 2022-10-08 в логике возврата грязных страниц в режиме `MDBX_WRITEMAP`, из-за чего освободившиеся страницы использовались не немедленно, а попадали в retired-список совершаемой транзакции и происходил необоснованный рост размера транзакции. - Устранение SIGSEGV или ошибочного вызова `free()` в ситуациях повторного открытия среды посредством `mdbx_env_open()`. - Добавление подсчета грязных страниц в `MDBX_WRITEMAP` для предоставления посредством `mdbx_txn_info()` актуальной информации об объеме изменений в процессе транзакций чтения-записи. - Never use modern `__cxa_thread_atexit()` on Apple's OSes. - Don't check owner for finished transactions. - Fixed typo in `MDBX_EINVAL` which breaks MingGW builds with CLANG. Более полная информация в [списке изменений libmdbx](https://gitflic.ru/project/erthink/libmdbx/blob?file=ChangeLog.md&branch=master). 51 files changed, 24173 insertions(+), 14452 deletions(-) Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
Этот тег не содержит заметок к релизу