如何检查对象 属性 是对象内 属性、快速 属性 还是 v8 中的慢速 属性?
How do I inspect whether a object property is a in-object property, fast property, or slow property in v8?
post https://v8.dev/blog/fast-properties 提到了三种属性。我如何找出 属性 是哪一个?
我期待使用 v8 本机语法函数或开发工具功能的答案。
这里长话短说解释快速和慢速属性之间的区别。在JS中创建对象时,会附加一个隐藏的class。当将 属性 添加到对象时,会发生“class 转换”(旧的隐藏 class 切换到新的隐藏 class,其中新的 属性它)
当 V8 发现 class 构造函数被声明时,它会创建一个隐藏的 class ex: C0。现在,当 V8 在下一行看到一个 属性 被添加时,在我们的例子中:命名它用新的 属性 更新 C0 并从 C0 切换到一个新的隐藏 class 说 C1 , 然后它看到下一个 属性: age 并切换到 C2.
在此示例中,为 2 人对象动态添加新属性并不是优化的解决方案,因为两个新属性(喜欢和不喜欢)的实例化顺序不同。不同的顺序会导致创建两个不同的隐藏 classes,而不是共享一个共同的隐藏 class.
所以:我们为构造函数person创建了C0。它过渡到 C1 的名字,然后是 C2 的年龄。对于 person1,当它看到 属性“喜欢”时,它会转移到 C3a,“不喜欢”时会转移到 C4a。但是,对于 person2,V8 首先看到 属性“不喜欢”被添加到它,因此它没有共享隐藏的 class C3a,而是创建了一个新的隐藏的 class C3b。然后它为 属性 创建一个新的隐藏 class 喜欢说 C4b.
因为两个对象不共享隐藏的 classes(当它们本可以共享它们时);访问对象的属性很慢,因为 V8 现在无法使用内联缓存。如果两者共享隐藏 class,V8 将使用内联缓存来加快访问速度。所以在下面的示例中,这些是慢速属性。如果顺序相同的话会很快。
希望对您有所帮助。
function person(name,age) {
this.name = name;
this.age = age;
}
let person1 = new person("jim", 28);
let person2 = new person("jane", 27);
person1.likes = "games";
person1.dislikes = "running";
person2.dislikes = "cities";
person2.likes = "nature";
(此处为 V8 开发人员。)
对象是否具有 dictionary-mode 属性由 per-object(而非 per-property)决定。替代状态是具有“快速”属性,这通常意味着 in-object 和 out-of-object 属性的混合。
V8 的任何构建 运行 --allow-natives-syntax
都可以使用 %HasFastProperties(obj)
来判断对象是否具有“快速”属性(返回值为 true
)或字典属性( false
).
要查看“快速”模式对象有多少 in-object 属性,您需要调试版本,并使用 %DebugPrint(obj)
.
据我所知,DevTools 不会公开此信息。 (恕我直言,这很好,因为除了好奇之外,你 不需要 关心这个。)
旁注:我认为“快”和“慢”是非常具有误导性的描述,因为它们听起来太像“好案例”和“坏案例”,而实际上它们具有不同的优点和缺点。使用隐藏 class 跟踪其精确 属性 布局的对象在 reading/writing 现有属性值时速度很快,但在 adding/removing 属性时非常慢。将字典用于其属性的对象在 reading/writing 属性 值时稍慢,但在 adding/removing 属性时要快得多。因此,根据您的应用程序的用例,您有时需要一个,有时需要另一个,除了病态情况外,引擎也非常擅长切换到一个或另一个,并且没有明显优于另一个的对象状态。 (如果您知道您将添加和删除许多属性,使用 Map
将比使用普通对象提供更好的性能。)
post https://v8.dev/blog/fast-properties 提到了三种属性。我如何找出 属性 是哪一个?
我期待使用 v8 本机语法函数或开发工具功能的答案。
这里长话短说解释快速和慢速属性之间的区别。在JS中创建对象时,会附加一个隐藏的class。当将 属性 添加到对象时,会发生“class 转换”(旧的隐藏 class 切换到新的隐藏 class,其中新的 属性它)
当 V8 发现 class 构造函数被声明时,它会创建一个隐藏的 class ex: C0。现在,当 V8 在下一行看到一个 属性 被添加时,在我们的例子中:命名它用新的 属性 更新 C0 并从 C0 切换到一个新的隐藏 class 说 C1 , 然后它看到下一个 属性: age 并切换到 C2.
在此示例中,为 2 人对象动态添加新属性并不是优化的解决方案,因为两个新属性(喜欢和不喜欢)的实例化顺序不同。不同的顺序会导致创建两个不同的隐藏 classes,而不是共享一个共同的隐藏 class.
所以:我们为构造函数person创建了C0。它过渡到 C1 的名字,然后是 C2 的年龄。对于 person1,当它看到 属性“喜欢”时,它会转移到 C3a,“不喜欢”时会转移到 C4a。但是,对于 person2,V8 首先看到 属性“不喜欢”被添加到它,因此它没有共享隐藏的 class C3a,而是创建了一个新的隐藏的 class C3b。然后它为 属性 创建一个新的隐藏 class 喜欢说 C4b.
因为两个对象不共享隐藏的 classes(当它们本可以共享它们时);访问对象的属性很慢,因为 V8 现在无法使用内联缓存。如果两者共享隐藏 class,V8 将使用内联缓存来加快访问速度。所以在下面的示例中,这些是慢速属性。如果顺序相同的话会很快。
希望对您有所帮助。
function person(name,age) {
this.name = name;
this.age = age;
}
let person1 = new person("jim", 28);
let person2 = new person("jane", 27);
person1.likes = "games";
person1.dislikes = "running";
person2.dislikes = "cities";
person2.likes = "nature";
(此处为 V8 开发人员。)
对象是否具有 dictionary-mode 属性由 per-object(而非 per-property)决定。替代状态是具有“快速”属性,这通常意味着 in-object 和 out-of-object 属性的混合。
V8 的任何构建 运行 --allow-natives-syntax
都可以使用 %HasFastProperties(obj)
来判断对象是否具有“快速”属性(返回值为 true
)或字典属性( false
).
要查看“快速”模式对象有多少 in-object 属性,您需要调试版本,并使用 %DebugPrint(obj)
.
据我所知,DevTools 不会公开此信息。 (恕我直言,这很好,因为除了好奇之外,你 不需要 关心这个。)
旁注:我认为“快”和“慢”是非常具有误导性的描述,因为它们听起来太像“好案例”和“坏案例”,而实际上它们具有不同的优点和缺点。使用隐藏 class 跟踪其精确 属性 布局的对象在 reading/writing 现有属性值时速度很快,但在 adding/removing 属性时非常慢。将字典用于其属性的对象在 reading/writing 属性 值时稍慢,但在 adding/removing 属性时要快得多。因此,根据您的应用程序的用例,您有时需要一个,有时需要另一个,除了病态情况外,引擎也非常擅长切换到一个或另一个,并且没有明显优于另一个的对象状态。 (如果您知道您将添加和删除许多属性,使用 Map
将比使用普通对象提供更好的性能。)