V8 可以执行 JS 代码的构建时预编译吗?

Can V8 perform build-time precompilation of JS code?

我们正在尝试优化 JS 代码在移动设备上的启动时间并寻找机会。我发现 Facebook Hermes JS engine 是出于类似目的而创建的,但我们目前严重依赖 V8。

构建时预编译是否可以用 V8 完成,意味着解析和代码优化将在编译时完成,并在运行时节省一些时间?从源代码生成 LLVM 位码并在运行时执行位码似乎与我想象的非常接近。 WASM 似乎不是一个选项(至少对于移动设备而言)。

如果可能的话,能否提供一个使用 V8 优化的简单 JS 代码的简单示例?

PS。可能它也有助于内存消耗,这可能是次要目标。

V8 支持 heap snapshots for this very purpose. It's used by the Atom editor, for instance, to improve startup time. It's not so much about precompiling as it is about prebuilding your global environment and instantiating your functions (which may not be compiled [yet], just converted to bytecode for Ignition, which is sufficient). If you're using Electron, the mksnapshot npm package 可能会有用。 (如果没有,看看它是如何工作的可能仍然有用。)

我没有做过任何 V8 hacking,但是 example they link from the blog post above 如下:

TEST(PerIsolateSnapshotBlobs) {
  DisableTurbofan();
  const char* source1 = "function f() { return 42; }";
  const char* source2 =
      "function f() { return g() * 2; }"
      "function g() { return 43; }"
      "/./.test('a')";
  v8::StartupData data1 = v8::V8::CreateSnapshotDataBlob(source1);
  v8::StartupData data2 = v8::V8::CreateSnapshotDataBlob(source2);
  v8::Isolate::CreateParams params1;
  params1.snapshot_blob = &data1;
  params1.array_buffer_allocator = CcTest::array_buffer_allocator();
  v8::Isolate* isolate1 = v8::Isolate::New(params1);
  {
    v8::Isolate::Scope i_scope(isolate1);
    v8::HandleScope h_scope(isolate1);
    v8::Local<v8::Context> context = v8::Context::New(isolate1);
    delete[] data1.data;  // We can dispose of the snapshot blob now.
    v8::Context::Scope c_scope(context);
    CHECK_EQ(42, CompileRun("f()")->ToInt32(isolate1)->Int32Value());
    CHECK(CompileRun("this.g")->IsUndefined());
  }
  isolate1->Dispose();
  v8::Isolate::CreateParams params2;
  params2.snapshot_blob = &data2;
  params2.array_buffer_allocator = CcTest::array_buffer_allocator();
  v8::Isolate* isolate2 = v8::Isolate::New(params2);
  {
    v8::Isolate::Scope i_scope(isolate2);
    v8::HandleScope h_scope(isolate2);
    v8::Local<v8::Context> context = v8::Context::New(isolate2);
    delete[] data2.data;  // We can dispose of the snapshot blob now.
    v8::Context::Scope c_scope(context);
    CHECK_EQ(86, CompileRun("f()")->ToInt32(isolate2)->Int32Value());
    CHECK_EQ(43, CompileRun("g()")->ToInt32(isolate2)->Int32Value());
  }
  isolate2->Dispose();
}

那个博客 post(以及关联的示例?)是 2015 年的,所以事情可能已经发生了变化。