-
Notifications
You must be signed in to change notification settings - Fork 285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
支持原地更新老数据 #36
Comments
尝试了分析“原地更新”,类似于外排序,算法最好情况下应该可以约束到O(n*log(n)), 写入放大系数约20倍左右(因为log(n)); |
核心问题抽象: 将Old文件大小设置为maxSize(Old,New),遍历C数组,将被copy线引用到过的Old数据区域都按现有顺序对齐到文件尾,并更新C中oldPos新值; 假设一共有N块数据要排序,总数据长度S,不断的找到下一块应该排到最前面的new块,与当前要写入的位置的cur块交换,交换min(new,cur)长的数据; 这个算法的性能可能遇到的问题: 1. 每次从新的new块拿数据类似磁盘的随机访问,性能可能比较慢; 2.在迭代过程中,每次操作的数据块可能很小,甚至单字节,访问的额外磁盘代价很大; 对于重排序我现在的另一个思路: 用外排序的败者树的思路,假设可用内存为文件大小的1/M,那M次全文件范围的局部排序就能完成整体排序,也就是O(M*S)的总数据量读写;只要M够小(内存够大),而且因为文件一直是顺序访问,性能应该也还行; |
(不用担心覆盖掉还没有使用到的Old数据),完成后设置当前文件大小为size(new); |
@GTOTA 你可能没有注意到这句“将用到的Old数据区域都按文件尾对齐” |
@sisong 就是不太理解这句话,按文件尾对齐是啥意思,是把两个有重叠的copy数据区做对齐吗 |
同问,确实不清楚,按照文件尾对齐是什么意思,具体是如何实现对齐?求解答 |
解释一下“将用到的Old数据区域都按文件尾对齐” : 就是把Old中的数据看作2类,一类是被copy线引用过的,反之剩下的是无用数据;有用到的这些数据都按现有顺序堆放到文件尾部去。 |
增量更新应该是目标版本只有很少一部分有差异,大部分内容都相同,按照把相同的数据都拷贝到文件尾部的思路,那么,需要空间大小,可能接近于目标文件+原文件的大小,是这样吗? |
“需要空间大小,可能接近于目标文件+原文件的大小” 需要的空间是 max(目标文件,原文件),你再想想 |
终于理解了,感谢大哥 |
感觉原地更新旧文件不太可靠,尤其是手机上, 用户中途关了app,会导致旧文件损坏.得重新下载全量资源 |
当前的实现 create_single_compressed_diff\patch_single_stream ,已经解决了“支持在下载补丁包过程中,就可以开始执行(解压缩和)patch过程,内存占用可控”的问题。 |
作者您好,请问这个意思是支持分段合成了吗? |
“分段合成” 是分几次合成的意思吗? patch_single_stream并不支持,它支持的还是一次性patch,patch过程中可以等待补丁数据陆续下载到本地,不断的和旧数据合成出新数据。 |
是这个意思。也就是说,假如补丁20KB,可以先传10KB,用这10KB合成后,这10KB可以删掉了,再传10KB继续合成对吗? |
“是这个意思。也就是说,假如补丁20KB,可以先传10KB,用这10KB合成后,这10KB可以删掉了,再传10KB继续合成对吗?” “嵌入式设备上flash空间无法同时存放old程序和new程序” "嵌入式设备上" |
好的,感谢! |
作者您好,我目前已经实现了原地更新老数据。做法是在diff.covers.oldPos找出一个最长递增子序列出来,然后把不在此序列的删掉。这样做最然会使diff变大,但这个代价是值得的。 |
|
Would please create a PR? |
|
修改的原地升级版的我上传了 https://github.com/wangchz13/myhdiffpatch |
我有一个类似的使用场景:有一个文件夹(workdir),有一系列的脚本(比如 prog1, prog2,prog3)来操作这里的数据;我想对比一些关键环节间的文件变动,比如 workdir#v2(prog2 处理后的 workdir 状态) 和 workdir#v3 的区别(可以呈现为 1) 文件变动元信息 + 2) 可应用到 #v2 让这个目录变为 #v3 的一个 patch)。 我感觉 dvc (把文件版本控制系统 git 扩展到数据版本控制)应该可以做这个事情,好像 dvc 也是对文件做分块然后用这些块来表达现在的文件(夹)数据。不知道 @sisong 有没有了解过,和 HDiffPatch 有啥异同,各自有什么样的适用场景。 |
对 dvc 没有了解。 |
@wangchz13 |
@jimmy6270 |
hi,原地更新还没有实现吗?从原理上看,似乎需要牺牲压缩率才能实现 |
|
|
确实还有一处:old中如果和new中有文件数据完全一致,就会被排除出diff,这是为了优化diff速度,但可能因此错过一些匹配从而降低压缩率。 |
如果说将所有文件排序后,做一个后缀数组,在执行patch,或许可以提高diff速度?只是在目录文件总体较大时,diff内存消耗也较大。 |
不仅仅是影响diff,还会影响patch流程,因为预先知道文件相同,并且patch到相同old文件夹的时候,可以跳过这些文件。(当然,该影响很好排除掉) ps:完全不推荐再使用bzip2压缩器,推荐用zstd压缩 |
磁盘占用可控:下载的补丁包可能不能存储到磁盘,也需要原地更新老数据;(如果磁盘空间可用,patch执行又很快,那“边下载边patch”的需求不太可能单独存在)
内存占用可控:只下载一部分就开始执行补丁过程,分阶段完成patch过程;
缺点:
The text was updated successfully, but these errors were encountered: