1

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

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

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

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

4

1 回答 1

2

V8 支持堆快照就是为了这个目的。例如,Atom 编辑器使用它来缩短启动时间。与其说是预编译,不如说是预编译你的全局环境和实例化你的函数(可能还没有编译,只是转换为Ignition的字节码,这就足够了)。如果您使用的是 Electron,mksnapshotnpm 包可能很有用。(如果没有,看看它是如何工作的可能仍然有用。)

我没有做过任何 V8 黑客攻击,但他们从上面的博客文章中链接的示例如下:

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();
}

那篇博文(以及相关的例子?)是从 2015 年开始的,所以从那以后事情可能已经发生了变化。

于 2021-01-18T11:19:14.693 回答