V8エンジンメモリメカニズム

メモリサイズはオペレーティングシステムに関連しています:64ビット-1.4G32ビット-0.7G

64ビットシステムでの新世代メモリ-64MB旧世代メモリ-1400MB

32ビットシステムでの新世代メモリ-16MB旧世代メモリ-700MB

なぜメモリサイズを制限するのですか?

1.十分に、js設計の本来の意図は、ブラウザのスクリプト言語であり、1回だけ実行してから、メモリを解放します。

2.制限がない場合、100MBのメモリを1回再利用するのに約3msかかります。V8エンジンは、ガベージを再利用するときにすべてのコードの実行を一時停止します。ガベージが多すぎると、メモリを再利用するときの中断時間が長すぎます。経験は良くありません。

新生代の記憶:新しい変数を保存し、短命

古い世代のメモリ:古い変数を保存し、長期間有効にします(古い変数:いくつかのガベージコレクションの後で強制終了されていない変数)

若い世代の変数を古い世代の変数に昇格させるための条件:①この変数はメモリのリサイクルが行われ、回収されていない場合②新しい世代のメモリスペースが占有しきい値を超えると、①の変数は古い世代に移動されます世代メモリ

新世代のメモリの特徴:メモリの回復頻度が速いため、回復動作が速い、つまり持続時間が短いため、時間のスペースを犠牲にするアルゴリズムが採用されています。

ここに画像の説明を挿入します

新生代の記憶回復メカニズム

すべての新しい変数がFromに存在すると仮定すると、リサイクルの過程で、ライブ変数が最初にマークされ、すべてのライブ変数がToにコピーされ、Fromがクリアされます.2回目のリサイクルでは、ライブ変数はマークが付けられ、すべてのライブ変数が削除されます。コピー先とクリア先も次のとおりです。マーク-コピー-クリアのプロセス

旧世代のメモリ回復メカニズム

メモリに連続領域があると仮定します:1、2、3、4、5この時点で2、4は死んでおり、マークを付けて削除した後、メモリは次のようになります:1、-、3、-、5この時点で、データ構造では、配列内の要素がアドレスの連続部分に格納されているため、メモリ空間は連続的ではありません。これは、いわゆるメモリフラグメンテーションであり、パッチが適用されていない場合、配列に収まらない可能性があります。メモリ。そのため、V8エンジンでは、旧世代でマークを削除した後、メモリをデフラグするための準備が必要です。

デッド変数のマーク付け、デッド変数の削除、およびメモリスペースの配置は、mark-delete-organizeのプロセスです。

新世代メモリ:mark-copy-clear(時間とスペースの節約)旧世代メモリ:mark-delete-organize

メモリ再利用のタイミング

ここに画像の説明を挿入します

メモリ使用量がクリティカル値に近づいたら、メモリの再利用を開始します

グローバル変数:プログラムの実行後にのみリサイクルされます。それ以外の場合は、永久に保持されます。

メモリを表示する方法:

ブラウザ:window.performance

コードの一部:Node-process.memoryUsage()

function getMemory() {
    
    
  var memory = process.memoryUsage();
  var format = function(bytes){
    
    
    return (bytes/1024/1024).toFixed(2)+"MB"
  }
  console.log('heapTotal'+ format(memory.heapTotal)+ '        heapUsed'+ format(memory.heapUsed))
}

メモリ使用量を表示する

function getMemory() {
    
    
  var memory = process.memoryUsage();
  var format = function(bytes){
    
    
    return (bytes/1024/1024).toFixed(2)+"MB"
  }
  console.log('heapTotal'+ format(memory.heapTotal)+ '        heapUsed'+ format(memory.heapUsed))
}

var a = []
var size = 20*1024*1024
function b() {
    
    
  var arr1 = new Array(size)
  var arr2 = new Array(size)
  var arr3 = new Array(size)
  var arr4 = new Array(size)
}
b()
getMemory()
setInterval(()=>{
    
    
  a.push(new Array(size))
  getMemory()
},1000)

コンソールでノードxx.jsを実行して、メモリの変更を確認します

メモリの不適切な使用につながりやすいシナリオ:①グローバル変数の乱用②無制限のキャッシュ③大きなファイルを操作する

グローバル変数が必要ない場合は必要ありません。使用する必要がある場合は、使用後にメモリを解放する必要があります。削除する必要はありません。予期しないバグが発生するためです。 strictモードでは、グローバル変数をundefinedに直接設定できます。

通常、キャッシュはグローバル変数も定義し、一部のデータをキャッシュオブジェクトに配置します。これは一般的な方法ですが、永続的な操作である場合は、引き続きキャッシュに配置され、不十分になるリスクがあります。メモリ。したがって、キャッシュに制限を課す必要があります。

キャッシュに制限を課さないシナリオ:

var a = []
var size = 30 * 1024 * 1024
for (let i = 0; i < 16; i++) {
    
    
  a.push(new Array(size))
}

その中で、aはキャッシュオブジェクト、sizeはシミュレートされた配列のサイズです。これは、超大規模配列をaに連続的に配置するループです。16回以内にメモリが不足し、プログラムが続行できなくなる可能性があります。 。

キャッシュを制限します。

var a = []
var size = 30 * 1024 * 1024
for (let i = 0; i < 16; i++) {
    
    
  if(a.length < 4){
    
    
  a.shift()
  }
  a.push(new Array(size))
}

にデータを連続して入れる場合は、判断を加えてください。aに4つ以上の要素がある場合は、最初の要素を削除して、キャッシュが大きくなり続けないようにします。

パフォーマンスの最適化

灯台:Googleのプラグイン

戻りコード:window.performanceには、パブリックテンプレートで使用できる詳細なパフォーマンスデータ情報が含まれており、ajaxまたはその他のメソッドを介してバックエンドモニタリングインターフェイスに送信されます。これらのデータを視覚化するためのバックエンドがあります。

おすすめ

転載: blog.csdn.net/michaelxuzhi___/article/details/106224978