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。仅包含几行的简化微基准测试通常会产生误导(即:它们似乎告诉您的内容与您将在完整应用程序中看到的效果无关,甚至可能相反),因为通常会显着简化场景改变引擎将在引擎盖下做出的决定。您可能会想“但是在我的完整应用程序中,我不会看到这么小的细节的影响”——好吧,如果是这样,那么这就是您的答案:没关系。
我有一个 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。仅包含几行的简化微基准测试通常会产生误导(即:它们似乎告诉您的内容与您将在完整应用程序中看到的效果无关,甚至可能相反),因为通常会显着简化场景改变引擎将在引擎盖下做出的决定。您可能会想“但是在我的完整应用程序中,我不会看到这么小的细节的影响”——好吧,如果是这样,那么这就是您的答案:没关系。