发现问题
在迭代🤖yuè - Web 阅读器漫画阅读能力时,我发现在翻页的时候,硬盘的读写直接被拉满了
我很自然的想到是indexedDB的问题,在翻页的时候阅读器会记录阅读进度写入其中,代码片段如下:
const updateProcess = useCallback(
async () => {
// ...
await fs.updateBook({
hash,
info: delFalsy({
readProgress,
}),
});
// ...
},
[book],
);
我尝试注释掉了该段代码然后翻页,硬盘非常安静,问题定位成功
出现原因
我在数据库中构建了一张表,用来存储图书和其阅读进度,表结构如下:
type BookTable = Table<{
hash: string;
file: File;
cover: Blob;
readProgress: {
value: string;
percent: number;
}
}>
在上面代码中,我仅仅只更新了 readProgress
却产生了大量的 I/O,于是我推测它在更新 readProgress
的同时,也重新写入了其他字段,例如 file
和 cover
,它两的开销会很大
一开始我以为是Dexie.js的问题,提了一个issue,维护者也回答了我的问题,告诉我这其实取决于浏览器的实现:
“That is down to the implementation of IndexedDB in the browser.”
经过测试,我发现 safari (VMware macOS13)
, firefox (Windows11)
, edge (Windows11)
都是这样干的
解决方法
没办法,只能通过抽离 Blob
对象到一个新表中来解决它,维护者也是这样建议的:
“A doable workaround would be to store the blobs in a different table and refer to the id of the stored content (like a foreign key)”
更新后数据库中 books
表不再存储文件内容:
文件内容和其它尺寸较大的对象都放到了 bookContents
里面:
还有点问题
这里其实应将
cover
单独拆分出来,加载图书列表时没必要也同时加载图书的内容,只需要封面即可2023-07-05更新:
已在v1.6.1中改进