研究 V8 比较多,也关注了一下 vscode 和 atom 的性能,每次 vscode、atom 的 change log 我都会看一遍。印象最深的是 vscode 1.14 的一次更新日志,doApplyEdits Lines inserted using splice · Issue #351 · Microsoft/monaco-editor:不要在循环中使用 splice。

300+倍的差距。

在之前 vscode 还有一次很大的性能提升,在版本 1.9 的时候,改进了语法高亮的算法。

语法高亮的过程通常分为 2 个阶段(tokenization 和 render):先将源码分割为 token,然后使用不同的主题对分割后的 token 进行着色。

tokenization 的过程是:从上到下逐行运行。tokenizer 在行的末尾存储一些状态,在 tokenize 下一行时会用到这些状态。这样,在用户进行编辑时仅需要重新 tokenize 行的一小部分,而不需要扫描整个文件内容。

还有一种情况是当前行的输入会影响到后面(甚至是前面)的行,这时会用到结束状态:

在 1.9 之前的版本,vscode 如何 tokenization 呢?

比如上面的代码:

在 vscode 种这样存储:

tokens = [

{ startIndex: 0, type: 'keyword.js' },

{ startIndex: 8, type: '' },

{ startIndex: 9, type: 'identifier.js' },

{ startIndex: 11, type: 'delimiter.paren.js' },

{ startIndex: 12, type: 'delimiter.paren.js' },

{ startIndex: 13, type: '' },

{ startIndex: 14, type: 'delimiter.curly.js' },

]

{ startIndex: 0, type: 'keyword.js' } 表示从 0 开始的 token 是一个 keyword。

VSCode 团队在博客种指出这在 Chrome 中占据 648 个字节,因此存储这样的对象在内存方面的代价非常高(每个对象实例必须保留指向其原型的空间,以及其属性列表等)。为 15 个字符存储 648 字节是不可接受的。

所以,vscode 使用二进制来存储token:

// 0 1 2 3 4

map = ['', 'keyword.js', 'identifier.js', 'delimiter.paren.js', 'delimiter.curly.js'];

tokens = [

{ startIndex: 0, type: 1 },

{ startIndex: 8, type: 0 },

{ startIndex: 9, type: 2 },

{ startIndex: 11, type: 3 },

{ startIndex: 12, type: 3 },

{ startIndex: 13, type: 0 },

{ startIndex: 14, type: 4 },

]

和上面的表示法相比,只是把 type 由字符串变成了数字,本质上并没有节约太多的内存。但是别着急,vscode 还有黑科技。

我们都知道 JavaScript 使用 IEEE-754 标准存储双精度浮点数,尾数为 53bit。能够在不丢失精度的情况下处理的最大整数为 2^53-1。因此 vscode 使用其中的 48big 进行编码:使用 32bit 来存储 startIndex,16bit 来存储type。 于是上面的对象在 vscode 种被存储为:

tokens = [

// type startIndex

4294967296, // 0000000000000001 00000000000000000000000000000000

8, // 0000000000000000 00000000000000000000000000001000

8589934601, // 0000000000000010 00000000000000000000000000001001

12884901899, // 0000000000000011 00000000000000000000000000001011

12884901900, // 0000000000000011 00000000000000000000000000001100

13, // 0000000000000000 00000000000000000000000000001101

17179869198, // 0000000000000100 00000000000000000000000000001110

]

每个数字是 64bit(8字节),一共是 7 个数字,存储这些元素一共需要 7*8 = 56 字节,再加上数组的额外开销共需要 104 个字节,只有之前的 648 字节的 1/6。

而主题的渲染则用到了 Trie 数据结构。

这个学过《数据结构》的都懂,算不上奇技淫巧,就不展开了。

这一切都是 2017 年 3 月发布的 vscode 1.9。

而今年 3 月,vscode 又重写了 Text Buffer。用户使用编辑器,大部分时间就是写新代码,改旧代码,说到底还是对 text 进行编辑。

对于高性能的文本操作,vscode 最初尝试使用 C++ 进行编写,毕竟 C++ 的性能要比 JavaScript 高出不少,但是事实却不够理想,使用 C++ 确实节约了内存,但是在使用 C++ 模块时,需要在 JavaScript 和 C++ 之间往返数次,这大大减慢了 vscode 的性能。

vscode 团队从 Vyacheslav Egorov 的一篇文章 Maybe you don't need Rust and WASM to speed up your JS 收到了启发,如何充分压榨 V8 引擎的性能。mrale.ph 的博客我几乎每篇都看,非常经典,也非常难懂 。

大多编辑器都是基于行的。程序员逐行编写代码,编译器提供基于行的反馈信息,堆栈跟踪包含行号,tokenization 引擎逐行运行…… 在 vscode 的早期版本中也是直接把每行代码作为字符串存储在数组中。

但是这种方式存在一些问题:

无法打开大文件,因为把所有内容读入数组中可能导致内存不足。

即使文件不大,但是行数太多也无法打开。例如,一个用户无法打开一个 35 MB 的文件。根本原因是该文件的行数太多,1370 万行。引擎将为ModelLine每行和每个对象使用大约 40-60 个字节,因此整个数组使用大约 600MB 内存来存储文档。也就是说打开这个 35M 的文件需要 600M 的内容,20 倍啊!!!

另一个问题就是速度。为了构建这个数组,必须通过换行符分割内容,以便每行获得一个字符串对象。

于是 vscode 开始寻找新的数据结果,最终选择了 Piece table。不知道为什么这么晚才选择 piece table,要知道在微软的 office word 中早就已经使用了 piece table。我也是在一次 Java 读取 word 的 jar 包源码中第一次知道的 piece table 数据结构。

推荐几篇延伸阅读的文章:

目前主要的三种编辑方式有 gap buffer, rope, piece table。

最近用 Atom 少了。

上一次让我兴奋的地方是:The State of Atom's Performance。在2017年6月 Atom 使用了 piece table 数据结构,使用 C++ 重新实现了 text buffer:Atom's new concurrency-friendly buffer implementation。比 vscode 还要早半年,但是为什么还是这么慢呢???

Atom 使用 V8 的自定义快照(snapshot)提升启动性能,最终删除了影响性能的 jQuery 和自定义 element。就连 V8 的

Atom 还更新了 DOM 渲染的方式:A new approach to text rendering,而这个新算法包括一个类似 React 的 vdom,从 issue 来看这是一个大工程啊,包含了近 100 个 task

经过一系列优化,官方说道:

we made loading Atom almost 50% faster and snapshots were a crucial tool that enabled some otherwise impossible optimizations.

我们使 Atom 快了 50%,snapshot 功不可没。(PS:我一定是使用了假的 Atom)

不过 snapshot 确实是 V8 的神器,Nodejs 也看到了 Atom 的成果,于 2017-11-16 开了 issue :speeding up Node.js startup using V8 snapshot · Issue #17058 · nodejs/node。这在我之前的专栏里面有介绍:Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍。

最近一次关注 Atom 是 atom/xray。知乎上也有相关的讨论,atom 开发的下一代编辑器(莫非已经定义 atom 为上一代编辑器了吗)。大概就是一种“大号废了,开小号重练”的感觉。

值得学习的地方是 text 处理使用 copy-on-write CRDT:

如果一直关注 Atom,对于 CRDT 应该不会陌生。Atom 的多人实时共同编辑插件 https://teletype.atom.io/ 就是使用的 CRDT。

CRDT 全称:Conflict-Free Replicated Data Types,强行翻译过来就是“无冲突可复制数据类型”。

CAP定理:在分布式系统中,最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项。

很多分布式系统都舍弃了C(一致性):允许可以在某些时刻不一致,转而求其次要求系统满足最终一致性。这也是目前很多 nosql 数据库追求的方式(另一种是传统的符合 ACID 特性的数据库系统,放弃了A(可用性),这种系统称为强一致性)。

而在最终一致性分布式系统中,一个最基本的问题就是,应该采用什么样的数据结构来保证最终一致性? 答案就是 CRDT。

这篇文章只是一个提纲,里面的每个知识点都可以展开了讲上三天三夜。

atom对比 vscode_VS Code、ATOM这些开源文本编辑器的代码实现中有哪些奇技淫巧?...相关推荐

  1. 在mac上用文本编辑器写python_Mac开源文本编辑器CotEditor

    coteditor for mac版是一款适用于macOS系统的轻量级文本编辑器,可以用于编辑纯文本文件,如网页(HTML,CSS),程序源代码(Python,Ruby,Perl等),结构化文本(Ma ...

  2. linux atom编辑器下载,Atom 1.7.0 发布下载,跨平台开源文本编辑器

    Atom 1.7.0 发布下载,作为目前全球范围内影响力最大的代码仓库/开源社区,GitHub 的程序员们并不满足于此.他们使用目前最先进流行的技术重新打造了一款称为"属于21世纪" ...

  3. Atom - 介绍和使用方法(好用的文本编辑器,代码提示高亮、Markdown)

    一,Atom介绍 Atom 是 Github 开源的文本编辑器,这个编辑器完全是使用Web技术构建的(基于Node-Webkit).启动速度快,提供很多常用功能的插件和主题,可以说Atom已经足以胜任 ...

  4. 【程序源代码】开源文本编辑器Notepad--

    " 关键字:  "小程序" 01 ---- [总体介绍] 使用C++编写的文本编辑器Notepad-- 可以支持Win/Linux/Mac平台.我们的目标是要替换Note ...

  5. 基于qtc++设计文本编辑器的代码_文本编辑器Vim/Neovim被曝任意代码执行漏洞,Notepad:兄弟等你好久了...

    犹记前些日子,微软的记事本文本编辑器爆出了本地代码执行漏洞. Google Project Zero研究员Tavis Ormandy宣布在微软的记事本文本编辑器中发现代码执行漏洞. 可以看见,他在no ...

  6. Notepad++免费开源文本编辑器

    原文链接:http://www.xiongmaoi.com/notepad-free-open-source-text-editor.html Notepad++是一套非常有特色的自由软件的纯文字编辑 ...

  7. linux系统atom安装教程,Ubuntu/Linux Mint上安装Atom文本编辑器

    Atom是一款由Github开发的开源文本编辑器,虽然目前该软件依然在Beta阶段,但我们依然可以在你的Ubuntu/Linux Mint上使用它. 据Atom官方博客介绍,与Atom类似的编辑器Su ...

  8. 文本编辑器_国外程序员最爱的5种文本编辑器

    文本编辑器的选择是很多初学编程者在学习编程时需要考虑的问题之一,当前IT行业应用开发平台软件较多,可供程序员选择的文本编辑器类型较多,但是一个好的文本编辑器能够提高程序工作的效率,达到事半功倍的效果. ...

  9. 如何为JavaScript选择文本编辑器

    by Ayo Isaiah 通过Ayo Isaiah 如何为JavaScript选择文本编辑器 (How to choose a text editor for JavaScript) If you' ...

最新文章

  1. module 'scipy.misc' has no attribute 'imresize'
  2. 什么是公网IP、内网IP和NAT转换?
  3. 给转型做技术的同学的一些建议
  4. 5G同步信号(PSS/SSS)及其时频资源
  5. Hibernate性能提升
  6. jop怎么读音英语怎么说_“春晚”英语怎么说?
  7. 数据库 | OMIM (在线人类孟德尔遗传)数据库简介
  8. POJ 1325 Machine Schedule(zoj 1364) 最小覆盖数
  9. java复习即基础知识点 思维导图
  10. php加入语音播报功能_微信收付款怎么设置语音播报
  11. 【杂谈】MacPro 2015款拆机清灰换导热硅脂实录
  12. ce修改植物大战僵尸之植物无冷却
  13. 微信公众号,JS-SDK获取位置信息,并调起第三方地图App导航
  14. oracle 修改lsnrctl,lsnrctl oracle 监听器 命令行
  15. 剪切后的文件可以恢复吗?恢复剪切文件怎么办?
  16. 迅雷9远程服务器,迅雷9【搞定方式】
  17. 中国制冷剂市场供需调研与投资竞争力分析报告2022-2028年
  18. python文本txt处理
  19. “专利费用减缓”怎么申请?
  20. 取模是什么意思python_原来Python中的取模运算方法竟然是这样的!

热门文章

  1. 算算奖学金(洛谷P1051题题解,Java语言描述)
  2. 【数据结构与算法】顺序栈的Java实现
  3. 管理软件实施(2)——开发包括哪些成本
  4. 基于套接字SOCKET的及时聊天
  5. jenkins——部署java项目(2)
  6. U-Time巡回完美收官:精细化数据将主导未来运营趋势(数据应用篇)
  7. Sublime text3装入插件Anaconda
  8. datagrid——jQuery EasyUI
  9. Indent Guides for Visual Studio 代码格式化收缩插件
  10. objective-c 语法快速过(4)