成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

內存溢出分析及解決實踐

開發 項目管理
在項目過程中,如果遇到了某些性能問題可能跟內存泄漏有關時,就可以參照本文方法去排查,一定能找到問題所在并給到解決辦法的。

 

[[407593]]

如果頁面卡頓、或者半夜內存飆升,你覺得可能是什么原因造成的?有什么辦法鎖定原因并解決嗎?(項目常用)

這是一個非常寬泛而又有深度的問題,涉及到很多的頁面性能優化問題,我依稀還記得當初面試被問到這個問題時是這么回答的:

1)先會檢查是否是網絡請求太多,導致數據返回較慢,可以適當做一些緩存;

2)也有可能是某塊資源的bundle太大,可以考慮拆分一下;3)然后排查一下js代碼,是不是某處有過多循環導致占用主線程時間過長;

4)瀏覽器某幀渲染的東西太多,導致的卡頓;

5)在頁面渲染過程中,可能有很多重復的重排重繪;

后來了解到了,感官上的長時間運行頁面卡頓也有可能是因為內存泄漏,內存溢出引起的。

一、內存溢出與內存泄露

1、內存溢出

1)一種程序運行出現的錯誤。

2)當程序運行所需內存超過了計算機剩余的內存時,程序崩潰并拋出內存溢出的錯誤。

例如:系統已經不能再分配出你所需要的空間,比如你需要100M的空間,系統只剩90M了,這就叫內存溢出。

2、內存泄漏

1)指內存被占用且沒有及時釋放。

2)內存泄漏越多,計算機剩余的內存就越小,此時越容易發生內存溢出。

常見的內存泄露情況:

1)意外的全局變量

2)未及時清理計時器或回調函數

3)閉包

例如:用資源的時候為他開辟了一段空間,當你用完時忘記釋放資源了,這時內存還被占用著,一次沒關系,但是內存泄漏次數多了就會導致內存溢出。內存泄漏是導致遲緩,崩潰的根本原因,甚至會導致其他應用問題。

二、垃圾回收機制

垃圾回收機制(GC)

根據內存泄漏的定義,有些變量或數據不再被使用或不需要了,那么它就是垃圾變量或垃圾數據,如果其一直保存在內存中,最終可能會導致內存占用過多的情況。那么此時就需要對這些垃圾數據進行回收,這里引入了垃圾回收機制的概念。

1、GC定義與作用

GC 就是垃圾回收機制的簡寫;

GC 可以找到內存中的垃圾、并釋放和回收空間;

2、GC里的垃圾是什么

1) 程序中不再需要使用對象

 

  1. function func() { 
  2.  name = 'lg' 
  3.   return `${nameis a coder` 
  4. func() 

2) 程序中不再需要使用對象

 

  1. function func() { 
  2.   const name = 'lg' 
  3.   return `${nameis a coder` 
  4. func() 

3、常見 GC 算法- 引用計數

引用計數算法實現原理

引用計數算法(重要)

  • 核心思想:設置引用數,判斷當前引用數是否為 0;
  • 引用計數器;
  • 引用關系改變時修改引用數字;
  • 引用數字為0時立即回收;

 

  1. const user1 = {age: 11} 
  2. const user2 = {age: 22} 
  3. const user3 = {age: 33} 
  4.  
  5. const nameList = [user1.age, user2.age, user3.age] 
  6.  
  7. function fn() { 
  8.  const num1 = 1; 
  9.   const num2 = 2; 
  10. fn(); 

說明:fn() 的num1,num2會被回收。

4、常見 GC 算法- 標記清除

標記清除算法實現原理

  • 核心思想:分標記和清除二個階段完成;
  • 遍歷所有對象找標記活動對象;
  • 遍歷所有對象清除沒有標記對象;
  • 回收相應的空間;

 

  1. function speakLines(){ 
  2.   let night="天黑";//做個標記 ,進入環境  
  3.   let closeEyes="閉眼";//做個標記 ,進入環境  
  4.   let speak=`開始狼人殺,${night}請${closeEyes}`;//做個標記 ,進入環境  
  5.   console.log(speak); 
  6. speakLines() //代碼執行完畢  里面被標記過的變量,又被標記 離開環境 最后被回收 

三、V8引擎- node內存溢出

用戶反饋的說是半夜沒人用的時候內存飆升了,node內存的溢出的問題分析。

1、先期排查(重要)

先期排查的內容,信息如下:

1) 日志:數據分析大小,內存溢出日志。

2) 監控:開啟Sentry監控,Sonar代碼質量,阿里云監控。

1) 報錯日志

a. 數據分析

 

 

 

 

b. 報錯日志

 

  1. 2021-05-13 22:26:48:198S: FATAL ERROR:  
  2. CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 
  3.  
  4. 2021-05-15 00:18:33:670S: FATAL ERROR:  
  5. Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory 

2、問題分析 (重要)

1) V8引擎對Node.js(和Chrome V8)中的內存限制大小。

2) 代碼分析:內存泄漏出現情況(重要)

  • redis服務(沒有使用去掉);
  • 無用的node安裝依賴包;
  • node的回收機制沒有開啟;
  • websocket機制;
  • socket在node里面是否銷毀;
  • node端是否存儲了api返回的數據(導致內存溢出);
  • node代理的時候是否發送給dns,或者帶域名的地址(網絡慢導致代理失敗);

3、Nodejs內存 - 擴大容量

V8引擎對Node.js(和Chrome V8)中的內存限制大小。

原因

因為在Node中,通過JavaScript使用內存時只能使用部分內存(64位系統:1.4 GB,32位系統:0.7 GB),這個時候,如果前端項目非常的龐大,Webpack編譯時就會占用很多的系統資源,如果超出了V8引擎對Node默認的內存限制大小時,就會產生內存溢出的錯誤。

解決方案一:通過 package.json 中的 "build" 加大內存

 

  1. "scripts": { 
  2.     "dev""node build/dev-server.js"
  3.     "start""node build/dev-server.js"
  4.     "build""set NODE_ENV=production && node --max_old_space_size=4096 build/build.js"
  5.     "e2e""node test/e2e/runner.js"
  6.     "test""npm run e2e" 
  7.   }, 

解決方案二:安裝插件,加大內存

第一步:在packagejson里添加這兩個插件

 

  1. npm install -g increase-memory-limit 
  2. npm install cross-env 

第二步:在package.json里的scripts里進行配置

 

  1. "scripts": { 
  2.     "fix-memory-limit""cross-env LIMIT=8192 increase-memory-limit" 
  3.   }, 

LIMIT是你想分配的內存大小,這里的8192單位是M也就是8G(具體的大小根據實際情況而定);

第三步:

 

  1. npm run fix-memory-limit 

*說明:增加內存限制大小,并不能夠實質解決問題。

擴展知識

1、認識 V8

  • V8 是一款主流的 JavaScript 執行引擎
  • V8 采用即時編譯
  • V8 內存設限

因為在Node中,通過JavaScript使用內存時只能使用部分內存(64位系統:1.4 GB,32位系統:0.7 GB)

2、V8 垃圾回收策略

  • 采用分代回收的思想
  • 內存分為新生代、老生代
  • 針對不同對象采用不同算法

3、V8 如何回收新生代對象

  • V8內存分配
  • V8內存空間一分為二
  • 小空間用于存儲新生代對象(32M | 16M)
  • 新生代指的是存活時間較短的對象

V8 內存分配

 

 

 

 

新生代對象回收實現

  • 回收過程采用復制算法 + 標記整理
  • 新生代內存區分為二個等大小空間
  • 使用空間為 From,空閑空間為 To
  • 活動對象存儲于 From 空間
  • 標記整理后將活動對象拷貝至 To
  • From 與 To 交換空間完成釋放

回收細節說明

  • 拷貝過程中可能出現晉升
  • 晉升就是將新生代對象移動至老生代
  • 一輪 GC 還存活的新生代需要晉升
  • To 空間的使用率超過 25%

4、V8 如何回收老生代對象

老年代對象說明

  • 老年代對象存放在右側老生代區域
  • 64位操作系統1.4G,32操作系統 700M
  • 老年代對象就是指存活時間較長的對象

老年代對象回收實現

  • 主要采用標記清除、標記整理、增量標記算法
  • 首先使用標記清除完成垃圾空間的回收
  • 采用標記整理進行空間優化
  • 采用增量標記進行效率優化

細節對比

  • 新生代區域垃圾回收使用空間換時間
  • 老生代區域垃圾回收不適合復制算法

標記增量如何優化垃圾回收

 

 

 

 

四、Chrome devTools查看內存情況

監控內存的幾種方式(重要)

  • 瀏覽器任務管理器
  • Timeline 時序圖記錄
  • 堆快照查找分離 DOM
  • 判斷是否存在頻繁的垃圾回收

chrome內存泄露、內存泄漏分析工具

內存分析使用的工具包括chrome任務管理器、chrome時間軸(低版本是Timeline,高版本對應performance)、chrome memory(低版本是chrome profiles,主要用JS堆快照、JS堆動態分配時間軸)。

1) 使用Chrome任務管理器,了解網頁使用的內存量。

2) 使用時間軸記錄可視化內存使用。

3) 使用堆快照標識分離的DOM樹(內存泄漏的常見原因)。

4) 通過堆動態分配時間軸記錄了解在JS堆中分配及回收情況。

首先打開Chrome的無痕模式,這樣做的目的是為了屏蔽掉Chrome插件對我們之后測試內存占用情況的影響。

 

 

 

 

然后打開開發者工具,找到Performance這一欄,可以看到其內部帶著一些功能按鈕,例如:開始錄制按鈕;刷新頁面按鈕;清空記錄按鈕;記錄并可視化js內存、節點、事件監聽器按鈕;觸發垃圾回收機制按鈕等等。

 

 

 

 

簡單錄制一下百度頁面,看看我們能獲得什么,如下動圖所示:

 

 

 

 

從上圖中我們可以看到,在頁面從零到加載完成這個過程中JS Heap(js堆內存)、documents(文檔)、Nodes(DOM節點)、Listeners(監聽器)、GPU memory(GPU內存)的最低值、最高值以及隨時間的走勢曲線,這也是我們主要關注的點。再來看看開發者工具中的Memory一欄,其主要是用于記錄頁面堆內存的具體情況以及js堆內存隨加載時間線動態的分配情況

 

 

 

 

五、代碼優化

代碼優化介紹(重要)

  • JavaScript中的內存管理自動完成;
  • 執行引擎會使用不同的 GC 算法;
  • 算法工作的目的是為了實現內存空間良性循環;
  • Performance 工具監測內存變化;
  • JavaScript 是單線程機制的解釋型語言;

 遞歸導致內存溢出 (函數執行中再次調用自己執行)

 

  1. // 下面案例是“死遞歸”  Uncaught RangeError: Maximum call stack size exceeded “內存溢出” 
  2. function fn(x) { 
  3.     // console.log(x); 
  4.     fn(x + 1); 
  5. fn(1);  

雖然JavaScript會自動垃圾收集,但是如果我們的代碼沒有及時清空一些被調用的東西,就會讓變量一直處于無法回收狀態。

 全局變量引起

 

  1. function leaks(){   
  2.     leak = 'xxxxxx';//leak 成為一個全局變量,不會被回收 

 閉包

 

  1. var leaks = (function(){   
  2.     var leak = 'xxxxxx';// 被閉包所引用,不會被回收 
  3.     return function(){ 
  4.         console.log(leak); 
  5.     } 
  6. })() 

 被遺忘的計時器

 

  1. var someResource = getData(); 
  2. setInterval(function() { 
  3.     var node = document.getElementById('Node'); 
  4.     if(node) { 
  5.         // Do stuff with node and someResource. 
  6.         node.innerHTML = JSON.stringify(someResource)); 
  7.     } 
  8. }, 1000); 

 eval 使用

使用eval()函數會帶來安全隱患,eval()函數的作用是返回任意字符串,當作js代碼來處理。

原來代碼:

 

  1. this.formColor = eval('(' + resp.responsePageData.sysColor + ')'); 

 

 

 

 

處理后代碼:

 

  1. this.formColor = JSON.parse(resp.responsePageData.sysColor); 

 

 

 

 

*總結

在項目過程中,如果遇到了某些性能問題可能跟內存泄漏有關時,就可以參照本文方法去排查,一定能找到問題所在并給到解決辦法的。

雖然JavaScript的垃圾回收是自動的,但我們有時也是需要考慮要不要手動清除某些變量的內存占用的,例如你明確某個變量在一定條件下再也不需要,但是還會被外部變量引用導致內存無法得到釋放時,你可以用null對該變量重新賦值就可以在后續垃圾回收階段釋放該變量的內存了。

責任編輯:姜華 來源: 前端學苑
相關推薦

2009-08-18 16:45:50

Tomcat內存溢出

2012-05-29 16:30:33

Tomcat內存溢出

2013-08-02 10:06:36

Android內存溢出

2024-09-09 09:41:03

內存溢出golang開發者

2018-04-17 14:41:41

Java堆內存溢出

2019-08-29 14:29:42

JVM內存 Java

2023-05-29 07:17:48

內存溢出場景

2018-12-20 10:17:35

JVM模型內存溢出

2010-09-26 16:04:48

JVM內存溢出

2021-05-26 08:02:03

ThreadLocal多線程多線程并發安全

2023-09-22 17:34:37

內存remove方法

2009-06-16 11:01:14

Java內存溢出

2012-03-14 10:58:27

Java

2024-03-11 08:22:40

Java內存泄漏

2024-10-24 16:51:08

2021-08-26 05:00:44

生產環境內存

2024-04-11 11:04:05

Redis

2015-03-30 11:18:50

內存管理Android

2024-03-25 12:38:00

MySQL內存參數

2022-07-20 22:55:39

直播OOM抖動
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: www日| 欧美日韩国产一区二区三区不卡 | 成人自拍视频网站 | 精品久久国产视频 | 精品国产乱码久久久 | 懂色tv| 成人免费在线播放视频 | 精品欧美一区二区三区免费观看 | 国产午夜一级 | 欧美一区永久视频免费观看 | 三级av在线 | 91视频在线 | 天天夜碰日日摸日日澡 | 色婷婷综合久久久中文字幕 | 亚洲国产精品激情在线观看 | 精品成人一区二区 | 一区二区三区免费 | 国产精品99久久久久久久久 | 91免费版在线观看 | 啪啪精品| 中文字幕第二十页 | www.日本国产 | 欧美男人天堂 | 久久中文网 | 午夜精品一区二区三区三上悠亚 | 高清国产午夜精品久久久久久 | 久久精品国产清自在天天线 | 久久亚洲一区二区三区四区 | 国产在线视频一区 | 看av片网站 | 国产午夜在线观看 | 色噜噜狠狠色综合中国 | 国产精品毛片一区二区在线看 | 欧美日韩亚洲在线 | 日韩一级黄色毛片 | 国产亚洲第一页 | 91麻豆精品国产91久久久久久久久 | www国产亚洲精品久久网站 | 中国av在线免费观看 | 久久久久久亚洲国产精品 | 亚洲精品电影在线 |