JavaScript의 성능 최적화 1

기사 설명 : 본 기사는 레가 오 프론트 엔드 트레이닝 캠프의 경험담입니다. 뭔가 잘못된 점이 있으면 지적 해주시고 가르쳐 주시길 바랍니다. 감사합니다!

 이 기사의 내용 :

  • 메모리 관리
  • 가비지 수집 및 일반 GC 알고리즘
  • V8 엔진의 가비지 콜렉션
  • 성능 도구
  • 코드 최적화 예

하나, 메모리 관리

  • 메모리 : 읽기 및 쓰기 가능한 단위로 구성되며 작업 공간을 나타냅니다.

  • 관리 : 공간의 응용, 사용 및 해제를 인위적으로 운영

  • 메모리 관리 : 개발자가 적극적으로 공간 신청, 공간 사용 및 공간 해제

  • 관리 프로세스 : 애플리케이션 사용 릴리스

JavaScript의 메모리 관리

  • 메모리 공간 요청
  • 메모리 공간 사용

  • 메모리 공간 확보

//申请
// 在JavaScript中执行引擎中遇到变量定义时自动分配给我们一个相应的空间,相当于定义一个变量:
let obj = {}

//使用,相当于读取的操作
obj.name = 'lg'

//释放 
obj = null 
//相当于按照内存管理的流程去实现这样一个内存管理

2. JavaScript의 가비지 수집

  • JavaScript의 메모리 관리는 자동입니다. 객체, 배열 또는 함수를 생성 할 때마다 일정량의 메모리 공간이 자동으로 할당됩니다. 이후 코드 실행 중에 일부 참조 관계를 통해 일부 객체를 찾을 수없는 경우 이러한 객체가 생성됩니다. 가비지로 간주되거나 이러한 개체가 실제로 이미 존재하지만 코드의 부적절한 구문이나 구조적 오류로 인해 이러한 개체를 다시 찾을 수 없습니다. 개체를 가비지라고도합니다.

  • 더 이상 참조되지 않는 객체는 가비지입니다.

  • 객체는 루트에서 액세스 할 수 없으며 가비지입니다.

JavaScript 엔진은 위의 가비지 메모리를 재활용합니다.

JavaScript에서 접근 할 수있는 개체 :

  • 액세스 할 수있는 개체는 도달 할 수있는 개체 (참조, 범위 체인)입니다.
  • 도달 가능성의 표준은 루트에서 찾을 수 있는지 여부입니다.

  • JavaScript의 루트는 전역 변수 객체로 이해할 수 있습니다.

let obj = {name:'xm'}

let ali = obj 

obj = null //此时ali 这个对象仍然能够访问到{name:'xm'}这个空间,{name:'xm'}是可达的
function objGroup(obj1,obj2){
    obj1.next = obj2
    obj2.next = obj1

    return {
        o1:obj1,
        o2:obj2
    }
}

let obj = objGroup({name:'obj1'},{name:'obj2'})

console.log(obj)
/*{
    o1: { name: 'obj1', next: { name: 'obj2', next: [Circular] } },
    o2: { name: 'obj2', next: { name: 'obj1', next: [Circular] } } 
  }
  */

다음 그림은 위 개체의 도달 가능성 다이어그램입니다.

위의 그림은 경로를 통해 모든 개체에 액세스 할 수 있음을 보여줍니다. 다음 그림과 같이 {name : obj1}의 액세스 경로가 잘 리면 개체에 연결할 수 없게되고 다음 그림과 같이 가비지가되어 재활용됩니다.

세, GC 알고리즘 소개

1. GC 정의 및 역할

  • GC는 가비지 컬렉션 메커니즘의 약어입니다.
  • GC는 메모리에서 쓰레기가 될 수 있으며 공간을 해제하고 회수 할 수 있습니다.

Gc의 쓰레기는 무엇입니까?

  • 프로그램에서 더 이상 필요하지 않은 개체
function func(){
    name = 'lg'
    return `${name} is a coder`
}

func()//某个数据使用完后上下文不再去用它了,就可以把它当做垃圾来看待,当函数调用完以后,这里已经不再需要name了,根据需求方面考虑被当做垃圾回收
  • 프로그램에서 더 이상 액세스 할 수없는 개체
function func(){
    const name = 'lg'
    return `${name} is a coder`
}

func()//函数调用完后,外部的空间不能再访问到它了,当我们找不到它的时候,它也可以算作是垃圾

2. GC 알고리즘

  • GC는 메커니즘이며 가비지 수집기가 특정 작업을 완료합니다.
  • 작업 내용은 쓰레기를 찾아 공간을 확보하고 공간을 되 찾는 것입니다.
  • 알고리즘은 직장에서 찾고 재활용하기위한 규칙입니다.

일반적인 GC 알고리즘 :

  • 참조 횟수
  • 명확한 표시
  • 마크 업
  • 세대 별 컬렉션

위의 내용은 나중에 설명합니다.

3. 참조 카운팅 알고리즘 구현의 원리

  • 핵심 아이디어 : 참조 카운터를 설정하여 현재 참조 횟수가 0인지 확인 (참조 횟수가 0 일 때 GC가 작동하기 시작하고 위치하는 개체 공간이 재활용되어 재사용을 위해 해제 됨)
  • 참조 카운터 (다른 GC 알고리즘과 비교할 때 참조 카운터가 있기 때문에 참조 카운터의 실행 효율성이 다른 카운팅 알고리즘과 다를 수 있음)
  • 참조 관계가 변경되면 참조 번호를 수정합니다 (개체 참조 관계가 변경되면 참조 카운터가 현재 개체에 해당하는 참조 값을 적극적으로 수정합니다. 코드에 개체 공간이 있으면 현재이를 가리키는 변수가 있습니다.) , then this 이때 값에 하나를 더합니다. 객체에 다른 변수가 있으면 하나 더 추가합니다. 감소하면 1 씩 감소합니다. 카운트가 0에 도달하면 GC가 즉시이를 회수합니다. .)
  • 참조 번호가 0이면 즉시 재활용
// reference count

const user1 = {age:11}
const user2 = {age:22}
const user3 = {age:33}

const nameList = [user1.age,user2.age,user3.age]//user1到3还被这个数组引用着,不会被回收

function fn(){
    const num1 = 1
    const num2 = 2
}

fn()//当函数调用完毕后,num1和num2无法被外部使用,引用计数为0会被回收

4. 참조 카운팅 알고리즘의 장단점

이점:

  • 쓰레기가 발견되면 즉시 재활용하십시오.
  • 프로그램 일시 중지 최소화 : 응용 프로그램은 실행 중에 필연적으로 메모리를 소비하고 현재 실행 플랫폼의 메모리에는 상한이 있어야하므로 메모리가 확실히 가득 차면 충분하지 않습니다. 참조 카운팅 알고리즘은 항상 객체를 참조하는 항목을 모니터링하기 때문입니다. 0의 숫자로, 그래서 우리는 생각합니다 : 극단적 인 현상은 메모리가 꽉 찼을 때 참조 카운터가 즉시 0의 값을 가진 객체 공간을 찾은 다음 해제하여 메모리가 꽉 차지 않습니다

단점 :

  • 순환 참조 된 개체를 회수 할 수 없습니다.
function fn(){
    const obj1 = {}
    const obj2 = {}

    obj1.name = obj2
    obj2.name = obj1

    return 'lg is a coder'
}

fn()

실행이 끝나면 내부 공간은 분명히 obj1 및 obj2와 같은 공간 재활용을 수반합니다. 글로벌 위치에서는 더 이상 가리 키지 않으므로 현재 참조 횟수는 0이어야하지만 문제가 있습니다. 이 함수에서 obj1을 삭제하기 위해 GC로 이동하려고 할 때 이전 규칙에 따르면 Obj1 및 obj2를 찾을 수 없지만 obj2에 obj1을 가리키는 속성이 있음을 알 수 있습니다. 글로벌 스코프에서, 그러나 그러한 스코프에서 그들 사이에 명백히 상호 안내 관계가 있기 때문에,이 경우 그들의 참조 카운터의 값은 0이 아닙니다. 현재, 참조 카운팅 알고리즘 아래의 GC는 방법이 없습니다. 이 두 공간을 재 확보하면 객체 간의 순환 참조 인 메모리 공간이 낭비됩니다.

  • 시간 비용이 큼 : 현재 참조 횟수가 값 변경을 유지해야하기 때문에 알고리즘의 시간 비용이 더 커집니다.이 경우 현재 객체의 참조 값을 수정해야하는지 지속적으로 모니터링해야합니다. 값을 수정하는 데 시간이 걸리며, 오브젝트가 많을 경우 시간이 더 많이 소요됩니다.

5. 마크 제거 알고리즘의 구현 원리

  • 핵심 아이디어 : 두 단계로 완료 : 표시 및 지우기
  • 모든 객체를 트래버스하여 활성 객체를 찾아 표시합니다. 활성 객체는 도달 가능한 객체와 동일합니다.이 단계에서는 도달 가능한 모든 객체를 찾아야합니다. 여기에서 계층 관계가 참조되면 돌아가서 검색합니다. A와 D를 찾는 글로벌 프로세스와 마찬가지로 재귀 적으로 수행됩니다. 검색이 완료되면 이러한 도달 가능한 개체가 표시됩니다.

  • 모든 개체를 가로 질러 표시되지 않은 개체를 지우고 이전 단계의 표시를 지 웁니다. 표시가 완료된 후 지우기를 시작하고 표시되지 않은 개체를 찾아 동시에 표시를 지워 재활용을 완료합니다.

  • 해당 공간 재 확보 : 재 확보 후 해당 공간은 현재 사용 가능한 목록에 배치되며 후속 프로그램은 여기에서 공간을 직접 신청할 수 있습니다.

마크 제거 알고리즘의 장점 :

  • 객체 순환 참조의 재활용 작업을 해결할 수 있습니다. 코드를 작성할 때 a, b, c와 같은 도달 가능한 객체가 전역 적으로 정의 될 수 있지만 일부 로컬 함수 범위도 있습니다. 예를 들어, a1은 현재 function., b1, 그리고 서로를 참조하도록합니다. 이러한 종류의 함수에 대한 호출은 종료 후 내부 공간을 해제해야합니다.이 경우 함수 호출이 종료되면 로컬 공간 변수가 현재 연결을 잃게됩니다. 범위의 글로벌 글로벌, a1 및 b1은 글로벌 글로벌 루트 아래에서 액세스 할 수 없으며 도달 할 수없는 객체이며 도달 할 수없는 객체는 마킹 단계에서 표시되지 않습니다. 두 번째 재활용 단계에서 회수 할 때 표시되지 않은 객체를 직접 찾습니다. 개체 및 내부 공간을 정리하고 해제합니다.이 이점은 참조 계산 알고리즘과 관련이 있습니다.

마크 제거 알고리즘의 단점 :

  • 공간 조각화 : 현재 철회중인 쓰레기 개체로 인해 주소가 연속적이지 않습니다. 회수 한 후에는 구석 구석에 흩어져 있습니다. 나중에 사용하고 싶다면 이런 일이 발생하면 신청할 것입니다. 새로운 공간입니다. 크기 만 일치하면 직접 사용할 수 있습니다. 어느 정도만 사용하면 사용하기에 적합하지 않습니다. 공간 링크 목록에 1.5 도메인의 공간이 적용되면 두 개의 재 확보 된 공간 주소가 일치하지 않습니다.

 넷째, 태그 정렬 알고리즘의 원리

  • 마킹은 마크 제거의 향상으로 볼 수 있습니다.
  • 마크 단계의 작업은 마크 제거의 작업과 동일합니다.
  • 청소 단계에서는 먼저 청소되고 개체 위치가 이동합니다.

재활용하기 전에 활성 개체를 표시하고 정렬 할 때 활성 개체를 한쪽 끝으로 이동 한 다음 활성 개체 이외의 메모리를 직접 해제합니다.

다섯, V8 알아보기

  • V8은 주류 JavaScript 실행 엔진입니다.
  • V8은 Just-In-Time 컴파일을 사용합니다.
  • V8 메모리 제한 (64 비트 1.5GB, 32 비트 700MB)

여섯째, V8 가비지 수집 전략

  • 세대 별 재활용 아이디어 채택 : 가장 중요한 것은 특정 규칙에 따라 현재 메모리 공간을 두 가지 범주로 나누는 것입니다.
  • 기억은 젊은 세대와 구세대 저장 공간으로 나뉩니다.
  • 객체마다 다른 알고리즘 사용

V8에서 일반적으로 사용되는 GC 알고리즘 :

  • 세대 별 컬렉션
  • 공간 복사
  • 명확한 표시
  • 마크 업
  • 증분 표시

세부 사항 후속 소개

일곱, V8은 어떻게 젊은 세대의 물건을 회수합니까?

  • V8 메모리 공간은 두 개로 나뉩니다.
  • 새로운 세대의 개체 (32M | 16M)를 저장하는 데 사용되는 작은 공간 : 64 비트 운영 체제는 32M, 32 비트 운영 체제는 16M
  • 새로운 세대는 생존 시간이 짧은 개체를 참조합니다. 예를 들어 현재 코드에 로컬 범위가 있고이 범위의 변수는 실행이 완료된 후 재활용되어야하며 전역과 같은 다른 위치에서 재활용되어야합니다. 또한 재활용되기 전에 프로그램이 종료 될 때까지 기다려야하는 변수이기도합니다. 따라서 새로운 세대는 생존 시간이 더 짧은 객체입니다.

차세대 개체 재활용 구현

  • 재활용 프로세스는 복사 알고리즘 + 마킹 및 분류를 채택합니다.
  • 신생대 기억은 동일한 크기의 두 공간으로 나뉩니다. 생존 시간이 더 짧은 것을 신생대 물체라고합니다.
  • 사용 된 공간은 From이고 여유 공간은 To입니다.
  • 활성 개체는 시작 공간에 저장됩니다.
  • 표시 후 활성 개체를 대상으로 복사
  • 릴리스를 완료하기 위해 공간을 교환하고 시작합니다.

재활용 세부 정보

  • 복사 프로세스 중에 프로모션이 발생할 수 있습니다.
  • 승진은 신세대의 물건을 구세대로 옮기는 것
  • GC 라운드에서 아직 살아있는 새로운 세대를 홍보해야합니다.
  • To 공간의 사용률이 25 %를 초과합니다. 향후 재활용 작업에서 From 공간과 To 공간이 결국 교환되어야합니다. 이전 To가 From 및 From이됩니다. 즉, To의 사용률이 80 %에 도달하면 마지막으로 활성 개체의 저장 공간이되고 새 개체가 저장되지 않는 것 같습니다.

V8은 이전 세대의 객체를 어떻게 회수합니까?

  • 노년 개체는 오른쪽의 노년 영역에 저장됩니다.
  • 64 비트 운영 체제 1.4G, 32 운영 체제 700M
  • 구세대의 개체는 생존 시간이 더 긴 개체를 나타냅니다.

구세대 개체 재활용 구현

  • 주로 마크 제거, 마크 정렬 및 증분 마크 알고리즘 사용
  • 먼저 마크를 사용하여 쓰레기 공간을 정리하여 재활용을 완료하십시오.
  • 태그 지정을 사용하여 공간 최적화
  • 효율성 최적화를 위해 증분 표시 사용 : 가비지 콜렉션이 작동 중일 때 실제로 JavaScript 프로그램의 실행을 차단하므로 갭 기간이 있습니다. 예를 들어 프로그램이 실행 된 후 현재 재활용 작업을 중지하고 실행합니다. 마크 증분은 현재 전체 가비지 수집 작업을 여러 개의 작은 단계로 분할하여 현재 전체 수집을 완료하여 한 번에 완료 한 가비지 수집을 대체하는 것입니다. 다음 그림은 매우 분명합니다. 주로 프로그램이 이전에 실행되었을 때 가비지 콜렉션 대신 가비지 콜렉션 완료와 프로그램 실행을 번갈아 수행하므로 시간 소비가 더 합리적입니다.

세부 비교

  • 신세대 지역 쓰레기 수거는 시간을 위해 공간을 사용합니다
  • 구세대 영역 가비지 콜렉션은 복사 알고리즘에 적합하지 않습니다. 구세대의 저장 공간은 상대적으로 크고 두 개로 나뉘면 기본적으로 수백 M의 공간이 낭비되므로 너무 사치 스럽습니다. 구세대의 저장 영역에 더 많은 객체 데이터가 저장되어 있고 복사 과정에 많은 시간이 소요되므로 적합하지 않습니다.

먼저 여기에서 공유하고, 다음 기사에서는 성능 도구를 소개합니다.

추천

출처blog.csdn.net/weixin_41962912/article/details/110048339