6

サーバーからmp3ファイルを順番にダウンロードし、サーバーに一時的に保存してから、クライアントに直接ストリーミングするアプリケーションがあります。

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によって解放されていない多くのバッファーを作成しているようです。「free-M」コマンドを実行すると、次のようになります(アプリを実行してから約4時間後)。

                   total      used       free     shared    buffers     cached
              Mem: 750        675         75          0         12        180
-/+ buffers/cache:            481        269
             Swap: 255        112        143

'buffers'の下の数は(キャッシュされたメモリと同様に)絶えず増加し、OSは明らかにその180mbを再利用しません。最終的に、トラックのビットレートを確認するために小さなプロセスを生成しようとすると、アプリがメモリを使い果たしてクラッシュします。 、サンプリングレート、id3情報など。

私は多くの異なるツール(memwatchやnodetimeなど)を使用して、それが内部メモリリークであるかどうかを確認しましたが、そうではない場合、V8メモリヒープとノードRSSは+/- 10mb変動しますが、一定のままですほとんどの場合、OSの空きメモリがどんどん少なくなっています(ノードプロセスが開始されると、約350MBの空きメモリがあります)。

Nodeによって割り当てられたBufferインスタンスがrawメモリに直接アクセスできるため、V8にはそれらに対するパワーがないことをどこかで読みました(V8ヒープからメモリリークが発生していないことを確認します)。これらの古いバッファを取り除く方法が必要です。これは可能ですか?または、5時間ごとにアプリを再起動する必要がありますか(さらに悪いことに、RAMを追加購入する必要があります!)?

PS。Ubuntu10.04でNodev0.8.16を実行しています。

4

2 に答える 2

2

私はTiagoに同意します。これは、コードの再帰的な性質が原因だと思います。あなたが言ったように、ストリーム変数は反復ごとに新しいReadStreamで再割り当てされているので、ストリームがヒープを食いつぶしているとは思いません。ただし、2行目のhttp.getの要求と応答(およびそれらが使用するバッファー)は、次の反復を呼び出す前に解放されることはありません。それらはdownloadNextTrack関数内でスコープされます。最終的に、ファイルごとに一連の要求オブジェクトと応答オブジェクト(およびいくつかの基礎となるバッファー)を持つ再帰的なスタックトレースが作成されます。

一般に、このコードを何度も実行する必要がある場合は、再帰をオプトアウトしてすべてを繰り返し実行してみませんか?終わりのない再帰は、プログラムがクラッシュするまで、たとえメモリリークがない場合でも、常にますます多くのメモリを消費します。

于 2013-01-03T17:36:12.253 に答える
0

これを読んでください:http ://www.linuxatemyram.com

バッファキャッシュは、iノードとデント(ファイルシステム構造)用のキャッシュです。そのメモリは引き続きプロセスで使用できます。あなたはこれを気にするべきではありません。

于 2016-03-02T03:00:29.360 に答える