我希望在 asyncio 程序中使用 shelve,但我担心每次更改都会导致主事件循环停顿。
尽管我不介意腌制操作偶尔变慢,但磁盘写入可能会很多。
shelve 多久会同步到磁盘一次?这是一个阻塞操作吗?我必须调用 吗.sync()
?
如果我安排sync()
在不同的线程下运行,不同的 asyncio 任务可能会同时修改搁置,这违反了单线程写入的要求。
我希望在 asyncio 程序中使用 shelve,但我担心每次更改都会导致主事件循环停顿。
尽管我不介意腌制操作偶尔变慢,但磁盘写入可能会很多。
shelve 多久会同步到磁盘一次?这是一个阻塞操作吗?我必须调用 吗.sync()
?
如果我安排sync()
在不同的线程下运行,不同的 asyncio 任务可能会同时修改搁置,这违反了单线程写入的要求。
shelve
默认情况下,由模块支持dbm
,反过来由系统上可用的某些 实现支持。模块和模块都不会努力减少写入;每次将值分配给键都会导致写入。即使在 时,这也只是意味着将新的分配放在缓存中并立即写入支持;它们被写入以确保原始值在那里,并且缓存条目被创建是因为分配的对象在分配后可能会发生变化,需要像处理新读取的对象一样处理(这意味着如果它发生变化,它将在ed 或d时再次写入)。dbm
shelve
dbm
writeback=True
dbm
sync
close
虽然底层
dbm
库的某些实现可能包含一些缓存,但据我所知,大多数确实会尝试立即写入(即,在没有用户模式缓冲的情况下立即将数据推送到内核),它们不一定强制立即同步到磁盘(尽管可以请求,例如使用gdbm_sync
)。writeback=True
会使情况变得更糟,因为当它这样做sync
时,需要付出巨大的努力(它实际上会重写自上次读取或写入数据库的每个对象sync
,因为它无法知道其中哪些对象可能已被修改),而不是一次重写单个键/值对的小努力。简而言之,如果您真的担心阻塞写入,则不能使用没有潜在阻塞的非线程异步代码,但只要
writeback=True
不涉及(或者只要您不sync
/close
它,直到性能考虑不再相关),所述阻塞就可能是短暂的。如果您需要真正的非阻塞异步行为,则所有shelve
交互都需要在工作线程的锁定下进行,并且writeback
必须是False
(以避免竞争条件腌制数据)或者如果writeback
是True
,您必须注意避免在/期间修改可能位于缓存中的任何对象。sync
close
每次更新
shelve
对象本身时,它都会写入磁盘。因此,如果你这样做或者
它将写入文件。
但是,如果字典中的 中有可变值,则修改它们不会触发对文件的写入。Python 中的对象没有任何对引用它们的容器的引用,因此 shelve 对象无法检测到这些更改并写入文件。如果您需要支持字典中的可变值,则应在创建 shelve 时使用选项来创建内存缓存;然后,每当您或 时,
writeback=True
文件都会更新。sync()
close()