js增量更新算法研究

2024-09-01 11:58
文章标签 算法 更新 js 增量 研究

本文主要是介绍js增量更新算法研究,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文链接:https://caelumtian.github.io/2017/09/18/js增量更新算法研究/

serviceWorker 方案 - js增量更新算法研究

调研背景
根据之前 serviceWorker 的调研,当服务端文件更新后,serviceWorker 会做对比,并请求这些新的文件。所有发生变化的文件都会被更新。现在 new-mini 内嵌页面,js 都被压缩成了一个文件。这样每次很小的文件改动,都会导致客户端需要下载整个js文件,这样会造成流量的浪费,同时也对服务器造成过大的流量压力。为此我们需要减少更新文件的体积,来更好的完成 serviceWorker 的架构。

js 增量更新算法
利用增量更新算法,我们大大的降低每次文件变动后传输的大小。这里调研了4中常见的js 增量更新算法:

基于chunk的增量更新算法
首先将旧的文件分成n块并并编号
a.png
然后在新文件上进行,滚动查找。如果找到匹配的则记录块号,如果没找到则块往前移动 1 个字符,并把上个字符压入新数据块,然后扫描下一块,最终得到一个新数据和数据块号的组合的增量文件(这一步可以用上线 JavaScript 时用的打包工具或者请求 JavaScript 服务器程序实时计算出来)。
b.png
最终得到的增量文件如下所示:

1, data1, 2, 3, data2, 4, 5, 6

进一步合并顺序快得到:

[1, 1], data1, [2, 2], data2, [4, 4]

客户端根据旧文件的 chunk 数据和增量更新数据,我们可以得出新版本数据由如下数据组成:

chunk0+data1+chunk1+chunk2+data2+chunk3+chunk4+chunk5

例如以 s = ‘‘1345678abcdefghijklmnopq’ 修改为 a = ‘‘13456f78abcd2efghijklmnopq’为例, 设块长度为4 则, 源文件分成:

通过滚动查找,得到新文件

最终增量文件表示如下数组: [“a=‘1”,2,”f”,3,”cd2ef”,5,6,7]。 进一步合并顺序块,可用一个js数组表示为: [“a=‘1”,[2,1],“f”,[3,1],“cd2ef”,[5,3]。
在 serviceWorker 客户端这边,调用如下函数,进行文件更新:

//source 是上一个版本内容,trunkSize 是块大小,checksumcode 是两个版本间的增量文件数组
var rsyncjs = function(source,trunkSize,checksumcode){
var strResult="";
for(var i = 0; i < checksumcode.length; i++){
var code = checksumcode[i];
if(typeof code === ‘string’){
strResult+=code;
}
else{
var start = code[0] * trunkSize;
var len = code[1] * trunkSize;
var oldcode = source.substr(start, len);
strResult += oldcode;
}
}
return strResult;
}
该方法存在的问题为:增量更新的精确度依赖于chunk的大小,在实际使用中总是会有不少代码需要冗余下载。

Myer’s diff algorithm
Myer’s diff algorithm 首次出是在1986年一篇论文中“An O(ND) Difference Algorithm and Its Variations”, 在文中实现上介绍了两种此diff算法 的实现。两种实现的核心思想是一致的,只是在具体的实现过程中,为进一步提升算法的性能及空间利用率,采取了不一致的迭代方式。
算法原理比较复杂,github 上有根据该算法实现的 jsdiff 插件
简单的演示如下:

require(‘colors’);
let jsdiff = require(‘diff’);
let oldStr = ‘bcdsgaff2 123’;
let newStr = ‘accdgadff2 42356’;
let diff = jsdiff.diffChars(oldStr, newStr);
console.log(diff);
diff.forEach(part => {
let color = part.added ? ‘green’ : part.removed ? ‘red’ : ‘gray’;
process.stderr.write(part.value[color]);
})

{% asset_img 5.png %}  
可以清楚的看到差异信息,这里我们利用下面这个函数 简化一下jsdiff输出信息,方便传输。    
```javascript  
function minimizeDiffInfo(originalInfo){let result = originalInfo.map(info => {if(info.added){return '+' + info.value;}if(info.removed){return '-' + info.count;}return info.count;});return JSON.stringify(result);
}
输出结果为:
6.png
客户端,采用如下函数,更新 serviceWorker 中的资源:function mergeDiff(oldString, diffInfo){let newString = '';let diffInfo = JSON.parse(diffInfo);let index = 0;for(var i = 0; i < diffInfo.length; i++){let info = diffInfo[i];if(typeof info === 'number'){newString += oldString.slice(index, index + info);index += info;continue;}if(typeof info === 'string'){if(info[0] === '+'){let addedString = info.slice(1, info.length);newString += addedString;}if(info[0] === '-'){let removedCount = parseInt(info.slice(1, info.length));index += removedCount;}}}return newString;
}
该方案,实际测试结果很糟糕,对于文件很大的内容比对时间都够我睡一觉了。基于编辑距离的比对算法
什么是编辑距离
编辑距离是针对二个字符串(例如英文字)的差异程度的量化量测,量测方式是看至少需要多少次的处理才能将一个字符串变成另一个字符串。编辑距离可以用在自然语言处理中,例如拼写检查可以根据一个拼错的字和其他正确的字的编辑距离,判断哪一个(或哪几个)是比较可能的字。DNA也可以视为用A、C、G和T组成的字符串,因此编辑距离也用在生物信息学中,判断二个DNA的类似程度。Unix 下的 diff 及 patch 即是利用编辑距离来进行文本编辑对比的例子。求解算法
比如要计算cafe和coffee的编辑距离。cafe→caffe→coffe→coffee。先创建一个6×8的表(cafe长度为4,coffee长度为6,各加2):
8.png
接着,在如下位置添加数字
9.png
从3,3格开始,开始计算。取以下三个值的最小值:如果最上方的字符等于最左方的字符,则为左上方的数字。否则为左上方的数字+1。(对于3,3来说为0)
左方数字+1(对于3,3格来说为2)
上方数字+1(对于3,3格来说为2)
因此为格3,3为0:
10.png
循环操作,推出下表:
11.png
取右下角,得编辑距离为3。

这篇关于js增量更新算法研究的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1126870

相关文章

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

JS 实现复制到剪贴板的几种方式小结

《JS实现复制到剪贴板的几种方式小结》本文主要介绍了JS实现复制到剪贴板的几种方式小结,包括ClipboardAPI和document.execCommand这两种方法,具有一定的参考价值,感兴趣的... 目录一、Clipboard API相关属性方法二、document.execCommand优点:缺点:

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

Linux Mint Xia 22.1重磅发布: 重要更新一览

《LinuxMintXia22.1重磅发布:重要更新一览》Beta版LinuxMint“Xia”22.1发布,新版本基于Ubuntu24.04,内核版本为Linux6.8,这... linux Mint 22.1「Xia」正式发布啦!这次更新带来了诸多优化和改进,进一步巩固了 Mint 在 Linux 桌面

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

Ubuntu 24.04 LTS怎么关闭 Ubuntu Pro 更新提示弹窗?

《Ubuntu24.04LTS怎么关闭UbuntuPro更新提示弹窗?》Ubuntu每次开机都会弹窗提示安全更新,设置里最多只能取消自动下载,自动更新,但无法做到直接让自动更新的弹窗不出现,... 如果你正在使用 Ubuntu 24.04 LTS,可能会注意到——在使用「软件更新器」或运行 APT 命令时,