没有银弹: LemonVM设计缺陷反省, 以及对未来的展望.

缘起

我在写LemonVM的时候, 第一版采取的Rust语言, 当时想着使用Rust语言至少能够保证在写VM的时候至少是内存安全的,
但是事实告诉我, 在写这种层面的底层大项目的时候, 想要使用静态检查来保证内存安全是不可能的一件事, 尤其是我要写
垃圾回收的前提下, 是不可能保证内存的占用是可以被估算的, 所以我的代码充满了Unsafe, 也丧失了Rust的最大优点之一 — 内存安全

随后, 因为指令集设计失误和过于画大饼, 导致第一版LemonVM根本无法达到可用阶段, 同时因为在我本地的源码已经达到了惊人的1w行的水平, 所以我觉得好好重新设计一下, 所以开始了第二版的征程.

再来一遍

在第二版开始之后, 大幅度的重构了原来的指令集和字节码加载部分, 因为第一版借鉴的LUA的VM, 然而LUA的VM由于LUA语言是
非常非常小的缘故, VM的功能比较少, 同时特别的Trivial, 不能胜任复杂的工作, 于是第二版直接开始借鉴JVM, 但是由于JVM是基于栈的字节码而不是基于寄存器的字节码, 于是我一遍借鉴Dalvik版的执行和JVM的加载模型, 做出了第二版.

通过 @HoshinoTented 和我的示例程序, 发现LemonVM第二版的效率在Python的50x的水准, 这意味着肯定是哪里的开销过于巨大了, 通过查找, 我发现是我在实现的时候大量的使用了堆分配内存和GC的实现过于Naive导致的, 同时还有Rust Iter和Rust 的 Match 对CPU的分支预测起到了非常大的影响导致运行效率奇低无比, 优化的方法有

  • 重写所有指令的实现
  • 所有堆分配手动管理
  • 避免使用Rust的STD
  • 更精细的控制分支流程

第一个因为现在是Prototype阶段,所以可以跳过, 第二个在Rust上近乎不可能, 第三个同样, 第四个由于Rust没有Goto和Label as Var 所以根本就不能控制分支预测, 也不能去手动优化指令的派发.

柠檬上头了

于是柠檬开始 重新设计 重新设计 , 这回直接采用C语言作为开发语言, 的确这四个问题都迎刃而解了, 但是遇到了更大的问题, 开发效率低的离谱, 同时对于性能不敏感的Use case因为C没有STD, 所以我需要自己实现HashTable Vector等这种最基础的数据结构, 这个使得我的工作变得异常的缓慢, 还有一个就是C的构建工具简直…恶心, 同时开了扩展就意味着在某些垃圾MSVC上面无法编译, 这就丢失掉了我跨平台的初衷, 我感到非常的难受, 所以最近在尝试一种新的解决方案, 首先使用Rust做完性能不敏感但是高度依赖标准库的(比如字节码的加载, GC, 线程池等), 然后使用C语言去写核心逻辑的优化(比如指令的分发, CPU的分支预测优化, 寄存器映射, 栈映射等), 因为在X64模式下的Rust拿ASM!去写MOVABSQ还要看编译器脸色我真的做不到.


对未来底层编程语言的展望

冰冰今天兴奋的跟我说, 作为底层编程语言就必须有goto啊, lebel啊, 我现在为止都非常统一, 但是作为高层语言, 就必须有很高级的抽象, 这些抽象有可能会破坏语言的底层特性, 然后我和冰冰都注意到F*语言使用lattice来把语言通过割裂成不同的部分来进行底层操作, 使得我们获得了很大的启发.

Unsafe Rust is NOT UNSAFE enough, Safe Rust is NOT SAFE enough

所以,希望未来能够推出一种语言, 能够可控的调节使用多么底层的特性, 而不是像C艹一样看编译器脸色, 更不是学Rust搞了个不伦不类的Unsafe结果连GOTO都没有.

暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇