Node.js 和 v8 专家的问题。
我正在开发Siesta测试工具的新版本。
默认情况下,Siesta 在新创建的 Node.js 进程中运行每个测试。但是,我想避免产生新进程的开销,而是提供在空 JavaScript 上下文中运行测试的能力。
可以使用内置的vm模块创建此类上下文。但是,以这种方式创建的上下文是一个空的JavaScript上下文,而不是一个空的Node.js上下文。例如,它没有全局变量process:
> require('vm').runInNewContext('process')
evalmachine.<anonymous>:1
process
^
Uncaught ReferenceError: process is not defined
at evalmachine.<anonymous>:1:1
at Script.runInContext (vm.js:143:18)
at Script.runInNewContext (vm.js:148:17)
at Object.runInNewContext (vm.js:303:38)
at REPL30:1:15
at Script.runInThisContext (vm.js:133:18)
at REPLServer.defaultEval (repl.js:484:29)
at bound (domain.js:413:15)
at REPLServer.runBound [as eval] (domain.js:424:12)
at REPLServer.onLine (repl.js:817:10)
>
Run Code Online (Sandbox Code Playgroud)
所以问题是 - 在同一进程中创建一个新的和空的 Node.js 上下文的最佳方法是什么?我期望这样的背景下都定期全局,如process,require等此外,我预计这种情况下有一个单独的,最初空模块高速缓存,这样即使有些模块在主背景加载,这将是在新的上下文中再次加载。
当然,我可以将全局变量从主上下文映射到新上下文,但这意味着这些全局变量在上下文之间共享,而我的目标是上下文隔离。此外,模块缓存也将被共享。
我相信 JavaScript 和 Node.js 上下文之间的区别在于后者是用某个脚本初始化的。是否有可能以某种方式获取该脚本的来源并在新的上下文中执行它? …
我很高兴Map在我的 JavaScript 代码库中使用索引访问,但我刚刚偶然发现了这个基准:https ://stackoverflow.com/a/54385459/365104
我也在这里重新创建了它: https: //jsben.ch/HOU3g
benchmark 所做的基本上就是用 1M 个元素填充一个映射,然后迭代它们。
我希望 Map 和 Object 的结果是相同的,但它们有很大不同 - 有利于 Object。
这是预期的行为吗?可以解释一下吗?是因为订购要求吗?或者因为map正在做一些键散列?或者只是因为 Map 允许任何对象作为键(我希望它使用指针地址作为键,这不需要任何哈希)?Map 和 Object 索引算法有什么区别?
这是非常出乎意料和令人沮丧的 - 基本上我将不得不恢复到老式的“对象作为地图”编码风格。
更新#1
正如评论中所建议的,对象可能会优化为数组(因为它是从零开始的整数索引)。
将迭代顺序从sizeto 0-Object更改为快 2 倍。当使用字符串作为索引时,Map 的性能提高了 2 倍。
假设 V8 将完全消除死代码(结构如下)是否正确?
export const DEBUG = false
Run Code Online (Sandbox Code Playgroud)
import { DEBUG } from './module1.js'
if (DEBUG) {
// dead code eliminated?
}
Run Code Online (Sandbox Code Playgroud)
请不要评论“‘if’检查的开销非常小,你应该 XXX 而不是问这个问题”。我只是想知道 V8 是否能够做到这一点(是/否,当然最好有一些细节)。