最近在做的项目需要运行用户编写的表达式,在选择运行环境的时候,在熟悉的语言里转了一圈,发现有2种模式可供选择:
支持 async/await 的语言/环境
Node.js
Python 3.5+
支持协程的语言/环境
Python + Gevent
Lua (Luajit) (OpenResty)
Fibjs (基于V8)
无论哪种方案,肯定不会让用户手工写 await,那么为了正确高效的运行,就需要把代码自动添加上 await 。一开始还以为只要给所有的函数调用加上就行了,后来发现,因为 ES 支持 getter,所以可能所有的属性读取都需要加上 await ,那么生成的代码及运行时效率可能都不好看。
// INPUT
`查看 $$`
// RUN
`查看 ${
await
(
(await (getRecentPost()))
.title
)
}${
((await (await getRecentPosts())).length) > 1 ?
` 及更多文章` :
''
}`
鉴于此,开始关注支持协程的方案 (可以隐式的支持 await)。
因为对于 Gevent 和 Lua 都比较熟悉,且更加偏好JS,所以就重点研究了一下 Fibjs 。
一开始以为 Fibjs 内部直接使用了 V8 的 Isolate 来实现 Fiber,看了下 V8 Isolate 的量级: 2.3MB/Isolate 就有点慌 (isolated-vm)。后来实际试了下 Fibjs 的代码,发现远低于这个量: 大概只有 4KB/Fiber。非常好奇其内部原理。找了一圈,发现了这篇: 探究fibjs的异步原理 - Asion。对于理解原理是很有用了。这类东西看起来跟拍电影的时候导演喊"ka",然后换道具、化妆 接着拍很相似。
探究fibjs的异步原理 - Asion: https://asionius.com/article/15
附各环境的内存占用对比:
https://gist.github.com/kindy/7095cd9028996bf0917aafc7fc086db4
# Lua
1.3KB/Thread
# Luajit
0.5KB/Thread
# Fibjs
1.5KB/Fiber
# V8
2.3MB/Isolate
哦对了,知乎里有一篇关于 Fibjs 的讨论,值得一看:
如何评价node-fibers? - 贺师俊的回答 - 知乎 https://www.zhihu.com/question/59441623/answer/168675034
领取专属 10元无门槛券
私享最新 技术干货