扩展String.prototype性能表明函数调用快了10倍 [英] Extending String.prototype performance shows that function calls are 10x faster

查看:83
本文介绍了扩展String.prototype性能表明函数调用快了10倍的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用一些实用方法扩展String对象原型。它起作用了,但性能却低得惊人。将字符串传递给函数比覆盖执行相同操作的 String.prototype 方法快10倍。为了确保这确实发生,我创建了一个非常简单的 count()函数和相应的方法。

I wanted to extend String object prototype with some utility method. It worked, but the performance was surprisingly low. Passing a string to a function is 10x times faster than overriding the String.prototype method that is doing the same thing. To make sure this really happens I created a very simple count() function and the corresponding methods.

(I正在试验,并创建了该方法的三个不同版本。)

(I was experimenting, and created three different versions of the method.)

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')

结果:

func: 705 ms
proto: 10011 ms
proto-reuse: 10366 ms
proto-var: 9703 ms

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

As you can see the difference is dramatic.

下面证明方法调用的性能可以忽略不计,并且函数代码它自我对于方法来说速度较慢。

The below proves that performance of method calls is neglectably slower, and that the function code it self is slower for methods.

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')

结果:

func-dummy: 0.165ms
proto-dummy: 0.247ms

虽然重复次数很大(如1e8),原型方法证明比函数慢10倍,但这可以在这种情况下可以忽略。

Although on huge repetitions (like 1e8) prototyped methods proves to be 10x times slower than functions, this can be ignored for this case.

所有这些只与String对象有关,因为简单的通用对象在将它们传递给函数或调用它们的方法时执行大致相同的操作。 :

All this may be related only to a String object, because simple generic objects perform about the same when you pass them to functions or call their methods:

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')

结果:

func: 1689.942ms
method: 1674.639ms

我一直在搜索Stackoverflow和binging,但其他那个建议不要因为污染名称空间而扩展字符串或数组(这对我的特定项目来说不是问题),与函数相比,我找不到与方法性能相关的任何内容。那么我是否应该忘记由于添加方法的性能下降而扩展String对象,还是有更多关于它?

I've been searching on Stackoverflow and binging, but other that the recommendation "do not extend String or Array because you pollute the name space" (which is not a problem for my particular project), I cannot find anything related to performance of methods compared to functions. So should I simply forget about extending the String object due to performance drop of added methods or there is more about it?

推荐答案

这个很可能是因为您没有使用严格模式,并且您的方法中的值需要强制转换为 String 实例而不是原始字符串。

This is most likely because you are not using strict mode, and the this value inside your method needs to be cast to a String instance instead of being a primitive string.

您可以通过在上重复测量来确认这一点var STR = new String('01101011 ...')

然后修复您的实施:

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;
};

这篇关于扩展String.prototype性能表明函数调用快了10倍的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆