V8 隐藏 类 和 JSON.parse() 将对象 属性 从字符串转换为日期

V8 Hidden Classes and JSON.parse() converting object property from string to Date

我有一个 REST 端点,它 returns 大型数组(100K+ 元素),其对象的属性包含 ISO 格式的日期(如 2021-08-08T10:48:39.637Z),我需要将它们解析为 Date 类型。

我目前有类似的东西:

const res = await fetch(...);
const json = await res.json();
for (let x of json.arr) {
  x.d = new Date(x.d);
}

我担心这会扰乱 V8 Hidden Classes 以及 [=16= 的类型更改(字符串 => 日期),从而导致一些不必要的缓慢] 属性.

我读到 here 更改 属性 类型会扰乱 V8 内部优化:

Changing the property or element type typically causes V8 to create a different HiddenClass which can lead to type pollution which prevents V8 from generating optimal code.

一种替代方法可能是将 JSON.parse()revival() 参数一起使用,它允许根据键名解析值,但我不确定 V8 在这个和与我目前所做的相比有什么不同吗?

  const json = JSON.parse(txt, (key, val) => {
    if (key === "d") {
      return new Date(val);
    }
    return val;
  });

另一种方法可能是重新映射从 await res.json() 返回的对象,如

const json = await res.json();
const objArr = json.map(x => ({ ...x, d: new Date(x.d) }));

使用这种方法,我担心克隆 100K+ 对象的开销,它们是否都具有相同的 V8 隐藏 Class?

我不关心 JSON.parse() 性能本身,只担心由于 属性 类型更改为 Date 而弄乱 V8 Hidden Classes 或弄乱一些内部优化。这是一个庞大的对象数组,性能对于这个 WebApp 来说非常重要,所以我想确保我没有犯任何大错误。

考虑到 V8 优化,解析日期类型的最有效方法是什么?

(此处为 V8 开发人员。)

没关系,只要写出有意义的代码,让引擎去操心让它变快。您目前的做法没有任何问题。

此外,如果事实证明编写某些代码的最明显方法并不是 运行 尽其所能,那么我们的工作就是解决这个问题;我们不希望 JavaScript 开发人员必须通过扭曲来解决引擎缺陷。

is there even a difference compared to what I'm doing currently

一般来说,要确定两种(或多种)方法中哪一种更好,以及是否存在差异,唯一的方法是同时实施和衡量。当你这样做时,一定要使用真实的数据,最好是你自己的完整生产应用程序,或者它的 snapshot/simulation。仅包含几行的简化微基准测试通常会产生误导(即:它们似乎告诉您的内容与您将在完整应用程序中看到的效果无关,甚至可能相反),因为通常会显着简化场景改变引擎将在引擎盖下做出的决定。您可能会想“但是在我的完整应用程序中,我不会看到这么小的细节的影响”——好吧,如果是这样,那么这就是您的答案:没关系。