成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

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

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

十余年的尼木網(wǎng)站建設(shè)經(jīng)驗,針對設(shè)計、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。成都營銷網(wǎng)站建設(shè)的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整尼木建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計,從而大程度地提升瀏覽體驗。成都創(chuàng)新互聯(lián)從事“尼木網(wǎng)站設(shè)計”,“尼木網(wǎng)站推廣”以來,每個客戶項目都認真落實執(zhí)行。

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

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

第一個版本大概是這樣實現(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);
  }
}

為了方便說明問題,我把測試程序獨立出來:

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的使用情況時,我發(fā)現(xiàn)垃圾回收的時間比例很大,一般在4%以上。當(dāng)時并沒有懷疑到drawImage這個函數(shù),理由很簡單:

這個函數(shù)很簡單,它只是一個簡單的分發(fā)函數(shù),而drawImage9的實現(xiàn)相對來說要復(fù)雜得多。

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

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

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

沒法在Chrome里查看動態(tài)分配內(nèi)存的地方(呵呵,后面證實是我的無知),只好去硬著頭皮看V8 JS引擎的代碼,看看能不能找到頻繁分配內(nèi)存的地方,后來找到了V8統(tǒng)計內(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)計代碼,Chrome里應(yīng)該有對應(yīng)的接口啊。再去看Chrome的Profile相關(guān)界面,最后發(fā)現(xiàn)需要在設(shè)置里勾選Record heap allocation stack traces,然后使用Record heap allocations功能,查看結(jié)果時選擇Allocations,可以看到每個函數(shù)分配內(nèi)存的次數(shù)。有時一個問題折騰你好久,解決之前百思不得其解,覺得難得不得了,而解決之后忍不住要苦笑,原來只是一層窗戶紙!

雖然還是不知道導(dǎo)致動態(tài)內(nèi)存分配的原因(誰知道請告訴我),至少可以想法規(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é)

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

文章名稱:動態(tài)內(nèi)存分配導(dǎo)致影響Javascript性能的問題
網(wǎng)站網(wǎng)址:http://jinyejixie.com/article12/gpihgc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、外貿(mào)建站、網(wǎng)站策劃、網(wǎng)頁設(shè)計公司、網(wǎng)站建設(shè)、網(wǎng)站設(shè)計公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司
韩城市| 察隅县| 文成县| 逊克县| 安吉县| 额济纳旗| 三明市| 上高县| 方山县| 肃北| 方山县| 雷州市| 北宁市| 宝兴县| 黑河市| 剑阁县| 通州市| 罗江县| 淳安县| 冷水江市| 巢湖市| 茂名市| 桂平市| 陵川县| 宝丰县| 当阳市| 苍溪县| 上思县| 云龙县| 贞丰县| 阆中市| 武宣县| 甘孜县| 思茅市| 唐河县| 阳江市| 惠安县| 鸡泽县| 南岸区| 泰宁县| 万州区|