서버에서 mp3 파일을 순차적으로 다운로드하여 임시로 서버에 저장 한 다음 클라이언트에 직접 스트리밍하는 응용 프로그램이 있습니다. 나는 '자유 -M'명령을 실행할 때NodeJS : V8 메모리 힙 외부에 할당 된 버퍼를 해제하는 방법
function downloadNextTrack(){
var request = http.get('http://mp3server.com', function(response){
response.on('data', function(data) {
fs.appendFile('sometrack.mp3', data, function (err) {});
});
response.on('end', function(){
streamTrack('sometrack.mp3');
}
});
};
var clients = []; // client response objects are pushed to this array when they request the stream through a route like /stream.mp3
var stream;
function streamTrack(track){
stream = fs.createReadStream(track);
stream.on('data', function(data){
clients.forEach(function(client) {
client.write(data);
});
});
stream.on('end', function(){
downloadNextTrack(); // redoes the same thing with another track
}
};
분명히이 코드는 OS에 의해 해제되지 않는 버퍼를 많이 만드는 것, 이것이 내가 응용 프로그램을 실행하는 약 4 시간 후 (무엇을 얻을) :
total used free shared buffers cached
Mem: 750 675 75 0 12 180
-/+ buffers/cache: 481 269
Swap: 255 112 143
'버퍼'아래의 숫자는 지속적으로 증가합니다 (캐시 에드 메모리) 그리고 운영체제는 결국 180 메가 바이트를 되찾지 못하게 될 것입니다. 결국 내 메모리가 다 떨어지고 트랙의 비트 전송률, 샘플링 속도, ID3 정보 등을 확인하기 위해 작은 프로세스를 생성하려고 할 때까지 충돌이 발생합니다.
나는 내부 메모리 누출인지 아닌지를 알아 내기 위해 memwatch와 nodetime과 같은 많은 도구를 가지고 진단했다. V8 메모리 힙과 Node RSS는 +/- 10mb가 다르지만 일정하게 유지된다. 대부분의 경우 OS free 메모리는 더 낮아지고 낮아집니다 (Node 프로세스가 시작될 때 약 350MB의 여유 메모리가 있음).
노드에 의해 할당 된 버퍼 인스턴스가 원시 메모리에 직접 액세스 할 수 있으므로 V8에 전원이 공급되지 않아 V8 힙에서 메모리 누수가 발생하지 않는 것으로 확인됩니다. 사실,이 오래된 버퍼를 제거 할 방법이 필요합니다. 이것이 가능한가? 아니면 5 시간마다 앱을 다시 시작해야합니까 (아니면 더 많은 RAM을 구입해야합니까).
추신. Ubuntu 10.04에서 Node v0.8.16을 실행하고 있습니다.
안녕하세요, 아마도 이것이 내가 틀렸다면 정정 해줘, 바보 같은 질문이지만 : 순서가 0) 트랙 번호를 다운로드 0 1) 할 때 모든 cliends 2) 마무리 스트림, dwonload에 대한 마무리, 스트림 트랙 # 1 이렇게하면 일종의 재귀입니다, 맞습니까? 첫 번째 호출 'streamTrack'안에는 스트림 변수 (전역 변수)가 있으며 결국에는 'downloadNextTrack'을 호출하고 'streamTrack'을 다른 스트림 변수로 다시 호출합니다. 재귀를 사용하여 호출하면 문제의 원인이 될 수 있습니까? –
프로덕션 코드에서이 스트림 변수는 싱글 톤 (singleton)과 비슷하게 동작하므로 다른 스트림이 시작되면 새로운 readStream에 다시 할당됩니다. 그것은 전역 변수와 같은 역할을하지만 전역 변수 자체는 아닙니다. – pedromtavares
'setTimeout (function() {somefile '};}, 0);'을 사용해보십시오. 그것은 "재귀"오류를 죽일 것이다 (나는 조금 지연된 대답을 알고있다) –