A Deep Dive Into Garbage Collection in JavaScript -1편

🐷Jinie (juniorDeveloper)·2023년 9월 3일
0

영어로개발읽기

목록 보기
2/3

원글 : https://betterprogramming.pub/deep-dive-into-garbage-collection-in-javascript-6881610239a

자바스크립트 책 시리즈를 다 읽고 V8 공식블로그 를 읽고 그것들을 쓰고 추가했다 정확한 것을 위해서.
이 글은 약간의 시간이 너에게 필요할거야. 북마크해두고 나중에 읽어봐 (나는 거의 2주 걸려 끝났어)

여기가 전체적인 이 글의 개요야:

메모리관리개요

전형적으로, 메모리 관리에는 두가지 방법이 있다. 자동과 수동

  • 자동 : GC는 자동메모리 관리의 한 형태이다. 메모리가 더이상 참조되지 않을때, 이것은 GC에 의해서 버려질 것이다.JS, GO, JAVA, Python
  • 수동 : 수동적으로 프로그래머들은 메모리를 관리해야만한다. C/C++

GC의 이점

수동방식에 비해, GC 는 우리의 시간을 아껴준다. 수동적인 메모리 해제로부터 우리를 자유롭게함으로.
게다가, 그것은 이런 메모리 관리 에러를 피하도록 도와줄 수 있다.

따라다니는 포인터들

이것은 메모리가 해제되었는데 여전히 몇몇 포인터들에서 참조되고 있을때.
전형적인 C++ 예시코드 :

#include<stdio.h>


int *call();
int main() {

  int *ptr;
  ptr = call();

  fflush(stdin);
  printf("%d", *ptr);
  return 0;
}

int * call() {
  int x=25;
  ++x;

  return &x;
}

포인터 ptr은 지역변수 x를 가리키는 dangling 포인터이다.
함수가 호출된 후에 x는 죽을거다. 그러나 포인터는 여전히 그 자리를 가리킨다.

중복프리 또는 에러충돌

이것은 일어난다 프로그램이 메모리를 두번 사용하거나 프리할때,
엔티티는 할당되지 않는다.

예를들어,

#include<iostream>

using namespace std;

int main()

{
   int * i = new int();
   delete i;
   //i = NULL; -> 이렇게 해줬어야함
   delete i;
}

너는 이런 에러를 볼 거야:

ERROR: AddressSanitizer: attempting double-free on 0x602000000010 in thread T0:

이 에러를 피하기위해, 프로그래머들은 몇몇 일들을 해야만한다:
1. 포인터에 프리후에 NULL 넣기
2. 프리하기 전에 NULL체크
3. 포인터 시작시 NULL로 시작

Memory leak

메모리 누수는 일어난다 우리가 도달할 수 없는 메모리를 프리해 주지 않을때.
그리고 이 메모리 조각들이 쌓리고, 이것은 메모리를 뻗게 만든다.

여기 메모리릭 코드가 있다:

#include <bits/stdc++.h>
using namespace std;

void func_mem_leak()
{
 int* ptr = new int(5);

 // return without deallocating ptr
 return;
}

int main()
{
 func_mem_leak();

 return 0;
}

이것을 피하기 위해서, 우린 포인터들을 삭제해줘야한다. 새로운 포인터들을위해 그들이 도달하지 않을때 수동적으로.
이것에 대한 예시,

void func_mem_leak()
{
    int* ptr = new int(5);
 
    // delete pointer ptr 
    delete (ptr);
}

GC의 단점

비록 GC의 이점들을 늘어놓았음에도 큰 단점도 따라온다 퍼포먼스에 해로울 수 있는:
첫째, 그것은 컴퓨팅 자원을 소비한다. 프리해 줄 수 있도록 트래킹하고 결정하는데
두번째, GC는 예측할 수 없다. 수동 메모리 관리와 달리, 메모리 할당 해제는 암시적으로 동작하고, 프로그래머의 통제를 벗어난다. 특히 트랜잭션이나 대화형 프로그램과 같은 실시간 환경에서 불필요한 뭔가(stop the world, stalls)를 한다. 비록 우리가 동시간적이고 점진적인 GC 솔루션을 생각해냈지만, 그러나 완전히 제거될 수 없었다.

컴퓨터 과학에서 메모리 관리가 어떻게 수행되는지에 대한 기본적인 이해를 얻은 후에 자바스크립트의 GC로 주제를 좁혀보자.

"메인 컨셉 Reachability"

GC는 모든 object들을 관찰하고 그것들의 unreachable을 제거한다. 그래서 우리는 어떤것이 reachable하고 아닌지 이해할 필요가 있다.

도달할 수 있는 값들이 무엇인가?
간단하게, 접근 가능한 것들을 'reachable'이라한다.
두가지 타입이 있다.

첫번째 타입은'roots' 그리고 이것은 아래를 포함한다:

  • 전역변수
  • 현재 실행 중인 함수, 지역번수, 파라미터들

두번째 타입은 roots의 참조 객체들이다. 예를들어 만약에 전역객체 A가 프로퍼티 B를 참조하면 B 는 reachable 하다.

예시: 상호연결된 가족

상호연결된 객체의 한 에시를 보자. 아래 그래프에 family라는 전역변수가 있고, mother 와 father 라는 두가지 참조를 가진다. 그리고 그들은 각각 서로를 참조한다.
family는 roots. 그리고 father 와 mother는 roots의 참조가된다.

function marry(man, woman) {
  woman.husband = man;
  man.wife = woman;

  return {
    father: man,
    mother: woman
  }
}

let family = marry({
  name: "John"
}, {
  name: "Ann"
});

만약에 너에게 일이 주어진다면: father 객체를 unreachable로 만들어라. 너는 어찌할래?

delete family.father;

코드는 예상과 같이 동작하지 않는다 왜냐하면 father는 두가지 객체에 참조되어진다.family 와 mother.
father를 unreachable하게 만들면 우리는 두 참조를 다 삭제해야한다.

delete family.father;
delete family.mother.husband;


비록 father가 mother를 참조하더라도, 그것은 roots를 참조하지 않으니까 father는 참조되지 않는다.
지금 우리는 접근가능성의 기본적인 이해를 했다, GC 뒤의 알고리즘으로 깊이 파고들어보자!!

profile
ᴘᴇᴛɪᴛs ᴅᴇ́ᴠᴇʟᴏᴘᴘᴇᴜʀ. ᴘʀᴏɢʀᴀᴍᴍᴀᴛɪᴏɴ = ᴘʟᴀɪsɪʀ 💕

0개의 댓글