자바 스크립트 코드의 최적화를 위해: 히든 클래스(hidden class)와 인라인 캐싱(inline-caching )

0

자바 스크립트 코드의 최적화를 위해: 히든 클래스(hidden class)와 인라인 캐싱(inline-caching )

자바스크립트 코드 최적화를 위해 알아두면 좋을 점인 히든 클래스와 인라인 캐싱에 대해 알아보자.

Today, we discuss about the hidden class and line caching for the writing optimized code.

Writing Optimzied Javascript Code

코드를 최적화 하기 위해서는 아래의
Eval(), arguments , for in , with , delete 이 5가지를 조심해야한다.

히든 클래스(hidden classes)

function Animal(x,y){
  this.x = x;
  thix.y = y;
}

const ojb1 = new Animal(1,2);
const obj2 = new Animal(3,4);

obj1.a = 30;
obj2.b = 100;

obj2.b = 30;
obj2.a = 100;

위의 예제를 보며 알아보자.

히든 클래스도 자바스크립트 엔진의 컴파일러가 내부적으로 최적화 시켜 활용하는 도구 중 하나이다. obj1 과 obj2는 앞서 선언했을 때는 동일한 Animal을 공유하는 클래스로 인지 한다. 그런데 그 이후에 위의 예제처럼 obj1과 obj2의 객체의 값에 다른 순서를 부여하면, 컴파일러가 두 객체가 같은 클래스(animal )을 인지 하는 것으로 파악하지 못하여 최적화에 시간이 오래 걸리게 된다.

즉, object객체와 순서가 똑같은 것이 핵심이다. 만약에 예제 상황에서 추가 하려면 똑같은 순서에 맞춰서 obj2.a = 100; obj2 = 30; 이로 해주어야 최적화에 도움이 될 것이다.

delete 키워드를 사용할 때 주의해야 하는 이유도 이와 맞닿아 있다. 예를 들어서 delete obj1.x = 30; 코드로 객체의 key를 삭제할 경우, obj1과 obj2는 더 이상 동일한 hidden class를 공유하지 않기 때문에 최적화가 어려워진다.

인라인 캐싱(inline Caching)

앞서 우리는 자바 스크립트 엔진의 원리에 대해 알아보았는데, JavaScript 엔진은 Inlin Caching를 사용하여 object에서 property를 찾을 수 있는 위치에 대한 정보를 암기하여, 높은 cost를 가지는 조회 횟수를 줄입니다.

즉, 반복 작업에서의 객체 접근 시 엔진 상에서의 '조회' 작업을 생략함으로써 최적화를 하를 하는 기법이라 할 수 있다. 조회 작업을 최적화 함으로써 불필요한 메모리 접근을 최소화 하는 것이라 할 수 있다.

function findUser(user){
  return `found ${user.firstName} ${user.lastName}`
}

const userData = {
  firstName : 'Johnson',
  lastName : 'Junior'
}

findUser(userData); //'found Johnson Junior'로 대체

간단하게 대표 예시를 들어보면, findUser(userData); 이것을 출력을 여러번 사용하셔 쓴다고 해보자 이럴 때 , 만약 위 코드에서 findUser(userData); 함수가 1백만번 반복적으로 실행된다면, 컴파일러는 userData 객체를 1백만번 찾는 대신, findUser(userData); 를 'found Jonhson Junior' 라는 텍스트로 대체하여 실행 속도를 대폭 향상시킨다. 처음에는 엔진이 객체위 치를 찾아서 key와 value를 확인하겠지만

finduser(userData); 인식

finduser(userData);

finduser(userData);

// engine assums that finduser(userData) equals " found Johnson Junior"

and save it to save time and caches.

이런 경우는 정적유형의 인라인 캐싱으로 객체가 동일한 순서와 속성을 가지고 있는 경우에 해당한다. 예를 들어 ,{firstname: "Han", lastname: "Solo"} 처럼 두 객의 속성이 전부 같을 경우는 아래와 같은 짤 처럼 작동하면 이를 모노모픽 IC(monomorphic IC) 라고 부른다.

동적 Inline Caching(IC)의 종류 Megamorphic IC vs Polymorphic

inline Caching의 종류로는 Megamorphinc inline Cache 와 Polymorphic caching이 있다.

Polymorphic inlince caching

(2개의 다른 객체 모양을 가진 코드의 예제)

Megamorphic inlice Caching

(5개의 서로 전부 다른 객체 모양을 가진 코드의 예제)

앞서 IC 개념에 대해 배운 것처럼 Monomorphic IC lC는 같은 형태의 객체로서 위의 예시에 first name예시처럼 짤에서도 그런 비슷한 함수가 실행 되는데, 같은 형태(shape)의 객체형태 프로퍼티가 모두 동일한 경우 해당하는 것이라 할 수 있다. function getName에 first name , last name있는 경우였다.

그런데 여기에 다른 속성의 객체가 추가되서 서로 다른 형태의 객체가 많아 질 경우 Polymorphic inlince caching 이라 부르며, 이러한 것이 더 많아 질 경우 megamorphic IC라 부른다.

인라인 캐싱은 객체의 구조나 순서가 동일할 경우 효과적이나 서로 다른 객체의 수가 늘어 날 수록 처리할 것이 늘어난다. 위의 Megamorphic 짤에서 보듯이 인라인 캐싱 할 메로리가 없을시 전역 캐시에서 조회를 하면서 퍼포먼스가 낮아진다.

그렇다면 해결방법은?

서로다른 객체를 클래스 하나로 묶어버린다.

해결 방법과 예시는 여기 참조할 것 , 참고자료의 사이트와 동일.

결론:

  • 인라인 캐싱은 강력한 최적화 기술이며, 단일 오브젝트 형태만 최적화 된 기능으로 넘어갈 때 가장 효과적이다.

  • Megamorphic 케이스처럼 서로 다른 객체 일 경우는 자바스크립트 클래스를 사용하는 것이 좋다. TypeScript와 같은 정적 타입화 된 트랜스파일러는 monomorphic 인라인 캐싱의 가능성을 높인다.

참고자료:

인라인 캐싱에 원리 대해 더 자세하게 알고 싶다면 아래의 shape를 참조할 것(원문은 Spanish):

JS engine fundamentals: Shapes and Inline Caches :https://shlrur.github.io/javascripts/javascript-engine-fundamentals-shapes-and-Inline-caches/JavaScript

JavaScript essentials: why you should know how the engine works:

https://www.freecodecamp.org/news/javascript-essentials-why-you-should-know-how-the-engine-works-c2cc0d321553/

https://devtimothy.tistory.com/94 [공부하는 블로그] //

JavaScript essentials: why you should know how the engine works 번역본

Hidden Calsses and inline caching in v8 :https://richardartoul.github.io/jekyll/update/2015/04/26/hidden-classes.html
Managing Arguments:https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments

profile
문과생 개발자되다

0개의 댓글