You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Myer's Algorithm 是一种用于计算 最长公共子序列(Longest Common Subsequence,LCS)的算法,尤其是用于 文本差异比较(diff)任务中的优化算法。它被广泛应用于版本控制系统(如 Git)中,以高效地找到两个文本之间的差异。
// v8/src/debug/liveedit-diff.ccMyersDiffer(Comparator::Input* input, Comparator::Output* output)
: input_(input),
output_(output),
fr_forward_(input->GetLength1() + input->GetLength2() + 1),
fr_reverse_(input->GetLength1() + input->GetLength2() + 1) {
// Length1 + Length2 + 1 is the upper bound for our work arrays.// We allocate the work arrays once and re-use them for all invocations of// `FindMiddleSnake`.
}
std::optional<Path> FindEditPath() {
returnFindEditPath(Point{0, 0},
Point{input_->GetLength1(), input_->GetLength2()});
}
问题分析
Myer's Algorithm 的时间复杂度为 O(ND), 其中:
N 是第一个序列的长度。
D 是两个序列之间的差异数量(即“编辑距离”)
看到这里有种不好的预感, 看了一下 detail.js 文件的大小, 竟然有 11M ⚠️
➜ src git:(a5f3f617bb) ls -lh /Users/temp/detail.js
total 22568
-rw-------@ 1 duoxiaokai staff 11M 12 1 17:16 detail.js
前情提要
上一篇 Chrome Renderer 进程 CPU 占用 100% 排查 (上) 文章排查了我调试某个详情页时, 每当打开 Chrome Devtool 时页面就立马会卡死的问题。疑似因为开启了
Enable Local Overrides
功能触发了 Chrome 的 bug, 只能暂时关闭了该功能规避了问题代码分析
上一篇文章我们知道了最后卡死时代码的执行堆栈停留在了 FindEditPath 函数, 而卡死时正在 diff 的文件是 detail.js
让我们先分析一下 🧐 FindEditPath 函数的代码, 原来这里是 v8 实现的 Myer's Algorithm
问题分析
Myer's Algorithm 的时间复杂度为 O(ND), 其中:
看到这里有种不好的预感, 看了一下 detail.js 文件的大小, 竟然有 11M⚠️
文件这么大耗时严重貌似解释得通, 严谨一点还是要排查 v8 这里实现的 Myer's Algorithm 是否有性能问题
验证问题
逐行阅读算法的代码寻找优化空间当然最好, 如果你比较擅长算法这块。对于算法渣, 验证问题时确保做到了单一变量法则也能得出正确的结论
此时我通过另外一种语言比如 Node.js 中 Myer's Algorithm 的实现来看看性能表现如何
接着运行
node diff.js
, 然后运行top
命令, 最后发现 CPU 占用也达到了 100%+。到这里基本也排除 v8 实现的 Myer's Algorithm 存在性能问题的可能, 因为不同语言的实现版本对于大文本的输入表现基本一致问题探索
其实我有个疑问, 当用户 Overrides 了文件的内容, 为什么需要 diff 了? 直接读取最新文件的内容不就好了么?
此时我们需要对
v8/src/debug/liveedit-diff.cc
的功能有所了解, liveedit 听上去是实时编辑, 实时生效?为了验证这个问题我随意打开了一个网页比如 taobao.com, 然后随意覆写了一个 JS 内容, 加上了前面的 4行代码
然后你可能想到了, 在不刷新页面的情况下, 把 greet 函数的
console.log("Hello, world!");
改为console.log("Hello, world1!");
, 让我们看看运行的结果v8 实现了用户实时修改函数代码, 热重载了函数的实现, 引用地址没有变化证明了是同一个对象
问题结论
v8 的 liveedit 是基于 Myer's Algorithm 实现了增量热重载 JS 变量的更新, 相比于全量的 JS 内容更新
The text was updated successfully, but these errors were encountered: