[英]Performance of accessing properties - Factory function vs. Concatenative inheritance vs. Class
請幫助:) — 我必須檢查訪問屬性的性能 — 工廠函數、串聯繼承和類,我不明白為什么串聯繼承會丟失? 畢竟,在 Concatenative 繼承中訪問復制的屬性應該是最快的。 我在 Chrome 和 Safari 上運行測試,而 CI 總是失敗。 https://jsperf.com/factory-function-vs-concatenative-inheritance-get
此測試中的代碼:
const alien = {
sayHello () {
return `Hello, my name is ${ this.name }`;
}
};
//Delegate prototype
const createAlienFF = (name) => {
return Object.assign(Object.create(alien), {
name
});
}
//Delegate prototype - creating objects
var tabFF = [];
for(var i = 0; i < 1000; i++ ) {
tabFF[i] = createAlienFF('Clark' + i);
}
//Concatenative inheritance
const createAlienCI = (name) => {
return Object.assign(
{},
alien,
{name: name}
);
}
//Concatenative inheritance - creating objects
var tabCI = [];
for(var i = 0; i < 1000; i++ ) {
tabCI[i] = createAlienCI("Clark" + i );
}
//Class
class Alien {
constructor(name) {
this.name = name
}
sayHello() {
return `Hello, my name is ${ this.name }`;
}
}
//Class - creating objects
var tabClass = [];
for(var i = 0; i < 1000; i++ ) {
tabClass[i] = new Alien("Clark" + i );
}
//Tests
//1 - Delegate prototype
for(var i = 0; i < 1000; i++ ) {
tabFF[i].sayHello();
}
//2 - Concatenative inheritance
for(var i = 0; i < 1000; i++ ) {
tabCI[i].sayHello();
}
//3 - Class
for(var i = 0; i < 1000; i++ ) {
tabClass[i].sayHello();
}
畢竟,在 Concatenative 繼承中訪問復制的屬性應該是最快的。
為什么你這么想? 因為是不需要遍歷原型鏈的直接屬性訪問?
嗯,是的,這可能是關於簡單引擎實現的一個很好的推理。 但是你沒有考慮到對象模型的優化是專門為繼承量身定制的,使得對(類)實例的方法訪問非常快。 看看https://github.com/v8/v8/wiki/Design%20Elements#fast-property-access , https://blog.ghaiklor.com/optimizations-tricks-in-v8-d284b6c8b183 , HTTP: //richardartoul.github.io/jekyll/update/2015/04/26/hidden-classes.html和偉大的http://mrale.ph/blog/2012/06/03/explaining-js-vms-in- js-inline-caches.html 。 要點:V8優化的“已知的形狀”的對象的方法訪問,也就是從繼承對象alien
或Alien.prototype
你的情況(它們共享相同的隱藏的類)。 它知道猜測在你的循環中,只使用了那個形狀的對象,並且可以推斷出它們都調用了完全相同的sayHello
函數。 這是一個可以從中獲取代碼的固定位置,可以進行進一步的優化,例如內聯。 另一方面,由createAlienCI
工廠創建的對象也都共享相同的形狀,但每個對象都包含其單獨的sayHello
屬性。 所有這些屬性可能都包含相同的函數對象,但我們無法知道(我們也不會猜到——這是一種不尋常的模式)。 因此,引擎每次在調用之前都會從每個實例中獲取函數引用 - 至少它知道每個實例的位置(在哪個內存偏移處),因為它們的形狀不變。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.