首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >扩展String.prototype性能表明函数调用速度快了10倍

扩展String.prototype性能表明函数调用速度快了10倍
EN

Stack Overflow用户
提问于 2016-07-16 04:36:40
回答 1查看 1.8K关注 0票数 7

我想用一些实用方法来扩展String对象原型。它起了作用,但性能却出奇地低。将字符串传递给函数比重写正在执行相同操作的String.prototype方法快10倍。为了确保这种情况真的发生,我创建了一个非常简单的count()函数和相应的方法。

(我在做实验,并创建了三个不同版本的方法。)

代码语言:javascript
复制
function count(str, char) {
    var n = 0;
    for (var i = 0; i < str.length; i++) if (str[i] == char) n++;
    return n;
}

String.prototype.count = function (char) {
    var n = 0;
    for (var i = 0; i < this.length; i++) if (this[i] == char) n++;
    return n;
}

String.prototype.count_reuse = function (char) {
    return count(this, char)
}

String.prototype.count_var = function (char) {
    var str = this;
    var n = 0;
    for (var i = 0; i < str.length; i++) if (str[i] == char) n++;
    return n;
}

// Here is how I measued speed, using Node.js 6.1.0

var STR ='0110101110010110100111010011101010101111110001010110010101011101101010101010111111000';
var REP = 1e3//6;

console.time('func')
for (var i = 0; i < REP; i++) count(STR,'1')
console.timeEnd('func')

console.time('proto')
for (var i = 0; i < REP; i++) STR.count('1')
console.timeEnd('proto')

console.time('proto-reuse')
for (var i = 0; i < REP; i++) STR.count_reuse('1')
console.timeEnd('proto-reuse')

console.time('proto-var')
for (var i = 0; i < REP; i++) STR.count_var('1')
console.timeEnd('proto-var')

结果:

代码语言:javascript
复制
func: 705 ms
proto: 10011 ms
proto-reuse: 10366 ms
proto-var: 9703 ms

正如你所看到的,差别是巨大的。

以下证明了方法调用的性能被忽略地较慢,并且函数代码it self对于方法的执行速度较慢。

代码语言:javascript
复制
function count_dummy(str, char) {
    return 1234;
}

String.prototype.count_dummy = function (char) {
    return 1234; // Just to prove that accessing the method is not the bottle-neck.
}

console.time('func-dummy')
for (var i = 0; i < REP; i++) count_dummy(STR,'1')
console.timeEnd('func-dummy')

console.time('proto-dummy')
for (var i = 0; i < REP; i++) STR.count_dummy('1')
console.timeEnd('proto-dummy')

console.time('func-dummy')
for (var i = 0; i < REP; i++) count_dummy(STR,'1')
console.timeEnd('func-dummy')

结果:

代码语言:javascript
复制
func-dummy: 0.165ms
proto-dummy: 0.247ms

虽然在大量重复(如1e8)中,原型方法的速度比函数慢10倍,但在这种情况下可以忽略这一点。

所有这些可能只与字符串对象相关,因为当您将简单的泛型对象传递给函数或调用它们的方法时,它们的执行情况大致相同:

代码语言:javascript
复制
var A = { count: 1234 };

function getCount(obj) { return obj.count }

A.getCount = function() { return this.count }

console.time('func')
for (var i = 0; i < 1e9; i++) getCount(A)
console.timeEnd('func')

console.time('method')
for (var i = 0; i < 1e9; i++) A.getCount()
console.timeEnd('method')

结果:

代码语言:javascript
复制
func: 1689.942ms
method: 1674.639ms

我一直在Stackoverflow和binging上搜索,但是除了建议“不要扩展String或Array,因为您污染了名称空间”(这对于我的特定项目来说不是问题),我找不到与函数相比的方法性能相关的任何东西。因此,我应该简单地忘记由于添加的方法的性能下降而扩展String对象,还是更多呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-16 10:29:16

这很可能是因为您没有使用严格模式,而且您的方法中的this值被胁迫到一个String实例,而不是作为一个原始字符串。这种强制以及对String对象的进一步方法调用或属性访问比使用原语值慢。

你可以(编辑:至少在2016年)通过在var STR = new String('01101011…')上重复你的测量来确认这一点,因为它的开销应该更小。

然后修复您的实现:

代码语言:javascript
复制
String.prototype.count = function (char) {
    "use strict";
//  ^^^^^^^^^^^^
    var n = 0;
    for (var i = 0; i < this.length; i++)
        if (this[i] == char)
            n++;
    return n;
};
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38407760

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档