検索
ホームページウェブフロントエンドjsチュートリアルme_javascript スキルから JavaScript のガベージ コレクション メカニズムとメモリ管理を学びます

1. ガベージ コレクション メカニズム - GC

JavaScript には自動ガベージ コレクション メカニズム (GC: Garbage Collection) があり、コードの実行中に使用されるメモリは実行環境が管理する必要があります。

原則: ガベージ コレクターは定期的に (定期的に) 使用されなくなった変数を見つけて、そのメモリを解放します。

JavaScript のガベージ コレクションのメカニズムは非常に単純です。使用されなくなった変数を見つけて、それらが占有しているメモリを解放します。ただし、このプロセスはオーバーヘッドが比較的大きいため、リアルタイムではありません。固定スケジュール に従って一定の時間間隔で定期的に実行 します。

使用されなくなった変数は、ライフサイクルが終了した変数です。もちろん、グローバル変数のライフサイクルは、ブラウザがページをアンロードするまで終了しません。ローカル変数は関数の実行中にのみ存在し、このプロセス中に、値を保存するためにスタックまたはヒープ上のローカル変数に対応するスペースが割り当てられ、その後、これらの変数は関数の終了まで関数内で使用されます。 、そしてクロージャー パッケージ内の内部関数のため、外部関数は終わりと見なすことはできません。

コードを説明しましょう:

function fn1() {
 var obj = {name: 'hanzichi', age: 10};
}

function fn2() {
 var obj = {name:'hanzichi', age: 10};
 return obj;
}

var a = fn1();
var b = fn2();

コードがどのように実行されるかを見てみましょう。まず、fn1 と fn2 という 2 つの関数が定義されています。fn1 が呼び出されると、fn1 の環境に入り、オブジェクト {name: 'hanzichi', age: 10} を保存するためにメモリが開かれます。 fn1 環境が完了すると、このメモリ ブロックは js エンジンのガベージ コレクタによって自動的に解放されます。fn2 が呼び出されるプロセス中に、返されたオブジェクトはグローバル変数 b によってポイントされるため、このメモリ ブロックは解放されないこと。

ここで疑問が生じます: どの変数が役に立たないのでしょうか?したがって、ガベージ コレクターは、どの変数が役に立たないかを追跡し、将来のメモリ再利用に備えて役に立たなくなった変数にマークを付ける必要があります。未使用の変数をマークするために使用される戦略は実装によって異なりますが、一般的にはマークスイープと参照カウントの 2 つの実装があります。参照カウントはあまり一般的には使用されず、マークアンドスイープがより一般的に使用されます。

2. マーククリア

js で最も一般的に使用されるガベージ コレクション方法は、マークのクリアです。たとえば、関数内で変数を宣言することによって、変数が環境に入ると、その変数には「環境に入った」というマークが付けられます。論理的には、環境に入る変数によって占有されているメモリは、実行フローが対応する環境に入るたびに使用される可能性があるため、解放することはできません。そして、変数が環境から離れると、「環境から離れる」とマークされます。

function test(){
 var a = 10 ; //被标记 ,进入环境 
 var b = 20 ; //被标记 ,进入环境
}
test(); //执行完毕 之后 a、b又被标离开环境,被回收。

ガベージ コレクターが実行されると、メモリに保存されているすべての変数にマークが付けられます (もちろん、任意のマーク付け方法を使用できます)。次に、環境内の変数および環境内の変数によって参照される変数のタグ (クロージャ) を削除します。これ以降にマークされた変数は、環境内の変数がこれらの変数にアクセスできなくなるため、削除される変数とみなされます。最後に、ガベージ コレクターはメモリのクリーンアップ作業を完了し、マークされた値を破棄し、それらが占有しているメモリ領域を再利用します。

これまでのところ、IE、Firefox、Opera、Chrome、Safari の JS 実装はすべて、マークアンドスイープ ガベージ コレクション戦略または同様の戦略を使用していますが、ガベージ コレクションの時間間隔は異なります。

3. 参照数

参照カウントの意味は、各値が参照された回数を追跡することです。変数が宣言され、その変数に参照型の値が割り当てられている場合、この値への参照の数は 1 です。同じ値が別の変数に代入されている場合、その値の参照カウントは 1 増加します。逆に、この値への参照を含む変数が別の値を取得すると、この値への参照の数は 1 つ減ります。この値への参照の数が 0 になると、この値にアクセスする方法がなくなったことを意味するため、この値が占有しているメモリ領域を再利用できます。このようにして、次回ガベージ コレクターが実行されるときに、それらの値によって占有されていたメモリが参照カウント 0 で解放されます。

function test(){
 var a = {} ; //a的引用次数为0 
 var b = a ; //a的引用次数加1,为1 
 var c =a; //a的引用次数再加1,为2
 var b ={}; //a的引用次数减1,为1
}

Netscape Navigator3 は、参照カウント戦略を使用した最初のブラウザですが、すぐに循環参照という深刻な問題に遭遇しました。循環参照とは、オブジェクト A にオブジェクト B へのポインターが含まれており、オブジェクト B にもオブジェクト A への参照が含まれていることを意味します。

function fn() {
 var a = {};
 var b = {};
 a.pro = b;
 b.pro = a;
}

fn();

  以上代码a和b的引用次数都是2,fn()执行完毕后,两个对象都已经离开环境,在标记清除方式下是没有问题的,但是在引用计数策略下,因为a和b的引用次数不为0,所以不会被垃圾回收器回收内存,如果fn函数被大量调用,就会造成内存泄露。在IE7与IE8上,内存直线上升。

我们知道,IE中有一部分对象并不是原生js对象。例如,其内存泄露DOM和BOM中的对象就是使用C++以COM对象的形式实现的,而COM对象的垃圾回收机制采用的就是引用计数策略。因此,即使IE的js引擎采用标记清除策略来实现,但js访问的COM对象依然是基于引用计数策略的。换句话说,只要在IE中涉及COM对象,就会存在循环引用的问题。

var element = document.getElementById("some_element");
var myObject = new Object();
myObject.e = element;
element.o = myObject;

  这个例子在一个DOM元素(element)与一个原生js对象(myObject)之间创建了循环引用。其中,变量myObject有一个名为element的属性指向element对象;而变量element也有一个属性名为o回指myObject。由于存在这个循环引用,即使例子中的DOM从页面中移除,它也永远不会被回收。

看上面的例子,有同学回觉得太弱了,谁会做这样无聊的事情,其实我们是不是就在做

window.onload=function outerFunction(){
 var obj = document.getElementById("element");
 obj.onclick=function innerFunction(){};
};

这段代码看起来没什么问题,但是obj引用了document.getElementById(“element”),而document.getElementById(“element”)的onclick方法会引用外部环境中德变量,自然也包括obj,是不是很隐蔽啊。

解决办法

最简单的方式就是自己手工解除循环引用,比如刚才的函数可以这样

myObject.element = null;
element.o = null;


window.onload=function outerFunction(){
 var obj = document.getElementById("element");
 obj.onclick=function innerFunction(){};
 obj=null;
};

変数を null に設定すると、変数とその変数が以前に参照していた値との間の接続が切断されることになります。次回ガベージ コレクターが実行されるときに、これらの値は削除され、それらが占有しているメモリが再利用されます。

IE9 には循環参照による Dom メモリ リークの問題がないことに注意してください。Microsoft が最適化を行ったか、Dom のリサイクル方法が変更された可能性があります。

4. メモリ管理

1. ガベージ コレクションはいつトリガーされますか?

大量のメモリが割り当てられている場合、ガベージ コレクションの間隔を決定することは非常に困難になります。 IE6 のガベージ コレクションは、環境内に 256 個の変数、4096 個のオブジェクト、または 64k の文字列がある場合に、メモリ割り当ての量に基づいて実行されます。これは非常に科学的であり、段落を押す必要はありません。毎回一度だけ呼び出されますが、必要ない場合もあります。オンデマンドで呼び出すのは良いことではないでしょうか?しかし、環境内に非常に多くの変数があり、スクリプトが非常に複雑である場合、これは正常なことですが、その結果、ガベージ コレクターが常に動作しているため、ブラウザーは再生できません。

Microsoft は IE7 で調整を行いました。ガベージ コレクターによって回復されるメモリ割り当て量が占有メモリの 15% 未満の場合、トリガー条件は動的に変更されます。プログラムでは、メモリの大部分が再利用できないことを意味します。このとき、再利用されるメモリの割合が 85% を超えると、ガベージ コレクションのトリガー条件が 2 倍になります。メモリはずっと前にクリーンアップされているはずです。この時点で、トリガー条件を元に戻してください。これにより、ガベージコレクション機能が非常に簡単になります

2. リーズナブルな GC プラン

1) Javascript エンジンの基本的な GC ソリューションは (単純な GC): マークとスイープ、つまり:

  • (1) アクセス可能なすべてのオブジェクトを走査します。
  • (2) アクセスできなくなったオブジェクトをリサイクルします。

2)、GC の欠陥

他の言語と同様、JavaScript の GC 戦略では問題を回避できません。GC 中に他の操作への応答が停止します。これはセキュリティ上の理由によるものです。 JavascriptのGCは100ms以上なので、一般的なアプリケーションでは問題ありませんが、比較的高い継続性が要求されるJSゲームやアニメーションアプリケーションでは厄介です。これは、新しいエンジンが最適化する必要があるものであり、GC によって引き起こされる応答の長い一時停止を回避します。

3)、GC 最適化戦略

Uncle David は主に 2 つの最適化プランを紹介しました。これらは最も重要な 2 つの最適化プランでもあります。

(1) 世代 GC (世代 GC)
これは Java リサイクル戦略の考えと一致しています。その目的は、「一時的」オブジェクトと「永続的」オブジェクトを区別し、より多くの「一時的オブジェクト」領域 (若い世代) と、より少ない「永続的オブジェクト」領域 (テニュア世代) をリサイクルして、毎回走査する必要があるオブジェクトの数を減らすことです。これにより、各 GC にかかる時間が削減されます。写真に示すように:

ここで追加する必要があるのは、tenured 世代オブジェクトの場合、若い世代から tenured 世代への移行という追加のオーバーヘッドがあることです。さらに、それが参照されている場合は、参照ポイントも変更する必要があります。

(2) インクリメンタル GC
このソリューションのアイデアは非常にシンプルです。つまり、「毎回少しずつ処理し、次回も少しずつ処理する、というようにする」というものです。写真に示すように:

この解決策は短時間で完了しますが、中断が多く、頻繁にコンテキストが切り替わるという問題が発生します。

各ソリューションには適用可能なシナリオと欠点があるため、実際のアプリケーションでは、実際の状況に基づいてソリューションが選択されます。

例: (オブジェクト/秒) 比率が低い場合、割り込み実行 GC の頻度は低くなり、多数のオブジェクトが長期間「存続」する場合は単純な GC が低くなります。処理はあまり良くありません。

参考:

上記は JavaScript のガベージ コレクションのメカニズムとメモリ管理に関するものであり、皆さんの学習に役立つことを願っています。

声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

20+道必知必会的Vue面试题(附答案解析)20+道必知必会的Vue面试题(附答案解析)Apr 06, 2021 am 09:41 AM

本篇文章整理了20+Vue面试题分享给大家,同时附上答案解析。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強力な PHP 統合開発環境

mPDF

mPDF

mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

SublimeText3 英語版

SublimeText3 英語版

推奨: Win バージョン、コードプロンプトをサポート!