Node.js 가비지 수집이 작동하는 방법, 코드를 작성할 때 백그라운드에서 수행되는 작업 및 메모리를 확보하는 방법
Node.js를 Scale로 사용 하여 더 큰 Node.js 설치가있는 회사와 Node의 기본 사항을 이미 배운 개발자의 요구에 초점을 맞춤
Node.js 응용 프로그램의 메모리 관리
모든 응용 프로그램이 제대로 작동하려면 메모리가 필요합니다. 메모리 관리는 프로그램이 요청할 때 동적으로 메모리 청크를 할당하는 방법을 제공하며, 더 이상 필요가 없어지면 다시 사용할 수 있도록 메모리 청크를 무료로 할당합니다.
응용 프로그램 수준의 메모리 관리는 수동 또는 자동이 될 수 있습니다. 자동 메모리 관리에는 대개 가비지 수집기가 필요합니다.
다음 코드 조각은 C
수동 메모리 관리를 사용하여 메모리를 할당하는 방법을 보여줍니다 .
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char name[20];
char *description;
strcpy(name, "RisingStack");
// memory allocation
description = malloc( 30 * sizeof(char) );
if( description == NULL ) {
fprintf(stderr, "Error - unable to allocate required memory\n");
} else {
strcpy( description, "Trace by RisingStack is an APM.");
}
printf("Company name = %s\n", name );
printf("Description: %s\n", description );
// release memory
free(description);
}
수동 메모리 관리 에서는 사용 하지 않는 메모리 부분을 비우는 것이 개발자의 책임입니다. 이 방법으로 메모리를 관리하면 응용 프로그램에 몇 가지 주요 버그가 발생할 수 있습니다.
- 사용 된 메모리 공간이 절대로 사용되지 않으면 메모리 누수가 발생합니다.
- 야생 / 매달려있는 포인터 는 객체가 삭제되었지만 포인터가 다시 사용될 때 나타납니다. 심각한 보안 문제는 다른 데이터 구조를 덮어 쓰거나 중요한 정보를 읽을 때 발생할 수 있습니다.
다행히도 Node.js는 가비지 컬렉터와 함께 제공되므로 메모리 할당을 수동으로 관리 할 필요가 없습니다.
가비지 컬렉터의 개념
가비지 수집은 응용 프로그램 메모리를 자동으로 관리하는 방법입니다. 가비지 컬렉터 (GC)의 일은 사용되지 않는 객체 (쓰레기)가 차지하는 메모리를 회수하는 것 입니다. 이것은 John McCarthy가 발명 한 1959 년 LISP에서 처음 사용되었습니다.
GC가 객체가 더 이상 사용되지 않는다는 것을 알 수있는 방법은 다른 객체가 객체를 참조하지 않는다는 것입니다.
가비지 수집 전의 메모리
다음 다이어그램에서는 서로에 대한 참조가있는 객체가 있고 객체에 대한 참조가없는 객체가있는 경우 메모리가 어떻게 보이는지 보여줍니다. 이것들은 가비지 수집기가 수집 할 수있는 개체입니다.
가비지 수집 후 메모리
일단 가비지 수집기가 실행되면 도달 할 수없는 객체가 삭제되고 메모리 공간이 비워집니다.
가비지 수집기 사용의 이점
- 그것은 방지 야생 / 매달려 포인터 버그를,
- 이미 해방 된 공간을 해방 시키려하지 않을 것이며,
- 그것은 어떤 종류의 메모리 유출 로부터 당신 을 보호 할 것 입니다.
물론, 가비지 컬렉터를 사용한다고해서 모든 문제가 해결되는 것은 아니며 메모리 관리를위한 핵심 요소는 아닙니다. 당신이 명심해야 할 것들을 살펴 봅시다!
가비지 수집기를 사용할 때 염두에 두어야 할 사항
- 성능에 미치는 영향 - 무엇이 자유롭게 될지 결정하기 위해 GC는 컴퓨팅 성능을 소비합니다
- 예측할 수없는 노점 - 현대 GC 구현은 "세계에서 멈추는"콜렉션을 피하려고 노력합니다.
Node.js 가비지 컬렉션 및 메모리 관리 실습
가장 쉬운 학습 방법은하는 것입니다. 그래서 다른 코드 스 니펫으로 메모리에서 어떤 일이 일어나는지 보여 드리겠습니다.
스택
스택에는 로컬 변수와 응용 프로그램의 제어 흐름을 정의하는 힙 또는 포인터에 대한 객체에 대한 포인터가 포함되어 있습니다.
다음 예에서 모두 a
와는 b
스택에 배치됩니다.
function add (a, b) {
return a + b
}
add(4, 5)
엔터프라이즈 급 Node.js 개발에 대한 도움이 필요하십니까?
RisingStack의 전문가를 고용하십시오!
힙
힙은 문자열이나 객체와 같은 참조 유형 객체를 저장하는 데 사용됩니다.
Car
다음 코드에서 생성 된 객체는 힙에 배치됩니다.
function Car (opts) {
this.name = opts.name
}
const LightningMcQueen = new Car({name: 'Lightning McQueen'})
이 후, 메모리는 다음과 같이 보입니다.
더 많은 자동차를 추가하고 우리의 기억이 어떻게 생겼는지 보자!
function Car (opts) {
this.name = opts.name
}
const LightningMcQueen = new Car({name: 'Lightning McQueen'})
const SallyCarrera = new Car({name: 'Sally Carrera'})
const Mater = new Car({name: 'Mater'})
GC가 지금 실행되면, 루트는 모든 객체에 대한 참조를 가지므로 아무 것도 해제 될 수 없습니다.
조금 더 재미있게 만들고 자동차에 부품을 추가하십시오!
function Engine (power) {
this.power = power
}
function Car (opts) {
this.name = opts.name
this.engine = new Engine(opts.power)
}
let LightningMcQueen = new Car({name: 'Lightning McQueen', power: 900})
let SallyCarrera = new Car({name: 'Sally Carrera', power: 500})
let Mater = new Car({name: 'Mater', power: 100})
우리가 더 이상 사용하지 Mater
않지만 그것을 재정의하고 다른 가치를 부여한다면 Mater = undefined
어떻게됩니까?
결과적으로 Mater
루트 객체에서 원본 객체에 도달 할 수 없으므로 다음 가비지 컬렉터에서 실행될 때 해제됩니다.
이제 우리는 가비지 수집기의 예상되는 동작에 대한 기본 사항을 이해하고 V8에서 어떻게 구현되는지 살펴 보겠습니다.
가비지 수집 방법
이전 기사 에서 Node.js 가비지 수집 방법의 작동 방식 을 다루었 기 때문에이 기사를 읽는 것이 좋습니다.
여기에서 배우게 될 가장 중요한 것들이 있습니다 :
새로운 공간과 오래된 공간
힙에는 두 개의 주요 세그먼트 인 New Space와 Old Space가 있습니다. 새로운 공간은 새로운 할당이 일어나는 곳입니다. 여기에 쓰레기를 모으는 것이 빠르며 ~ 1-8MB 크기입니다. 새로운 공간에 살고있는 대상을 젊은 세대라고합니다.
올드 스페이스 (Old Space)는 뉴 스페이스 (New Space)에서 콜렉터에서 살아남은 오브젝트가 승격되는 곳으로, 올드 세대 (Old Generation)라고 부릅니다. Old Space에서의 할당은 빠르지 만 콜렉션이 비싸기 때문에 드물게 수행됩니다.
젊은 세대
보통, 젊은 세대의 ~ 20 %는 구세대에 살아남습니다. 구식 공간에서의 수집은 일단 소진되면 시작됩니다. 이렇게하기 위해 V8 엔진은 두 가지 다른 수집 알고리즘을 사용합니다.
청소 및 마크 스윕 컬렉션
청소 컬렉션은 빠르며 Young Generation에서 실행되지만 느린 Mark-Sweep 컬렉션은 구세대에서 실행됩니다.
실제 사례 - 유성 사례 연구
2013 년에 Meteor의 제작자는 메모리 누수에 대한 조사 결과를 발표했습니다. 문제가되는 코드 스 니펫은 다음과 같습니다.
var theThing = null
var replaceThing = function () {
var originalThing = theThing
var unused = function () {
if (originalThing)
console.log("hi")
}
theThing = {
longStr: new Array(1000000).join('*'),
someMethod: function () {
console.log(someMessage)
}
};
};
setInterval(replaceThing, 1000)
음, 클로저가 구현되는 일반적인 방법은 모든 함수 객체가 어휘 범위를 나타내는 사전 스타일 객체에 대한 링크를 가지고 있다는 것입니다. 내부에서 정의 된 두 함수가
replaceThing
실제로 사용 되면 두 함수originalThing
가 동일한 객체를 얻는 것이 중요합니다.originalThing
두 함수가 동일한 어휘 환경을 공유하기 때문입니다. 이제 크롬의 V8 자바 스크립트 엔진은 Meteor 블로그를 통해 어떤 변수도 사용하지 않으면 어휘 환경에서 변수를 유지할 수있을만큼 현명 합니다.
'개발 > Node.JS' 카테고리의 다른 글
Node.js에서 메모리 누수 찾기 (0) | 2018.03.11 |
---|---|
Node.js Internals Deep Dive - 네이티브 Node.js 모듈 작성하기 (0) | 2018.03.11 |
npm - CommonJS & require가 작동하는 방식 (0) | 2018.03.11 |
npm - npm Publishing Tutorial (0) | 2018.03.11 |
npm - npm모범 사례 (0) | 2018.03.11 |