V8에서 객체 리터럴에 대한 메서드 호출이 느린 이유는 무엇입니까?

Bfavaretto

간단한 jsperf 테스트 의 결과에 놀랐습니다 .

Benchmark.prototype.setup = function() {
  var O = function() {
      this.f = function(){};
  }
  var o = new O();
  var o2 = {
      f : function(){}
  };
};

// Test case #1
o.f();  // ~721M ops/s

// Test case #2
o2.f(); // ~135M ops/s

나는 둘 다 동일한 성능을 기대했습니다 (실제로 Firefox에서도 성능이 비슷합니다). V8은 케이스 # 1에서 무언가를 최적화해야합니다.

Vyacheslav Egorov

V8 및 jsPerf에 대한 첫 번째 기본 사항 :

  • V8은 숨겨진 클래스 라는 기술을 사용합니다 . 각 히든 클래스는 특정 오브젝트 모양을 설명합니다. 예를 들어 오브젝트는 x오프셋에 속성 16 있거나 오브젝트가 메소드를f 가지며 이러한 히든 클래스는 오브젝트가 변형되어 전환 트리 (엄밀히 말하면 dags)를 형성 할 때 전환함께 연결됩니다 . 모든 숨겨진 클래스가 동일한 전환 트리에있는 것은 아닙니다. 대신 각 생성자에서 새로운 전환 트리가 생성됩니다. 숨겨진 클래스의 기본 개념을 이해하려면 이 슬라이드살펴보십시오 .

  • jsPerf는 다음과 같은 작업을 수행 할 때 테스트를 실행합니다 : 부여 setup하고 body그것을 여러 번 생성하고이 같은 약을 찾고 함수를 실행합니다 :

    function measure() {
      /* setup */
      var start = Date.now();
      for (var i = 0; i < N; i++) {
        /* body */
      }
      var end = Date.now();
    
      /* N / (start - end) determines ops / ms reported */
    }
    

    각 실행을 샘플 이라고합니다 .

이제 벤치 마크에서 전환 트리를 살펴 보겠습니다.

  1. 의 숨겨진 클래스는 oconstructor에 루트가있는 전환 트리 속합니다 O. 각 생성자는 한 번만 호출됩니다. 이를 통해 V8은 메모리에 다음과 같은 전환 트리를 구축 할 수 있습니다.

    O{} -f-> O{ f: <closure> }
    

    의 히든 클래스는 o기본적 으로 주어진 클로저에 의해 구현 된 메소드o있음 V8에 알려줍니다 . 이를 통해 V8의 최적화 컴파일러가 위의 벤치 마크에서 인라인 할 수 있으므로 벤치마킹 루프가 비워집니다.ff

  2. 의 숨겨진 클래스는 o2의 전환 트리에 속합니다 Object. 먼저 통지 setupV8 홍보와 같은 최적화를 적용하려고 그래서 만약 여러 번 호출 f이 불가능한 전환 트리에 도착할 것입니다 방법에 :

    Object{} -f-> Object{ f: <closure> }
             -f-> Object{ f: <other closure> }
    

    사실 V8은 시도조차하지 않습니다. V8 구현 f자는 이 상황을 예견했고 V8 은 정상적인 속성을 만듭니다 .

    Object{} -f-> Object{ f: <property at offset 8> }
    

    따라서 호출 o2.f()하려면 먼저로드해야하며 이로 인해 인라인도 손상됩니다.

여기서 한 가지 중요한 사실을 깨달아야합니다. O생성자를 두 번 호출 하면 V8은 V8이 타격을 피하는 동일한 불가능한 전환 트리에 도달합니다 Object.

    O{} -f-> O{ f: <closure> }
        -f-> O{ f: <other closure> }

당신은 그런 구조를 가질 수 없습니다. 이 경우 V8 on the fly는 f메서드를 만드는 대신 필드 로 변환 하고 전환 트리를 다시 작성합니다.

    O{} -f-> O{ f: <property at offset 8> }

http://jsperf.com/function-call-on-js-objects/3 에서이 효과를 확인하십시오. 여기서 new O()생성하기 전에 추가했습니다 o. 객체 리터럴과로 구성된 객체의 성능 new이 동일 하다는 것을 알 수 있습니다.

여기서 또 다른 세부 사항 f은 리터럴이 전역 범위 에서 선언 된 경우 V8이 리터럴에 대한 메서드 로도 전환하려고 시도한다는 것 입니다. V8에 대한 http://jsperf.com/function-call-on-js-objects/5Issue 2246을 참조하십시오 . 이유는 간단합니다. 전역 범위의 리터럴은 한 번만 평가되므로 그러한 승격이 성공할 가능성이 높고 리터럴이 여러 번 평가되는 경우 발생하는 메서드간에 충돌이 발생하지 않습니다.

내 블로그 게시물 에서 유사한 문제에 대해 자세히 읽을 수 있습니다 .

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

Python에서 숫자 리터럴에 대한 메서드를 호출하는 것이 구문 오류 인 이유는 무엇입니까?

분류에서Dev

이 대신 객체의 메서드에서 객체 이름이 사용되는 이유는 무엇입니까?

분류에서Dev

hexbin 객체에 대한 graphics :: plot 호출에서 오류가 발생하는 이유는 무엇입니까?

분류에서Dev

arangodb에서 정렬이 느린 이유는 무엇입니까?

분류에서Dev

함수에 대한 인수가 입력이 객체의 속성 인 해당 메서드가있는 객체 인 경우 Typescript에서 메서드 호출을 추론 할 수없는 이유는 무엇입니까?

분류에서Dev

페이드 에지가 느린 이유는 무엇입니까?

분류에서Dev

더 빠른 컴퓨터에서 동일한 그래픽 카드가 느린 이유는 무엇입니까?

분류에서Dev

Xorg에서 키보드 입력이 느린 이유는 무엇입니까?

분류에서Dev

파이썬에서 객체에 의한 호출이란 무엇입니까?

분류에서Dev

deinit 메서드가 호출 된 후 객체에 액세스 할 수있는 이유는 무엇입니까?

분류에서Dev

Keras 서브 클래 싱 API에서 호출 메서드가 호출되지 않고 대체로이 클래스의 객체를 호출하여 입력이 전달되는 이유는 무엇입니까?

분류에서Dev

객체 리터럴 foo 외부에서 foo 내부 메서드의 내부 함수를 호출하는 방법은 무엇입니까? (아래 코드 참조)

분류에서Dev

내 코드에서 numba가 순수한 Python보다 느린 이유는 무엇입니까?

분류에서Dev

Chrome에서 다운로드 속도가 느린 이유는 무엇입니까?

분류에서Dev

자바 스크립트에서 배열을 분해하는 것이 객체보다 느린 이유는 무엇입니까?

분류에서Dev

정렬 된 벡터에 대한 이진 검색이 std :: set find보다 느린 이유는 무엇입니까?

분류에서Dev

객체에서`valid?`메서드를 호출 한 후 오류를 수집하는 방법은 무엇입니까?

분류에서Dev

객체에서`valid?`메서드를 호출 한 후 오류를 수집하는 방법은 무엇입니까?

분류에서Dev

내 슈퍼 클래스가 Swift에서 자체 메서드 대신 하위 클래스의 메서드를 호출하는 이유는 무엇입니까?

분류에서Dev

Clojure에서 중첩 루프 / 반복이 느린 이유는 무엇입니까?

분류에서Dev

Mac에서 SDL이 Linux보다 훨씬 느린 이유는 무엇입니까?

분류에서Dev

Linux에서 Firefox 3.0이 그렇게 느린 이유는 무엇입니까?

분류에서Dev

Windows 8.1 노트북에서 Nmap이 느린 이유는 무엇입니까?

분류에서Dev

$ firebaseArray가 디스플레이에서 느린 이유는 무엇입니까?

분류에서Dev

$ firebaseArray가 디스플레이에서 느린 이유는 무엇입니까?

분류에서Dev

우분투 12.04에서 gimp 2.8이 느린 이유는 무엇입니까?

분류에서Dev

stream () 메서드가없는 클래스의 객체에서 stream () 메서드를 호출 할 수있는 이유는 무엇입니까?

분류에서Dev

호출 된 객체에서 정적 블록이로드되지 않는 이유는 무엇입니까?

분류에서Dev

Cython에서 C 배열에 쓰기가 느린 이유는 무엇입니까?

Related 관련 기사

  1. 1

    Python에서 숫자 리터럴에 대한 메서드를 호출하는 것이 구문 오류 인 이유는 무엇입니까?

  2. 2

    이 대신 객체의 메서드에서 객체 이름이 사용되는 이유는 무엇입니까?

  3. 3

    hexbin 객체에 대한 graphics :: plot 호출에서 오류가 발생하는 이유는 무엇입니까?

  4. 4

    arangodb에서 정렬이 느린 이유는 무엇입니까?

  5. 5

    함수에 대한 인수가 입력이 객체의 속성 인 해당 메서드가있는 객체 인 경우 Typescript에서 메서드 호출을 추론 할 수없는 이유는 무엇입니까?

  6. 6

    페이드 에지가 느린 이유는 무엇입니까?

  7. 7

    더 빠른 컴퓨터에서 동일한 그래픽 카드가 느린 이유는 무엇입니까?

  8. 8

    Xorg에서 키보드 입력이 느린 이유는 무엇입니까?

  9. 9

    파이썬에서 객체에 의한 호출이란 무엇입니까?

  10. 10

    deinit 메서드가 호출 된 후 객체에 액세스 할 수있는 이유는 무엇입니까?

  11. 11

    Keras 서브 클래 싱 API에서 호출 메서드가 호출되지 않고 대체로이 클래스의 객체를 호출하여 입력이 전달되는 이유는 무엇입니까?

  12. 12

    객체 리터럴 foo 외부에서 foo 내부 메서드의 내부 함수를 호출하는 방법은 무엇입니까? (아래 코드 참조)

  13. 13

    내 코드에서 numba가 순수한 Python보다 느린 이유는 무엇입니까?

  14. 14

    Chrome에서 다운로드 속도가 느린 이유는 무엇입니까?

  15. 15

    자바 스크립트에서 배열을 분해하는 것이 객체보다 느린 이유는 무엇입니까?

  16. 16

    정렬 된 벡터에 대한 이진 검색이 std :: set find보다 느린 이유는 무엇입니까?

  17. 17

    객체에서`valid?`메서드를 호출 한 후 오류를 수집하는 방법은 무엇입니까?

  18. 18

    객체에서`valid?`메서드를 호출 한 후 오류를 수집하는 방법은 무엇입니까?

  19. 19

    내 슈퍼 클래스가 Swift에서 자체 메서드 대신 하위 클래스의 메서드를 호출하는 이유는 무엇입니까?

  20. 20

    Clojure에서 중첩 루프 / 반복이 느린 이유는 무엇입니까?

  21. 21

    Mac에서 SDL이 Linux보다 훨씬 느린 이유는 무엇입니까?

  22. 22

    Linux에서 Firefox 3.0이 그렇게 느린 이유는 무엇입니까?

  23. 23

    Windows 8.1 노트북에서 Nmap이 느린 이유는 무엇입니까?

  24. 24

    $ firebaseArray가 디스플레이에서 느린 이유는 무엇입니까?

  25. 25

    $ firebaseArray가 디스플레이에서 느린 이유는 무엇입니까?

  26. 26

    우분투 12.04에서 gimp 2.8이 느린 이유는 무엇입니까?

  27. 27

    stream () 메서드가없는 클래스의 객체에서 stream () 메서드를 호출 할 수있는 이유는 무엇입니까?

  28. 28

    호출 된 객체에서 정적 블록이로드되지 않는 이유는 무엇입니까?

  29. 29

    Cython에서 C 배열에 쓰기가 느린 이유는 무엇입니까?

뜨겁다태그

보관