Skip to content

Latest commit

 

History

History
27 lines (22 loc) · 2.54 KB

mistakes.md

File metadata and controls

27 lines (22 loc) · 2.54 KB

踩坑总结

最初的想法

  1. 最开始写的时候,,只想着实现数据增删查改就行了,当时还在想,lowdb不会也这么简单实现的吧,没考虑到性能问题,采用readFile直接读取整个文件到内存里,当我用一个500m的json文件测试时,node读取最少需要阻塞4s。读取一个1.2g左右的json测试时,最少需要阻塞9s,这简直太操蛋了!
  2. 然后就想到了,文件这么大,我能不能只读取我需要的内容到内存了呢?

踩坑1

  1. 突然想到网络io在传输大文件时会分片传输,而文件io也有分片读写的操作,就准备试一试了。
  2. 虽然read方法支持读取指定字节位置的数据,但是当我读取的时候,我咋知道读取那段数据呢?这尼玛存的都是字符串,我想操作的可是json对象啊!gg。。。

踩坑2

  1. 换一种思路,如果能有一个索引文件,提供了源db数据的key和value所在的字节区间,岂不是美滋滋?
  2. 关键这个自动生成map的方法卡了一个多小时,最终通过傻瓜式的纯字符串索引实现啦,跪求一位正则大佬帮忙实现。。。正则才是正义!
  3. 到此,只要有了map文件后,我们就可以读取部分字节数据到内存里,但是如果开发者初始化一个超级超级大的json咋搞?1个多g那种!
  4. 慌的一批的我赶紧用一个400m的json来试试,gg,200m,gg,40m,js内存栈终于不崩溃了,泪奔~
  5. 经过仔细查看,原因出在自动生成map的方法中,因为需要遍历整个db文件的对象,成千上万个key啊,成千山万个for循环,这谁顶得住啊~

踩坑3

  1. 痛定思痛,jsonDb只支持插件生成的db文件,这样就限制了初始化时超大的内存消耗。
  2. 既然读取了部分字节到内存里,那内存里操作的肯定也只是这一部分数据,当调用write方法时,最理想的是,db文件只重写被改变的这部分io。
  3. fs提供的所有写入方法只支持,完全覆盖写入,文件尾部插入写入和截取字节。gg。。。
  4. 猛然一想,c操作io也是这样,看来是操作系统对io操作的限制,这样一来,就没发分片写入了。

踩坑4

  1. 纠结了一个晚上,决定使用完全覆盖写入和文件尾部插入写入组合的方式来解决这个问题。
  2. 其实相当于对整个db和map文件重写了一遍,内心很慌会不会js栈又down了~
  3. 还是很慌重写超大的db和map时,会阻塞很久,只好分批读取很小的字节,依次写入。