最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

動(dòng)態(tài)內(nèi)存分配導(dǎo)致影響Javascript性能的問(wèn)題

 更新時(shí)間:2018年12月18日 14:44:23   作者:李先靜  
今天小編就為大家分享一篇關(guān)于動(dòng)態(tài)內(nèi)存分配導(dǎo)致影響Javascript性能的問(wèn)題,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧

內(nèi)存分配對(duì)性能的影響是很大的,分配內(nèi)存本身需要時(shí)間,垃圾回收器回收內(nèi)存也需要時(shí)間,所以應(yīng)該盡量避免在堆里分配內(nèi)存。不過(guò)直到最近優(yōu)化HoLa cantk時(shí),我才深刻的體會(huì)到內(nèi)存分配對(duì)性能的影響,其中有一個(gè)關(guān)于arguments的問(wèn)題挺有意思,寫在這里和大家分享一下。

我要做的事情是用webgl實(shí)現(xiàn)canvas的2d API(這個(gè)話題本身也是挺有意思的,有空我們?cè)儆懻?,drawImage是一個(gè)重要的函數(shù),游戲會(huì)頻繁的調(diào)用它,所以它的性能至關(guān)重要。drawImage的參數(shù)個(gè)數(shù)是可變的,它有三種形式:

  • drawImage(image, x, y)
  • drawImage(image, x, y, width, height)
  • drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)

第一個(gè)版本大概是這樣實(shí)現(xiàn)的:

function Context() {
}
Context.prototype.drawImage3 = function(image, x, y) {
  this.drawImage9(image, 0, 0, image.width, image.height, x, y, image.width, image.height);
}
Context.prototype.drawImage5 = function(image, dx, dy, dw, dh) {
  this.drawImage9(image, 0, 0, image.width, image.height, dx, dy, dw, dh);
}
Context.prototype.drawImage9 = function(image, sx, sy, sw, sh, dx, dy, dw, dh) {
  //DO IT
}
Context.prototype.drawImage = function(image, a, b, c, d, e, f, g, h) {
  var n = arguments.length;
  if(n === 3) {
    this.drawImage3(image, a, b);
  }else if(n === 5) {
    this.drawImage5(image, a, b, c, d);
  }else if(n === 9) {
    this.drawImage9(image, a, b, c, d, e, f, g, h);
  }
}

為了方便說(shuō)明問(wèn)題,我把測(cè)試程序獨(dú)立出來(lái):

var image = {width:100, height:200};
var ctx = new Context();
function test() {
  var a = Math.random() * 100;
  var b = Math.random() * 100;
  var c = Math.random() * 100;
  var d = Math.random() * 100;
  var e = Math.random() * 100;
  var f = Math.random() * 100;
  var g = Math.random() * 100;
  var h = Math.random() * 100;
  for(var i = 0; i < 1000; i++) {
    ctx.drawImage(image, a, b);
    ctx.drawImage(image, a, b, c, d);
    ctx.drawImage(image, a, b, c, d, e, f, g, h);
  }
}
window.onload = function() {
  function loop() {
    test();
    requestAnimationFrame(loop);
  }
  requestAnimationFrame(loop);
}

用chrome的Profile查看CPU的使用情況時(shí),我發(fā)現(xiàn)垃圾回收的時(shí)間比例很大,一般在4%以上。當(dāng)時(shí)并沒(méi)有懷疑到drawImage這個(gè)函數(shù),理由很簡(jiǎn)單:

這個(gè)函數(shù)很簡(jiǎn)單,它只是一個(gè)簡(jiǎn)單的分發(fā)函數(shù),而drawImage9的實(shí)現(xiàn)相對(duì)來(lái)說(shuō)要復(fù)雜得多。

這里看不出有動(dòng)態(tài)內(nèi)存分配,也沒(méi)有違背arguments的使用規(guī)則,只是使用了它的length屬性。

加trace_opt和trace_deopt參數(shù)運(yùn)行時(shí),drawImage被優(yōu)化了,而且沒(méi)有被反優(yōu)化出來(lái)。

Chrome的內(nèi)存Profile只能看到?jīng)]有被釋放的對(duì)象,用它查看內(nèi)存泄露比較容易。這里的問(wèn)題并不是泄露,而是分配了然后又釋放了,V8采用的分代垃圾回收器,這種短時(shí)存在的對(duì)象是由年輕代回收器管理器負(fù)責(zé)的,而年輕代回收器使用的半空間(semi-space)算法,這種大量短時(shí)間生存的對(duì)象,很快會(huì)耗盡其中一半空間,這時(shí)回收器需要把存活的對(duì)象拷貝到另外一半空間中,這就會(huì)耗費(fèi)大量時(shí)間,而垃圾回收時(shí)會(huì)暫停JS代碼執(zhí)行,如果能避免動(dòng)態(tài)內(nèi)存分配,減少垃圾回收器的工作時(shí)間,就能提高程序的性能。

沒(méi)法在Chrome里查看動(dòng)態(tài)分配內(nèi)存的地方(呵呵,后面證實(shí)是我的無(wú)知),只好去硬著頭皮看V8 JS引擎的代碼,看看能不能找到頻繁分配內(nèi)存的地方,后來(lái)找到了V8統(tǒng)計(jì)內(nèi)存分配的代碼:

void Heap::OnAllocationEvent(HeapObject* object, int size_in_bytes) {
 HeapProfiler* profiler = isolate_->heap_profiler();
 if (profiler->is_tracking_allocations()) {
  profiler->AllocationEvent(object->address(), size_in_bytes);
 }
 if (FLAG_verify_predictable) {
  ++allocations_count_;
  // Advance synthetic time by making a time request.
  MonotonicallyIncreasingTimeInMs();
  UpdateAllocationsHash(object);
  UpdateAllocationsHash(size_in_bytes);
  if (allocations_count_ % FLAG_dump_allocations_digest_at_alloc == 0) {
   PrintAlloctionsHash();
  }
 }
 if (FLAG_trace_allocation_stack_interval > 0) {
  if (!FLAG_verify_predictable) ++allocations_count_;
  if (allocations_count_ % FLAG_trace_allocation_stack_interval == 0) {
   isolate()->PrintStack(stdout, Isolate::kPrintStackConcise);
  }
 }
}

HeapProfiler已經(jīng)有了內(nèi)存分配的統(tǒng)計(jì)代碼,Chrome里應(yīng)該有對(duì)應(yīng)的接口啊。再去看Chrome的Profile相關(guān)界面,最后發(fā)現(xiàn)需要在設(shè)置里勾選Record heap allocation stack traces,然后使用Record heap allocations功能,查看結(jié)果時(shí)選擇Allocations,可以看到每個(gè)函數(shù)分配內(nèi)存的次數(shù)。有時(shí)一個(gè)問(wèn)題折騰你好久,解決之前百思不得其解,覺得難得不得了,而解決之后忍不住要苦笑,原來(lái)只是一層窗戶紙!

雖然還是不知道導(dǎo)致動(dòng)態(tài)內(nèi)存分配的原因(誰(shuí)知道請(qǐng)告訴我),至少可以想法規(guī)避它:

Context.prototype.drawImage = function() {
  var n = arguments.length;
  if(n === 3) {
    this.drawImage3.apply(this, arguments);
  }else if(n === 5) {
    this.drawImage5.apply(this, arguments);
  }else if(n === 9) {
    this.drawImage9.apply(this, arguments);
  }
}

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接

相關(guān)文章

  • JavaScript兩張圖搞懂原型鏈

    JavaScript兩張圖搞懂原型鏈

    這篇文章主要分享JavaScript的兩張?jiān)玩湀D,我們上一篇文章介紹了JavaScript中的原型,為什么不將原型鏈一起介紹了呢?因?yàn)镴avaScript中的原型鏈?zhǔn)且粋€(gè)難點(diǎn),也是一個(gè)面試必問(wèn)的考點(diǎn),現(xiàn)在就來(lái)學(xué)習(xí)一下具體內(nèi)容吧
    2021-12-12
  • 帶你徹底理解JavaScript中的原型對(duì)象

    帶你徹底理解JavaScript中的原型對(duì)象

    這篇文章主要介紹了帶你徹底理解JavaScript中的原型對(duì)象,文中有詳細(xì)的代碼介紹,對(duì)正在學(xué)習(xí)js的小伙伴們有一定的幫助,需要的朋友可以參考下
    2021-04-04
  • 微信小程序中用WebStorm使用LESS

    微信小程序中用WebStorm使用LESS

    這篇文章主要介紹了微信小程序中用WebStorm使用LESS的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • web?worker在項(xiàng)目中的使用學(xué)習(xí)為項(xiàng)目增加亮點(diǎn)

    web?worker在項(xiàng)目中的使用學(xué)習(xí)為項(xiàng)目增加亮點(diǎn)

    這篇文章主要為大家介紹了web?worker使用學(xué)習(xí)來(lái)為你的項(xiàng)目增加亮點(diǎn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • JavaScript 原型與原型鏈詳情

    JavaScript 原型與原型鏈詳情

    這篇文章主要介紹了JavaScript 原型與原型鏈,JavaScript常被描述為一種基于原型的語(yǔ)言,對(duì)象以其原型為模板、從原型繼承屬性和放法。原型對(duì)象也可能擁有原型,并從中繼承屬性和方法,一層一層以此類推。這種關(guān)系常被稱為原型鏈,帶著簡(jiǎn)單的了解看看下文內(nèi)容具體介紹吧
    2021-10-10
  • 詳解HTML5 使用video標(biāo)簽實(shí)現(xiàn)選擇攝像頭功能

    詳解HTML5 使用video標(biāo)簽實(shí)現(xiàn)選擇攝像頭功能

    這篇文章主要介紹了詳解HTML5 使用video標(biāo)簽實(shí)現(xiàn)選擇攝像頭功能的相關(guān)資料,希望通過(guò)本文能幫助到大家,實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下
    2017-10-10
  • You-Dont-Know-JS詞法作用域及兩種常見的模型學(xué)習(xí)文檔

    You-Dont-Know-JS詞法作用域及兩種常見的模型學(xué)習(xí)文檔

    這篇文章主要為大家介紹了JS?詞法作用域及兩種常見的模型詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Javascript使用integrity屬性進(jìn)行安全驗(yàn)證

    Javascript使用integrity屬性進(jìn)行安全驗(yàn)證

    這篇文章主要介紹了Javascript使用integrity屬性進(jìn)行安全驗(yàn)證,在html中,script標(biāo)簽可以通過(guò)src屬性引入一個(gè)js文件,引入的js文件可以是本地的,也可以是遠(yuǎn)程的,下面我們一起來(lái)看看文章詳細(xì)內(nèi)容
    2021-11-11
  • 微信小程序 require機(jī)制詳解及實(shí)例代碼

    微信小程序 require機(jī)制詳解及實(shí)例代碼

    這篇文章主要介紹了微信小程序 require機(jī)制詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • 微信小程序 開發(fā)之滑塊視圖容器(swiper)詳解及實(shí)例代碼

    微信小程序 開發(fā)之滑塊視圖容器(swiper)詳解及實(shí)例代碼

    這篇文章主要介紹了微信小程序 開發(fā)之滑塊視圖容器(swiper)詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-02-02

最新評(píng)論

独山县| 大足县| 南澳县| 建宁县| 佳木斯市| 广平县| 会东县| 梅河口市| 西和县| 汉寿县| 临沧市| 双流县| 营口市| 巧家县| 苍梧县| 万全县| 秦安县| 黄陵县| 都匀市| 九龙坡区| 大丰市| 凤庆县| 贵南县| 紫阳县| 龙海市| 仙游县| 阿荣旗| 明水县| 清丰县| 松江区| 巴东县| 治县。| 鄂伦春自治旗| 富平县| 连江县| 土默特左旗| 青海省| 侯马市| 永宁县| 永济市| 南平市|