Полка записывает на диск при каждом изменении?

Я хочу использовать shelve в асинхронной программе и боюсь, что каждое изменение приведет к остановке основного цикла событий.

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

Как часто полка синхронизируется с диском? Это операция блокировки? Мне нужно вызвать .sync()?

Если я запланирую запуск sync() в другом потоке, другая задача asyncio может одновременно изменить полку, что нарушает требование однопоточной записи.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
0
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Он записывает на диск каждый раз, когда вы обновляете сам объект shelve. Так что если вы это сделаете

shelf[key] = something

или

shelf.update(somedict)

он будет писать в файл.

Однако если в словаре есть изменяемые значения, их изменение не приведет к записи в файл. Объекты в Python не имеют обратной ссылки на контейнеры, которые ссылаются на них, поэтому объект полки не может обнаружить эти изменения и записать файл. Если вам необходимо поддерживать изменяемые значения в словаре, вам следует использовать опцию writeback=True при создании полки, чтобы создать кеш в памяти; файл будет обновляться всякий раз, когда вы sync() или close().

Ответ принят как подходящий

shelve по умолчанию поддерживается модулем dbm, который, в свою очередь, поддерживается некоторой dbm реализацией, доступной в системе. Ни модуль shelve, ни модуль dbm не предпринимают никаких усилий для минимизации количества операций записи; присвоение значения ключу каждый раз вызывает запись. Даже если writeback=True, это просто означает, что новые задания помещаются в кеш и немедленно записываются в резервную копию dbm; они записываются, чтобы убедиться, что исходное значение существует, и запись в кэше делается, потому что назначенный объект может измениться после присвоения, и с ним нужно обращаться так же, как со только что прочитанным объектом (это означает, что он будет записан снова при sync или close г, на случай, если оно изменится).

Хотя возможно, что некоторые реализации базовых библиотек dbm могут включать в себя некоторое кэширование, AFAICT, большинство из них пытаются записывать немедленно (то есть немедленно отправлять данные в ядро ​​без буферизации в пользовательском режиме), они просто не обязательно вызывают немедленную синхронизацию диск (хотя его можно запросить, например, с помощью gdbm_sync).

writeback=True сделает ситуацию еще хуже, потому что когда это произойдет sync, это потребует серьезных усилий (он буквально перезапишет каждый объект, прочитанный или записанный в БД с момента последнего sync, потому что у него нет возможности узнать, какой из них мог быть изменен), поскольку в отличие от небольших усилий по переписыванию одной пары ключ/значение за раз.

Короче говоря, если вас действительно беспокоит блокировка записи, вы не можете использовать асинхронный код без потоков без потенциальной блокировки, но указанная блокировка, скорее всего, будет кратковременной, пока writeback=True не задействован (или пока вы этого не сделаете sync /close до тех пор, пока соображения производительности не перестанут быть актуальными). Если вам нужно иметь по-настоящему неблокирующее асинхронное поведение, все взаимодействия shelve должны происходить при блокировке в рабочих потоках, и либо writeback должно быть False (во избежание сбора данных в условиях гонки), либо, если writeback есть True, вы должны позаботиться о том, чтобы чтобы избежать изменения любого объекта, который может находиться в кеше во время sync/close.

В качестве примечания: модуль shelve не является удаленно потокобезопасным (механизм, лежащий в основе sync, состоит в том, чтобы установить writeback на False, повторить все назначения, а затем снова установить его на True, что означает, что все, что пишется после начала sync, будет записано. но не кэшируется, поэтому защита writeback на него не влияет), поэтому блокировка будет важна в любом многопоточном сценарии.

ShadowRanger 09.08.2024 00:47

Буферизация пользовательского режима была именно моим вопросом, и мне было интересно, кэширует ли какая-либо библиотека dbm эти операции. Спасибо за подробный ответ. Похоже, мне придется создать блокировку MRSW и с таким же успехом опубликовать ее с открытым исходным кодом.

Bharel 09.08.2024 00:58

Другие вопросы по теме