記事の説明:この記事は、レガオのフロントエンドトレーニングキャンプのメモと経験です。何か問題がある場合は、指摘して教えていただければ幸いです。ありがとうございます。
この記事の内容:
- メモリ管理
- ガベージコレクションと一般的なGCアルゴリズム
- V8エンジンのガベージコレクション
- パフォーマンスツール
- コード最適化の例
1つは、メモリ管理です
-
メモリ:読み取り可能および書き込み可能なユニットで構成され、操作スペースの一部を表します
-
管理:アプリケーションを人為的に操作し、スペースを使用および解放します
-
メモリ管理:開発者は積極的にスペースを申請し、スペースを使用し、スペースを解放します
-
管理プロセス:アプリケーション-使用-リリース
JavaScriptでのメモリ管理
- メモリスペースを要求する
-
メモリスペースを使用する
-
メモリスペースを解放します
//申请
// 在JavaScript中执行引擎中遇到变量定义时自动分配给我们一个相应的空间,相当于定义一个变量:
let obj = {}
//使用,相当于读取的操作
obj.name = 'lg'
//释放
obj = null
//相当于按照内存管理的流程去实现这样一个内存管理
2.JavaScriptでのガベージコレクション
-
JavaScriptのメモリ管理は自動です。オブジェクト、配列、または関数を作成するたびに、一定量のメモリスペースが自動的に割り当てられます。その後のコードの実行中に、参照関係でオブジェクトが見つからない場合、これらのオブジェクトガベージと見なされるか、これらのオブジェクトは実際にはすでに存在しますが、コード内の不適切な構文または構造エラーのため、そのようなオブジェクトを再度見つけることはできません。このオブジェクトはガベージとも呼ばれます。
-
参照されなくなったオブジェクトはゴミです
-
オブジェクトはルートからアクセスできず、ガベージです
JavaScriptエンジンは、上記のガベージメモリをリサイクルします
JavaScriptで到達可能なオブジェクト:
- アクセスできるオブジェクトは、到達可能なオブジェクト(参照、スコープチェーン)です。
-
到達可能性の基準は、ルートから見つけることができるかどうかです
-
JavaScriptのルートは、グローバル変数オブジェクトとして理解できます
let obj = {name:'xm'}
let ali = obj
obj = null //此时ali 这个对象仍然能够访问到{name:'xm'}这个空间,{name:'xm'}是可达的
function objGroup(obj1,obj2){
obj1.next = obj2
obj2.next = obj1
return {
o1:obj1,
o2:obj2
}
}
let obj = objGroup({name:'obj1'},{name:'obj2'})
console.log(obj)
/*{
o1: { name: 'obj1', next: { name: 'obj2', next: [Circular] } },
o2: { name: 'obj2', next: { name: 'obj1', next: [Circular] } }
}
*/
次の図は、上記のオブジェクトの到達可能性の図です。
上の図は、すべてのオブジェクトにパスでアクセスできることを示しています。次の図に示すように、{name:obj1}のアクセスパスが切断されると、オブジェクトは到達不能になり、ゴミになってリサイクルされます。
3、GCアルゴリズムの紹介
1.GCの定義と役割
- GCはガベージコレクションメカニズムの省略形です
- GCはメモリ内でゴミになり、スペースを解放して再利用する可能性があります
Gcのゴミは何ですか?
- プログラムで不要になったオブジェクト
function func(){
name = 'lg'
return `${name} is a coder`
}
func()//某个数据使用完后上下文不再去用它了,就可以把它当做垃圾来看待,当函数调用完以后,这里已经不再需要name了,根据需求方面考虑被当做垃圾回收
- プログラムでアクセスできなくなったオブジェクト
function func(){
const name = 'lg'
return `${name} is a coder`
}
func()//函数调用完后,外部的空间不能再访问到它了,当我们找不到它的时候,它也可以算作是垃圾
2.GCアルゴリズム
- GCはメカニズムであり、ガベージコレクターは特定の作業を完了します
- 仕事の内容は、ゴミを見つけてスペースを解放し、スペースを取り戻すことです
- アルゴリズムは、職場で見つけてリサイクルするためのルールです
一般的なGCアルゴリズム:
- 参照カウント
- 明確にマークする
- マークアップ
- 世代別コレクション
上記については後で説明します。
3.参照カウントアルゴリズムの実装の原則
- コアアイデア:参照カウンターを設定して、現在の参照カウントが0かどうかを判断します(参照カウントが0の場合、GCは動作を開始し、GCが配置されているオブジェクトスペースはリサイクルされ、再利用のために解放されます)
- 参照カウンター(他のGCアルゴリズムと比較して、参照カウントの実行効率が他のカウントアルゴリズムと異なる場合があるのは、まさに参照カウンターの存在によるものです)
- 参照関係が変更されたときに参照番号を変更します(オブジェクト参照関係が変更された場合、参照カウンターは現在のオブジェクトに対応する参照値をアクティブに変更します。コードにオブジェクトスペースがある場合、現在それを指す変数があります、次にthisその時点で、値に1を追加します。オブジェクトにそれを指す他の変数がある場合は、さらに1を追加します。減少すると、1ずつ減少します。カウントが0に達すると、GCはすぐにそれを再利用します。 。)
- 参照番号が0の場合はすぐにリサイクルしてください
// reference count
const user1 = {age:11}
const user2 = {age:22}
const user3 = {age:33}
const nameList = [user1.age,user2.age,user3.age]//user1到3还被这个数组引用着,不会被回收
function fn(){
const num1 = 1
const num2 = 2
}
fn()//当函数调用完毕后,num1和num2无法被外部使用,引用计数为0会被回收
4.参照カウントアルゴリズムの長所と短所
利点:
- ゴミが見つかったらすぐにリサイクルしてください
- プログラムの一時停止を最小限に抑える:アプリケーションプログラムは実行中に必然的にメモリを消費し、現在の実行プラットフォームのメモリには上限が必要であるため、メモリが確実にいっぱいになると十分ではありません。参照カウントアルゴリズムは常にオブジェクトを参照しているものを監視しているためです。極端な現象は、メモリがいっぱいになりそうになると、参照カウンタが値0のオブジェクト空間をすぐに見つけて解放し、それを確実にすることです。メモリがいっぱいになりません
短所:
- 循環参照オブジェクトを再利用できません
function fn(){
const obj1 = {}
const obj2 = {}
obj1.name = obj2
obj2.name = obj1
return 'lg is a coder'
}
fn()
実行が終了すると、その中のスペースには、obj1やobj2などのスペースのリサイクルが必ず含まれます。グローバルな場所では、それらをポイントしなくなったため、現時点では参照カウントは0であるはずですが、問題があります。この時点で、この関数では、GCに移動してobj1を削除すると、以前のルールではObj1とobj2が見つからないにもかかわらず、obj2にobj1を指す属性があることがわかります。グローバルスコープでは、しかし、そのようなスコープでは明らかに相互誘導関係があるため、この場合、それらの参照カウンターの値は0ではありません。現時点では、参照カウントアルゴリズムの下のGCにはこれらの2つのスペースを再利用すると、オブジェクト間の循環参照であるメモリスペースが無駄になります。
- 時間コストが大きい:現在の参照カウントは値の変更を維持する必要があるため、アルゴリズムの時間コストは大きくなります。この場合、現在のオブジェクトの参照値を変更する必要があるかどうかを常に監視する必要があります。このオブジェクトの値の変更には時間がかかり、オブジェクトが多いと時間がかかります。
5.マーク除去アルゴリズムの実装原理
- コアアイデア:2つの段階で完了する:マークとクリア
- すべてのオブジェクトをトラバースして、アクティブオブジェクトを見つけてマークします。アクティブオブジェクトは到達可能オブジェクトと同じです。この段階では、到達可能なすべてのオブジェクトを見つける必要があります。ここで階層関係が参照されている場合は、戻って検索します。再帰的に、A、Dの順にグローバル検索するプロセスと同じです。検索が完了すると、これらの到達可能なオブジェクトにマークが付けられます。
- すべてのオブジェクトをトラバースして、マークされていないオブジェクトをクリアし、前のステージのマークを消去します。マークが完了したら、クリアを開始し、マークされていないオブジェクトを見つけ、同時にマークをクリアして、リサイクルを完了します。
- 対応するスペースを再利用する:再利用後、スペースは現在の空きリストに配置され、後続のプログラムはここでスペースを直接申請できます。
マーク除去アルゴリズムの利点:
- オブジェクト循環参照のリサイクル操作を解決できます。コードを記述する場合、a、b、cなどの到達可能なオブジェクトをグローバルに定義できますが、関数のローカルスコープもいくつかあります。たとえば、a1は現在function。、b1、およびそれらを相互に参照させます。この種の関数の呼び出しは、終了後に内部空間を解放する必要があります。この場合、関数呼び出しが終了すると、そのローカル空間変数は現在の接続を失います。スコープ内のグローバルグローバルa1とb1は、グローバルグローバルルートの下ではアクセスできません。これは到達不能オブジェクトであり、到達不能オブジェクトはマーキングフェーズでマークされません。2番目のリサイクルフェーズで再利用する場合は、マークされていないオブジェクトを直接見つけます。オブジェクトを作成し、その内部空間をクリアして解放します。この利点は、参照カウントアルゴリズムに関連しています。
マーク除去アルゴリズムのデメリット:
- スペースの断片化:現在リトラクトしているガベージオブジェクトのため、アドレスが連続していません。再生後、隅々まで散らばっています。後で使用したい場合は、万が一、申請します。新しいスペース。サイズにぴったり合っているので、直接使用できます。多かれ少なかれ、使用には適していません。1.5ドメインのスペースがスペースリンクリストに適用されている場合、2つの再利用されたスペースアドレスは一致しません。
第四に、タグソートアルゴリズムの原理
- マーキングは、マーク除去の強化と見なすことができます
- マークフェーズの操作は、マーク除去の操作と同じです。
- クリーニングフェーズでは、最初にクリーンアップされ、オブジェクトの位置が移動されます
リサイクルする前にアクティブオブジェクトにマークを付け、並べ替え時にアクティブオブジェクトを一方の端に移動してから、アクティブオブジェクト以外のメモリを直接解放します。
5、V8を知る
- V8は主流のJavaScript実行エンジンです
- V8はジャストインタイムコンパイルを使用します
- V8メモリ制限(64ビット1.5GB、32ビット700MB)
第六に、V8ガベージコレクション戦略
- 世代別リサイクルのアイデアを採用する:主なことは、特定のルールに従って現在のメモリスペースを2つのカテゴリに分割することです。
- メモリは、若い世代と古い世代のストレージ領域に分けられます
- オブジェクトごとに異なるアルゴリズムを使用する
V8で一般的に使用されるGCアルゴリズム:
- 世代別コレクション
- スペースコピー
- 明確にマークする
- マークアップ
- マークの増分
詳細フォローアップ紹介
7つ目は、V8が若い世代のオブジェクトをどのように回収するか
- V8メモリスペースは2つに分割されます
- 新世代のオブジェクトを格納するために小さなスペースが使用されます(32M | 16M):64ビットオペレーティングシステムは32M、32ビットオペレーティングシステムは16Mです
- 新世代とは、存続期間が短いオブジェクトを指します。たとえば、現在のコードにローカルスコープがあり、このスコープの変数は、実行の完了後にリサイクルする必要があります。グローバルなどの他の場所には、また、変数は、プログラムが終了するまで待機してからリサイクルできるため、新世代は生存期間が短いオブジェクトです。
新世代オブジェクトリサイクルの実装
- リサイクルプロセスはコピーアルゴリズム+マーキングとソートを採用しています
- 新生代の記憶は2つの同じサイズの空間に分割されます。短い生存時間は新生代のオブジェクトと呼ばれます。
- 使用済みスペースはFrom、空きスペースはToです。
- アクティブオブジェクトはFromスペースに保存されます
- マークを付けた後、アクティブオブジェクトをToにコピーします
- スペースを交換してリリースを完了する
リサイクルの詳細
- コピープロセス中にプロモーションが発生する場合があります
- プロモーションは、新世代のオブジェクトを旧世代に移動することです
- GCのラウンドでまだ生きている新世代を促進する必要があります
- Toスペースの使用率が25%を超える:将来のリサイクル操作では、最終的にFromスペースとToスペースを交換する必要があります。前のToがFromになり、FromがToになります。つまり、Toの使用率が80%に達すると、最終的にアクティブオブジェクトのストレージスペースになり、新しいオブジェクトが格納されていないように見えます
V8はどのようにして旧世代のオブジェクトを再利用しますか?
- 老齢物は右側の老人エリアに保管されています
- 64ビットオペレーティングシステム1.4G、32オペレーティングシステム700M
- 旧世代のオブジェクトとは、生存期間が長いオブジェクトを指します
旧世代のオブジェクトリサイクルの実装
- 主にマークの削除、マークの並べ替え、インクリメンタルマークのアルゴリズムを使用します
- まずマークを使ってゴミスペースを片付け、リサイクルを完了します
- タグ付けを使用してスペースを最適化する
- 効率の最適化にインクリメンタルマークを使用する:ガベージコレクションが機能している場合、JavaScriptプログラムの実行が実際にブロックされるため、ギャップ期間が発生します。たとえば、プログラムの実行後、プログラムは停止し、現在のリサイクル操作を実行します。マークの増分は、現在のガベージコレクション全体の操作を複数の小さなステップに分割して、現在のコレクション全体を完了することです。これにより、一度に完了したガベージコレクションが置き換えられます。次の図は非常に明白です。主に、プログラムが以前に実行されたときのガベージコレクションではなく、ガベージコレクションとプログラムの実行を交互に完了するようにします。これにより、時間の消費がより合理的になります。
詳細比較
- 新世代エリアのガベージコレクションは時間のためにスペースを使用します
- 旧世代のガベージコレクションはコピーアルゴリズムには適していません。旧世代のストレージスペースは比較的大きく、2つに分割すると、基本的に数百Mのスペースが無駄になるため、贅沢すぎます。旧世代のストレージエリアにはより多くのオブジェクトデータが保存されており、コピープロセスに時間がかかるため、適切ではありません。
最初にここで共有し、次の記事でパフォーマンスツールを紹介します