Chrome分配配置文件:为什么handleEvent的内存消耗如此巨大?

时间:2018-03-13 20:43:30

标签: memory-management google-chrome-devtools v8 event-listener

首先,可以查看medium.com上有关将pojo指定为事件监听器的能力的this post。问题是这个对象应该有handleEvent方法,以便能够对某个事件做出反应。 例如:

const handler = {handleEvent(e) {this[`on${e.type}`](e)}};

在上面提到的media.com上的帖子中,作者将我们发送到benchmark,这是为了证明这一事实而创建的,即handleEvent的使用基本上需要O(1)内存开销。 例如(不是实际的基准):

const handlersQueue = [];

const masterHandler = {
    handleEvent(e) {
        this[`on${e.type}`](e)
    },
    onclick: function() {++this.counter},
    counter: 0
};

for (let i = 0; i < 1e4; i++) {
    const newHandler = Object.create(masterHandler);
    document.body.addEventListener('click', newHandler);
    handlersQueue.push(newHandler);
}

document.body.dispatchEvent(new Event('click'));

在这种情况下,假设所有事件处理程序都将从原型(masterHandler)借用handleEvent方法是合乎逻辑的。 作者已经创建了一个更复杂的上述示例形式(看看DynamicHandler类),但整体想法保持不变。 相反,分配配置文件显示handleEvent函数( Chrome 版本 64.0.3282.186 (官方构建)(64位),MacOS High Sierra)消耗大量内存: weird memory consumption results 问题是:

  • a)为什么会这样?
  • b)不应该为所有事件监听器使用handleEvent花费我们O(1)(基本上是0字节的SelfSize(字节))而不是O(n)?
  • c)是ChromeDevTools还是V8自身的问题?

1 个答案:

答案 0 :(得分:2)

V8开发者在这里。字符串连接,即原始基准中的'on' + e.type,或基于模板文字的替代:

`on${e.type}`

导致(不出所料?)在每次调用时创建一个字符串。 100,000次调用3.3MB,每次迭代33个字节;字符串&#34; onclick&#34;在堆上需要32个字节,因此大部分内容都可以解释。

虽然这不是特别高效,但这些字符串至少是短暂的,即垃圾收集器将迅速摆脱它们。除非您正在接受分配配置文件,否则您可能甚至都不会注意到;另一方面,如果你最终追逐真正的内存消耗问题,那么在配置文件中摆脱这样的噪音可能是值得的,因为这个原因。

如果您想节省开销,可以简单地重命名&#34; onclick&#34;功能到&#34;点击&#34; (以及任何其他事件的类似情况),所以你根本不需要使用字符串。