偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

內(nèi)存溢出分析及解決實(shí)踐

開(kāi)發(fā) 項(xiàng)目管理
在項(xiàng)目過(guò)程中,如果遇到了某些性能問(wèn)題可能跟內(nèi)存泄漏有關(guān)時(shí),就可以參照本文方法去排查,一定能找到問(wèn)題所在并給到解決辦法的。

 

[[407593]]

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

這是一個(gè)非常寬泛而又有深度的問(wèn)題,涉及到很多的頁(yè)面性能優(yōu)化問(wèn)題,我依稀還記得當(dāng)初面試被問(wèn)到這個(gè)問(wèn)題時(shí)是這么回答的:

1)先會(huì)檢查是否是網(wǎng)絡(luò)請(qǐng)求太多,導(dǎo)致數(shù)據(jù)返回較慢,可以適當(dāng)做一些緩存;

2)也有可能是某塊資源的bundle太大,可以考慮拆分一下;3)然后排查一下js代碼,是不是某處有過(guò)多循環(huán)導(dǎo)致占用主線程時(shí)間過(guò)長(zhǎng);

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

5)在頁(yè)面渲染過(guò)程中,可能有很多重復(fù)的重排重繪;

后來(lái)了解到了,感官上的長(zhǎng)時(shí)間運(yùn)行頁(yè)面卡頓也有可能是因?yàn)閮?nèi)存泄漏,內(nèi)存溢出引起的。

一、內(nèi)存溢出與內(nèi)存泄露

1、內(nèi)存溢出

1)一種程序運(yùn)行出現(xiàn)的錯(cuò)誤。

2)當(dāng)程序運(yùn)行所需內(nèi)存超過(guò)了計(jì)算機(jī)剩余的內(nèi)存時(shí),程序崩潰并拋出內(nèi)存溢出的錯(cuò)誤。

例如:系統(tǒng)已經(jīng)不能再分配出你所需要的空間,比如你需要100M的空間,系統(tǒng)只剩90M了,這就叫內(nèi)存溢出。

2、內(nèi)存泄漏

1)指內(nèi)存被占用且沒(méi)有及時(shí)釋放。

2)內(nèi)存泄漏越多,計(jì)算機(jī)剩余的內(nèi)存就越小,此時(shí)越容易發(fā)生內(nèi)存溢出。

常見(jiàn)的內(nèi)存泄露情況:

1)意外的全局變量

2)未及時(shí)清理計(jì)時(shí)器或回調(diào)函數(shù)

3)閉包

例如:用資源的時(shí)候?yàn)樗_(kāi)辟了一段空間,當(dāng)你用完時(shí)忘記釋放資源了,這時(shí)內(nèi)存還被占用著,一次沒(méi)關(guān)系,但是內(nèi)存泄漏次數(shù)多了就會(huì)導(dǎo)致內(nèi)存溢出。內(nèi)存泄漏是導(dǎo)致遲緩,崩潰的根本原因,甚至?xí)?dǎo)致其他應(yīng)用問(wèn)題。

二、垃圾回收機(jī)制

垃圾回收機(jī)制(GC)

根據(jù)內(nèi)存泄漏的定義,有些變量或數(shù)據(jù)不再被使用或不需要了,那么它就是垃圾變量或垃圾數(shù)據(jù),如果其一直保存在內(nèi)存中,最終可能會(huì)導(dǎo)致內(nèi)存占用過(guò)多的情況。那么此時(shí)就需要對(duì)這些垃圾數(shù)據(jù)進(jìn)行回收,這里引入了垃圾回收機(jī)制的概念。

1、GC定義與作用

GC 就是垃圾回收機(jī)制的簡(jiǎn)寫(xiě);

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

2、GC里的垃圾是什么

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

 

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

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

 

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

3、常見(jiàn) GC 算法- 引用計(jì)數(shù)

引用計(jì)數(shù)算法實(shí)現(xiàn)原理

引用計(jì)數(shù)算法(重要)

  • 核心思想:設(shè)置引用數(shù),判斷當(dāng)前引用數(shù)是否為 0;
  • 引用計(jì)數(shù)器;
  • 引用關(guān)系改變時(shí)修改引用數(shù)字;
  • 引用數(shù)字為0時(shí)立即回收;

 

  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(); 

說(shuō)明:fn() 的num1,num2會(huì)被回收。

4、常見(jiàn) GC 算法- 標(biāo)記清除

標(biāo)記清除算法實(shí)現(xiàn)原理

  • 核心思想:分標(biāo)記和清除二個(gè)階段完成;
  • 遍歷所有對(duì)象找標(biāo)記活動(dòng)對(duì)象;
  • 遍歷所有對(duì)象清除沒(méi)有標(biāo)記對(duì)象;
  • 回收相應(yīng)的空間;

 

  1. function speakLines(){ 
  2.   let night="天黑";//做個(gè)標(biāo)記 ,進(jìn)入環(huán)境  
  3.   let closeEyes="閉眼";//做個(gè)標(biāo)記 ,進(jìn)入環(huán)境  
  4.   let speak=`開(kāi)始狼人殺,${night}請(qǐng)${closeEyes}`;//做個(gè)標(biāo)記 ,進(jìn)入環(huán)境  
  5.   console.log(speak); 
  6. speakLines() //代碼執(zhí)行完畢  里面被標(biāo)記過(guò)的變量,又被標(biāo)記 離開(kāi)環(huán)境 最后被回收 

三、V8引擎- node內(nèi)存溢出

用戶反饋的說(shuō)是半夜沒(méi)人用的時(shí)候內(nèi)存飆升了,node內(nèi)存的溢出的問(wèn)題分析。

1、先期排查(重要)

先期排查的內(nèi)容,信息如下:

1) 日志:數(shù)據(jù)分析大小,內(nèi)存溢出日志。

2) 監(jiān)控:開(kāi)啟Sentry監(jiān)控,Sonar代碼質(zhì)量,阿里云監(jiān)控。

1) 報(bào)錯(cuò)日志

a. 數(shù)據(jù)分析

 

 

 

 

b. 報(bào)錯(cuò)日志

 

  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、問(wèn)題分析 (重要)

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

2) 代碼分析:內(nèi)存泄漏出現(xiàn)情況(重要)

  • redis服務(wù)(沒(méi)有使用去掉);
  • 無(wú)用的node安裝依賴包;
  • node的回收機(jī)制沒(méi)有開(kāi)啟;
  • websocket機(jī)制;
  • socket在node里面是否銷(xiāo)毀;
  • node端是否存儲(chǔ)了api返回的數(shù)據(jù)(導(dǎo)致內(nèi)存溢出);
  • node代理的時(shí)候是否發(fā)送給dns,或者帶域名的地址(網(wǎng)絡(luò)慢導(dǎo)致代理失敗);

3、Nodejs內(nèi)存 - 擴(kuò)大容量

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

原因

因?yàn)樵贜ode中,通過(guò)JavaScript使用內(nèi)存時(shí)只能使用部分內(nèi)存(64位系統(tǒng):1.4 GB,32位系統(tǒng):0.7 GB),這個(gè)時(shí)候,如果前端項(xiàng)目非常的龐大,Webpack編譯時(shí)就會(huì)占用很多的系統(tǒng)資源,如果超出了V8引擎對(duì)Node默認(rèn)的內(nèi)存限制大小時(shí),就會(huì)產(chǎn)生內(nèi)存溢出的錯(cuò)誤。

解決方案一:通過(guò) package.json 中的 "build" 加大內(nèi)存

 

  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.   }, 

解決方案二:安裝插件,加大內(nèi)存

第一步:在packagejson里添加這兩個(gè)插件

 

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

第二步:在package.json里的scripts里進(jìn)行配置

 

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

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

第三步:

 

  1. npm run fix-memory-limit 

*說(shuō)明:增加內(nèi)存限制大小,并不能夠?qū)嵸|(zhì)解決問(wèn)題。

擴(kuò)展知識(shí)

1、認(rèn)識(shí) V8

  • V8 是一款主流的 JavaScript 執(zhí)行引擎
  • V8 采用即時(shí)編譯
  • V8 內(nèi)存設(shè)限

因?yàn)樵贜ode中,通過(guò)JavaScript使用內(nèi)存時(shí)只能使用部分內(nèi)存(64位系統(tǒng):1.4 GB,32位系統(tǒng):0.7 GB)

2、V8 垃圾回收策略

  • 采用分代回收的思想
  • 內(nèi)存分為新生代、老生代
  • 針對(duì)不同對(duì)象采用不同算法

3、V8 如何回收新生代對(duì)象

  • V8內(nèi)存分配
  • V8內(nèi)存空間一分為二
  • 小空間用于存儲(chǔ)新生代對(duì)象(32M | 16M)
  • 新生代指的是存活時(shí)間較短的對(duì)象

V8 內(nèi)存分配

 

 

 

 

新生代對(duì)象回收實(shí)現(xiàn)

  • 回收過(guò)程采用復(fù)制算法 + 標(biāo)記整理
  • 新生代內(nèi)存區(qū)分為二個(gè)等大小空間
  • 使用空間為 From,空閑空間為 To
  • 活動(dòng)對(duì)象存儲(chǔ)于 From 空間
  • 標(biāo)記整理后將活動(dòng)對(duì)象拷貝至 To
  • From 與 To 交換空間完成釋放

回收細(xì)節(jié)說(shuō)明

  • 拷貝過(guò)程中可能出現(xiàn)晉升
  • 晉升就是將新生代對(duì)象移動(dòng)至老生代
  • 一輪 GC 還存活的新生代需要晉升
  • To 空間的使用率超過(guò) 25%

4、V8 如何回收老生代對(duì)象

老年代對(duì)象說(shuō)明

  • 老年代對(duì)象存放在右側(cè)老生代區(qū)域
  • 64位操作系統(tǒng)1.4G,32操作系統(tǒng) 700M
  • 老年代對(duì)象就是指存活時(shí)間較長(zhǎng)的對(duì)象

老年代對(duì)象回收實(shí)現(xiàn)

  • 主要采用標(biāo)記清除、標(biāo)記整理、增量標(biāo)記算法
  • 首先使用標(biāo)記清除完成垃圾空間的回收
  • 采用標(biāo)記整理進(jìn)行空間優(yōu)化
  • 采用增量標(biāo)記進(jìn)行效率優(yōu)化

細(xì)節(jié)對(duì)比

  • 新生代區(qū)域垃圾回收使用空間換時(shí)間
  • 老生代區(qū)域垃圾回收不適合復(fù)制算法

標(biāo)記增量如何優(yōu)化垃圾回收

 

 

 

 

四、Chrome devTools查看內(nèi)存情況

監(jiān)控內(nèi)存的幾種方式(重要)

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

chrome內(nèi)存泄露、內(nèi)存泄漏分析工具

內(nèi)存分析使用的工具包括chrome任務(wù)管理器、chrome時(shí)間軸(低版本是Timeline,高版本對(duì)應(yīng)performance)、chrome memory(低版本是chrome profiles,主要用JS堆快照、JS堆動(dòng)態(tài)分配時(shí)間軸)。

1) 使用Chrome任務(wù)管理器,了解網(wǎng)頁(yè)使用的內(nèi)存量。

2) 使用時(shí)間軸記錄可視化內(nèi)存使用。

3) 使用堆快照標(biāo)識(shí)分離的DOM樹(shù)(內(nèi)存泄漏的常見(jiàn)原因)。

4) 通過(guò)堆動(dòng)態(tài)分配時(shí)間軸記錄了解在JS堆中分配及回收情況。

首先打開(kāi)Chrome的無(wú)痕模式,這樣做的目的是為了屏蔽掉Chrome插件對(duì)我們之后測(cè)試內(nèi)存占用情況的影響。

 

 

 

 

然后打開(kāi)開(kāi)發(fā)者工具,找到Performance這一欄,可以看到其內(nèi)部帶著一些功能按鈕,例如:開(kāi)始錄制按鈕;刷新頁(yè)面按鈕;清空記錄按鈕;記錄并可視化js內(nèi)存、節(jié)點(diǎn)、事件監(jiān)聽(tīng)器按鈕;觸發(fā)垃圾回收機(jī)制按鈕等等。

 

 

 

 

簡(jiǎn)單錄制一下百度頁(yè)面,看看我們能獲得什么,如下動(dòng)圖所示:

 

 

 

 

從上圖中我們可以看到,在頁(yè)面從零到加載完成這個(gè)過(guò)程中JS Heap(js堆內(nèi)存)、documents(文檔)、Nodes(DOM節(jié)點(diǎn))、Listeners(監(jiān)聽(tīng)器)、GPU memory(GPU內(nèi)存)的最低值、最高值以及隨時(shí)間的走勢(shì)曲線,這也是我們主要關(guān)注的點(diǎn)。再來(lái)看看開(kāi)發(fā)者工具中的Memory一欄,其主要是用于記錄頁(yè)面堆內(nèi)存的具體情況以及js堆內(nèi)存隨加載時(shí)間線動(dòng)態(tài)的分配情況

 

 

 

 

五、代碼優(yōu)化

代碼優(yōu)化介紹(重要)

  • JavaScript中的內(nèi)存管理自動(dòng)完成;
  • 執(zhí)行引擎會(huì)使用不同的 GC 算法;
  • 算法工作的目的是為了實(shí)現(xiàn)內(nèi)存空間良性循環(huán);
  • Performance 工具監(jiān)測(cè)內(nèi)存變化;
  • JavaScript 是單線程機(jī)制的解釋型語(yǔ)言;

 遞歸導(dǎo)致內(nèi)存溢出 (函數(shù)執(zhí)行中再次調(diào)用自己執(zhí)行)

 

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

雖然JavaScript會(huì)自動(dòng)垃圾收集,但是如果我們的代碼沒(méi)有及時(shí)清空一些被調(diào)用的東西,就會(huì)讓變量一直處于無(wú)法回收狀態(tài)。

 全局變量引起

 

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

 閉包

 

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

 被遺忘的計(jì)時(shí)器

 

  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()函數(shù)會(huì)帶來(lái)安全隱患,eval()函數(shù)的作用是返回任意字符串,當(dāng)作js代碼來(lái)處理。

原來(lái)代碼:

 

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

 

 

 

 

處理后代碼:

 

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

 

 

 

 

*總結(jié)

在項(xiàng)目過(guò)程中,如果遇到了某些性能問(wèn)題可能跟內(nèi)存泄漏有關(guān)時(shí),就可以參照本文方法去排查,一定能找到問(wèn)題所在并給到解決辦法的。

雖然JavaScript的垃圾回收是自動(dòng)的,但我們有時(shí)也是需要考慮要不要手動(dòng)清除某些變量的內(nèi)存占用的,例如你明確某個(gè)變量在一定條件下再也不需要,但是還會(huì)被外部變量引用導(dǎo)致內(nèi)存無(wú)法得到釋放時(shí),你可以用null對(duì)該變量重新賦值就可以在后續(xù)垃圾回收階段釋放該變量的內(nèi)存了。

責(zé)任編輯:姜華 來(lái)源: 前端學(xué)苑
相關(guān)推薦

2009-08-18 16:45:50

Tomcat內(nèi)存溢出

2012-05-29 16:30:33

Tomcat內(nèi)存溢出

2013-08-02 10:06:36

Android內(nèi)存溢出

2024-09-09 09:41:03

內(nèi)存溢出golang開(kāi)發(fā)者

2018-04-17 14:41:41

Java堆內(nèi)存溢出

2019-08-29 14:29:42

JVM內(nèi)存 Java

2023-05-29 07:17:48

內(nèi)存溢出場(chǎng)景

2018-12-20 10:17:35

JVM模型內(nèi)存溢出

2010-09-26 16:04:48

JVM內(nèi)存溢出

2021-05-26 08:02:03

ThreadLocal多線程多線程并發(fā)安全

2009-06-16 11:01:14

Java內(nèi)存溢出

2023-09-22 17:34:37

內(nèi)存remove方法

2012-03-14 10:58:27

Java

2024-03-11 08:22:40

Java內(nèi)存泄漏

2024-10-24 16:51:08

2021-08-26 05:00:44

生產(chǎn)環(huán)境內(nèi)存

2024-04-11 11:04:05

Redis

2015-03-30 11:18:50

內(nèi)存管理Android

2024-03-25 12:38:00

MySQL內(nèi)存參數(shù)

2022-07-20 22:55:39

直播OOM抖動(dòng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)