質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

2233閲覧

クラスのメモリ解放方法

退会済みユーザー

退会済みユーザー

総合スコア0

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

メモリリーク

メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2021/12/14 09:21

一定時間の周期で複数のクラスを一時的に利用する単純なスクリプトです。
※複数のクラスのoptionsはそれぞれ別のものとします。

js

1 2(function update() { 3 4 // いろいろ 5 6 for (let i = 0; i < 20/*変動値*/; i++) { 7 const hoge = new HogeHoge(options); 8 // メモリ解放処理をしたい 9 } 10 11 setTimeout(update, (1000 * 10)); 12 13})();

クラスを大量に利用し、それを破棄したいのですが、以下のグラフの通りメモリ解放が正常にできなくなってしまいます。
メモリグラフ
スクリーンショットした時間が悪くて分かりづらくて申し訳ないのですが、左から2本目の破線からがテスト実行開始時間です。
また、そこから急激にメモリ使用量が減少しているのは、メモリを大量に使用しすぎてプロセスが再起動してそうなっています。
一時的に利用したいクラスなので、それを破棄するような処理が必要なのですが、どういった処理を記述すればよろしいでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

落ちてる原因って本当にメモリ不足なんですかね?

そりゃいつかはメモリ解放出来ずに死ぬとは思いますが、
これ再帰関数みたいな無限ループみたいになってて
スコープを作り続けるから5桁回数回るくらいまででエラー吐いて落ちるんじゃないですか?


さて、解決にあたってですが
setIntervalが使えれば話は早いですが、
update処理の実行にもたつくと2回、3回と溜まってしまうのが悩みどころ

コールバック関数の仕組みだけで
このパターンを解消するのはちとしんどいですね。
骨子はこんな感じ?

js

1const id = (() => { 2 let ready = true; 3 return setInterval( 4 () => { 5 if (!ready) return; 6 ready = false; 7 update(); 8 setTimeout(() => ready = true, (10 * 1000)); 9 }, 10 50 11 ); 12)(); 13 14// 止めたくなったらこれを実行すればお行儀よく停止できそう 15process.on("SIGINT", () => { 16 creaInterval(id); 17});

そこでわかり易さ重視で
Promise→async/awaitを併用したパターンで作ってみました。

js

1// 覚えさせたいデータがあれば外のスコープに変数を準備 2const state = { 3 foo: null, 4 update: true, 5}; 6 7// async関数を定義して返り値をPromiseにする 8const update = async () => { 9 // こんな感じで値を書き出す 10 state.foo = []; 11 12 for (let i = 0; i < 20/*変動値*/; i++) { 13 const hoge = new HogeHoge(options); 14 15 state.foo.push(hoge.awesomeCalc()); 16 } 17} 18 19// setTimeoutをラッピングしたPromise版のsetTimeoutを実装 20const timeout = ms => 21 new Promise(resolve => setTimeout(resolve, ms)); 22 23// asyncのアロー関数を定義して即時実行 24// これによりawait構文を有効にして待てるようにする 25(async () => { 26 while (state.update) { 27 // await Promiseインスタンスと記述すると、 28 // Promiseの動作が全て完了するのを待ってくれる挙動をする 29 await update(); 30 await timeout(1000 * 10); 31 } 32})(); 33 34process.on("SIGINT", () => { 35 state.update = false; 36});

JS・Node.jsのガベージコレクトの動作対象は参照の切れた値です
こうすればスコープがネストせず自然に参照が切れるので、
hoge達はいずれガベージコレクトのお掃除で消えてなくなるかと思います。

投稿2021/12/14 09:36

編集2021/12/14 11:05
miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問