고성능 JavaScript 작성

黄舟
풀어 주다: 2017-02-21 11:45:44
원래의
1570명이 탐색했습니다.



고성능 JavaScript 작성

이 글의 원래 의도는 몇 가지 간단한 코딩 팁을 사용하여 JavaScript를 개선하는 방법을 소개하는 것입니다. 컴파일러 최적화 프로세스는 코드 실행 효율성을 향상시킵니다. 특히 가비지 수집 속도가 빠른 게임에서는 성능이 약간 떨어지면 사용자에게 흰색 화면이 표시됩니다.

단형성: 단일형성

JavaScript에서는 함수를 호출할 때 동적 매개변수가 전달되도록 허용하지만 간단한 2개 매개변수 함수를 예로 들면 매개변수 유형, 매개변수 개수 및 반환 유형이 동적으로 호출되는 경우에만 확인할 수 있으며 컴파일러는 구문 분석하는 데 더 많은 시간이 필요합니다. 컴파일러는 당연히 단형적으로 예측 가능한 데이터 구조, 매개변수 통계 등을 처리할 수 있기를 원합니다.

function example(a, b) {
  // we expect a, b to be numeric
  console.log(++a * ++b);
};

example(); // bad
example(1); // still bad
example("1", 2); // dammit meg

example(1, 2); // good
로그인 후 복사

상수: 상수

상수를 사용하면 컴파일러가 컴파일 중에 변수 값 대체를 완료할 수 있습니다.

const a = 42; // we can easily unfold this
const b = 1337 * 2; // we can resolve this expression
const c = a + b; // still can be resolved
const d = Math.random() * c; // we can only unfold 'c'

// before unfolding
a;
b;
c;
d;

// after unfolding
// we can do this at compile time!
42;
2674;
2716;
Math.random() * 2716;
로그인 후 복사

인라인: 인라인

JIT 컴파일러는 다음을 찾을 수 있습니다. 가장 자주 실행되는 코드 부분. 코드를 작은 코드 블록으로 분할하면 컴파일러가 컴파일 타임에 이러한 코드 블록을 인라인 형식으로 변환하고 실행 속도를 높이는 데 도움이 됩니다.

데이터 유형: 데이터 유형

숫자와 부울은 문자열과 같은 다른 기본 유형보다 더 나은 성능을 발휘하므로 가능한 자주 사용하십시오. 문자열 유형을 사용하면 추가 가비지 수집 비용이 발생할 수 있습니다.

const ROBOT = 0;
const HUMAN = 1;
const SPIDER = 2;

let E_TYPE = {
  Robot: ROBOT,
  Human: HUMAN,
  Spider: SPIDER
};

// bad
// avoid uncached strings in heavy tasks (or better in general)
if (entity.type === "Robot") {
  
}

// good
// the compiler can resolve member expressions
// without much deepness pretty fast
if (entity.type === E_TYPE.Robot) {
  
}

// perfect
// right side of binary expression can even get unfold
if (entity.type === ROBOT) {
  
}
로그인 후 복사

엄격 및 추상 연산자

가능하면 == 연산자 대신 === 엄격한 비교 연산자를 사용하세요. 엄격한 비교 연산자를 사용하면 컴파일러가 유형 추론 및 변환을 수행하는 것을 방지하여 특정 성능을 향상시킬 수 있습니다.

엄격한 조건

JavaScript의 if 문도 매우 유연합니다. if(a) then bla 유형의 조건 선택 문에서 유사한 값을 직접 전달할 수 있습니다. 하지만 이 경우도 위에서 언급한 엄격한 비교 연산자와 느슨한 비교 연산자와 마찬가지로 비교를 위해 컴파일러가 이를 여러 데이터 형식으로 변환해야 하며 결과를 즉시 얻을 수는 없습니다. 물론 약어 사용에 대한 맹목적인 반대는 아니지만, 성능이 크게 강조되는 시나리오에서는 모든 세부 사항을 최적화하는 것이 좋습니다.

let a = 2;

// bad
// abstracts to check in the worst case:
// - is value equal to true
// - is value greater than zero
// - is value not null
// - is value not NaN
// ..
if (a) {
 // if a is true, do something 
}

// good
if (a === 2) {
  // do sth 
}

// same goes for functions
function b() {
  return (!false);
};

if (b()) {
  // get in here slow
}

if (b() === true) {
  // get in here fast
  // the compiler knows a specific value to compare with
}
로그인 후 복사

인수

인수 사용을 피하세요. 가능한 한 [index] 방법을 사용하여 매개변수를 얻고, 들어오는 매개변수 변수를 수정하지 않도록 하세요:

function mul(a, b) {
  return (arguments[0]*arguments[1]); // bad, very slow
  return (a*b); // good
};

function test(a, b) {
  a = 5; // bad, dont modify argument identifiers
  let tmp = a; // good
  tmp *= 2; // we can now modify our fake 'a'
};
로그인 후 복사

독성: 이 키워드는 독성이 있습니다

독성

여러 구문 아래 나열된 기능은 최적화 프로세스에 영향을 미칩니다.

  • 평가

  • with

  • try/catch

동시에 함수 선언이나 함수 내 클로저 선언을 피하세요. 이로 인해 다수의 작업에서 너무 많은 가비지 수집 작업이 발생할 수 있습니다.

객체

객체 인스턴스는 일반적으로 암시적 클래스를 공유하므로 인스턴스의 정의되지 않은 변수에 액세스하거나 값을 설정하면 암시적 클래스가 생성됩니다.

// our hidden class 'hc_0'
class Vector {
  constructor(x, y) {
    // compiler finds and expects member declarations here
    this.x = x;
    this.y = y;
  }
};

// both vector objects share hidden class 'hc_0'
let vec1 = new Vector(0, 0);
let vec2 = new Vector(2, 2);

// bad, vec2 got hidden class 'hc_1' now
vec2.z = 0;

// good, compiler knows this member
vec2.x = 1;
로그인 후 복사

루프

계산된 배열 길이 값을 최대한 캐시하고 단일 유형을 최대한 동일한 배열에 저장합니다. for-in 구문을 사용하여 배열을 반복하는 것은 매우 느리기 때문에 피하세요. 또한, 루프 내에서 continue 및 break 문의 성능도 좋기 때문에 사용 시에는 이에 대해 걱정하지 않으셔도 됩니다. 또한 짧은 논리 부분을 가능한 한 독립적인 기능으로 분할하면 컴파일러 최적화에 더 도움이 됩니다. 또한 접두사 자동 증가 표현식을 사용하면 성능이 약간 향상될 수도 있습니다. (i++ 대신 ++i)

let badarray = [1, true, 0]; // bad, dont mix types
let array = [1, 0, 1]; // happy compiler

// bad choice
for (let key in array) {
  
};

// better
// but always try to cache the array size
let i = 0;
for (; i < array.length; ++i) {
  key = array[i];
};

// good
let i = 0;
let key = null;
let length = array.length;
for (; i < length; ++i) {
  key = array[i];
};
로그인 후 복사

drawImage

draeImage 함수는 가장 빠른 2D 캔버스 API 중 하나이지만 편의상 모든 매개변수가 생략되었는지 주의해야 합니다. . , 성능 손실도 증가합니다:

// bad
ctx.drawImage(
  img,
  x, y
);

// good
ctx.drawImage(
  img,
  // clipping
  sx, sy,
  sw, sh,
  // actual stuff
  x, y,
  w, h
);

// much hax
// no subpixel rendering by passing integers
ctx.drawImage(
  img,
  sx|0, sy|0,
  sw|0, sh|0,
  x|0, y|0,
  w|0, h|0
);
로그인 후 복사

위 내용은 고성능 JavaScript 작성 내용이며, 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php)를 참고해주세요. .cn)!


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿