Program Tip

lodash.each가 native forEach보다 빠른 이유는 무엇입니까?

programtip 2020. 11. 17. 20:59
반응형

lodash.each가 native forEach보다 빠른 이유는 무엇입니까?


자체 범위로 for 루프를 실행하는 가장 빠른 방법을 찾으려고했습니다. 내가 비교 한 세 가지 방법은 다음과 같습니다.

var a = "t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t,t".split();

// lodash .each -> 1,294,971 ops/sec
lodash.each(a, function(item) { cb(item); });

// native .forEach -> 398,167 ops/sec
a.forEach(function(item) { cb(item); });

// native for -> 1,140,382 ops/sec
var lambda = function(item) { cb(item); };
for (var ix = 0, len = a.length; ix < len; ix++) {
  lambda(a[ix]);
}

이것은 OS X의 Chrome 29에 있습니다. 여기에서 직접 테스트를 실행할 수 있습니다.

http://jsben.ch/BQhED

lodash는 어떻게 .each네이티브보다 거의 두 배 빠른 .forEach가요? 게다가 평야보다 어떻게 빠른 for가요? 마법? 마법?


_.each()와 완전히 호환되지 않습니다 [].forEach(). 다음 예를 참조하십시오.

var a = ['a0'];
a[3] = 'a3';
_.each(a, console.log); // runs 4 times
a.forEach(console.log); // runs twice -- that's just how [].forEach() is specified

http://jsfiddle.net/BhrT3/

따라서 lodash의 구현 if (... in ...)에는 성능 차이를 설명 할 수 있는 검사 가 누락되었습니다 .


위의 주석에서 언급했듯이 네이티브와의 차이점 for은 주로 테스트의 추가 함수 조회로 인해 발생합니다. 보다 정확한 결과를 얻으려면이 버전을 사용하십시오.

for (var ix = 0, len = a.length; ix < len; ix++) {
  cb(a[ix]);
}

http://jsperf.com/lo-dash-each-vs-native-foreach/15


http://kitcambridge.be/blog/say-hello-to-lo-dash/

lo-dash 개발자는 네이티브의 상대적 속도가 forEach브라우저마다 다르다고 설명합니다 (여기와 비디오에서) . 그냥 때문에 forEach더 빨리로 만든 간단한 루프보다 것을 의미하지 않는다 네이티브 for또는 while. 우선 forEach더 특별한 경우를 처리해야합니다. 둘째, forEach함수 호출 등의 (잠재적) 오버 헤드와 함께 콜백을 사용합니다.

chrome특히 (적어도 lo-dash 개발자에게는) 상대적으로 느린 forEach. 따라서 해당 브라우저의 경우 lo-dash는 자체의 간단한 while루프를 사용하여 속도를 얻습니다. 따라서 속도 이점이 있습니다 (그러나 다른 사람들은 그렇지 않습니다).

Lo-Dash는 네이티브 메서드를 현명하게 선택하여 (주어진 환경에서 빠른 것으로 알려진 경우에만 네이티브 구현을 사용하여) 네이티브와 관련된 성능 비용 및 일관성 문제를 방지합니다.


예, lodash / underscore는 각각 .forEach. 엔진이 게터없이 희소 배열을 빠르게 확인할 수 없다면 함수를 정말 느리게 만드는 미묘한 세부 사항이 있습니다.

이는 99 % 사양을 준수하며 일반적인 경우에 대해 V8 에서 각각 lodash와 동일한 속도로 실행됩니다 .

function FastAlmostSpecForEach( fn, ctx ) {
    "use strict";
    if( arguments.length > 1 ) return slowCaseForEach();
    if( typeof this !== "object" ) return slowCaseForEach();
    if( this === null ) throw new Error("this is null or not defined");
    if( typeof fn !== "function" ) throw new Error("is not a function");
    var len = this.length;
    if( ( len >>> 0 ) !== len ) return slowCaseForEach();


    for( var i = 0; i < len; ++i ) {
        var item = this[i];
        //Semantics are not exactly the same,
        //Fully spec compliant will not invoke getters
       //but this will.. however that is an insane edge case
        if( item === void 0 && !(i in this) ) {
            continue;
        }
        fn( item, i, this );
    }
}

Array.prototype.fastSpecForEach = FastAlmostSpecForEach;

undefined를 먼저 확인하면 루프의 일반 배열을 전혀 처벌하지 않습니다. 엔진은 내부를 사용하여 이상한 배열을 감지 할 수 있지만 V8은 그렇지 않습니다.


Here's an updated link (circa 2015) showing the performance difference which compares all three, for(...), Array.forEach and _.each: https://jsperf.com/native-vs-underscore-vs-lodash

Note: Put here since I didn't have enough points yet to comment on the accepted answer.

참고URL : https://stackoverflow.com/questions/18881487/why-is-lodash-each-faster-than-native-foreach

반응형