奇怪的JavaScript / Node.js性能问题

时间:2017-03-25 19:29:04

标签: javascript node.js performance

目前我遇到了一个非常奇怪的性能问题。 SlowHeap所需的平均值为1448.623ms,而FastHeap仅需要550.425ms。我已多次看过它,但两者之间的唯一区别是第一个是使用" undefined" _arr开头的元素,第二个元素没有。但是,他们都做同样的操作,等等。我已经验证了下面的代码。

是否有人可以解决这个问题?

let slowHeapOperationCount = 0
let fastHeapOperationCount = 0

let slowHeapExchanged = []
let fastHeapExchanged = []

function SlowHeap(cmp = (a, b) => a > b ? 1 : a < b ? -1 : 0) {
    this.cmp = cmp
    this._arr = [undefined]
    this.size = 0
}
function FastHeap(cmp = (a, b) => a > b ? 1 : a < b ? -1 : 0) {
    this.cmp = cmp
    this._arr = []
    this.size = 0
}

SlowHeap.prototype.bubbleUp = function (cmp, _arr, val) {
    let idxNr = this.size, parentIdxNr = idxNr >> 1
    while (idxNr > 0 && cmp(_arr[parentIdxNr], val) > 0) {
        slowHeapExchanged.push([_arr[parentIdxNr], val])

        _arr[idxNr] = _arr[parentIdxNr]
        _arr[parentIdxNr] = val

        idxNr = parentIdxNr
        parentIdxNr = idxNr >> 1

        slowHeapOperationCount++
    }
}
FastHeap.prototype.bubbleUp = function (cmp, _arr, val) {
    var idxNr = this.size,
        parentIdxNr = ((idxNr - 1) / 2) | 0;

    while (idxNr > 0 && cmp(_arr[parentIdxNr], val) > 0) {
        fastHeapExchanged.push([_arr[parentIdxNr], val])

        _arr[idxNr] = _arr[parentIdxNr];
        _arr[parentIdxNr] = val;

        idxNr = parentIdxNr;
        parentIdxNr = ((idxNr - 1) / 2) | 0;

        fastHeapOperationCount++
    }
}

SlowHeap.prototype.push = function (val) {
    ++this.size
    this._arr.push(val)
    this.bubbleUp(this.cmp, this._arr, val)
    return this.size
}
FastHeap.prototype.push = function (val) {
    this._arr.push(val);
    this.bubbleUp(this.cmp, this._arr, val);
    return ++this.size;
}

const itemCount = 4000000

const slowHeap = new SlowHeap()
const fastHeap = new FastHeap()

//
// Append the same Number Collection to each Heap:
const numberCollection = []

for (let idxNr = 0; idxNr < itemCount; idxNr++) numberCollection.push(Math.random())

//
// Benchmark for the Slow Heap:
console.time('SlowHeap')

for (let idxNr = 0; idxNr < itemCount; idxNr++) {
    slowHeap.push(numberCollection[idxNr])
}

console.timeEnd('SlowHeap')

//
// Benchmark for the Fast Heap:
console.time('FastHeap')

for (let idxNr = 0; idxNr < itemCount; idxNr++) {
    fastHeap.push(numberCollection[idxNr])
}

console.timeEnd('FastHeap')

//
// Verify the "_arr" from the Slow Heap against the Fast Heap:
for (let idxNr = 0; idxNr < itemCount; idxNr++) {
    if (slowHeap._arr[idxNr + 1] !== fastHeap._arr[idxNr]) console.log('Unequal value found!')
}

if (slowHeapExchanged.length !== fastHeapExchanged.length) console.log('Help! Comp. is not equal.')

for (let idxNr = 0, maxNr = slowHeapExchanged.length; idxNr < maxNr; idxNr++) {
    if (slowHeapExchanged[idxNr][0] !== fastHeapExchanged[idxNr][0] || slowHeapExchanged[idxNr][1] !== fastHeapExchanged[idxNr][1]) {
        console.log('Help!')
    }
}

console.log(slowHeapOperationCount)
console.log(fastHeapOperationCount)

1 个答案:

答案 0 :(得分:2)

我对具体细节没有任何了解,但它看起来像是启用/禁用的V8优化:当您使用<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Resposive layout</title> <link rel="stylesheet" type="text/css" href="style.css" /> </head> <body> <div id="header"> <h3> Header area </h3> </div> <div id="wrapper"> <div id="main1"> <div id="leftside"> <h3> Categories </h3> </div> <div id="middle"> <h3> Slider </h3> </div> <div id="rightside"> <h3> Mobile App </h3> </div> </div> <br> <div id="special_discount"> <div id="sp_dis_leftside"> <h3> Mega Discount box </h3> </div> <div id="sp_dis_middle"> <h3> Top Brands </h3> </div> <div id="sp_dis_rightside"> <h3> Crazy Discount </h3> </div> </div> <br> <div id="newsletter"> <h3>Subscribe to Newsletter</h3> </div> <br> <div id="recommended"> <div id="recom_leftside"> <h3> Best for You </h3> </div> <div id="recom_rightside"> <h3> Recommended Products Manual Slider </h3> </div> </div> <br> <div id="ads1"> <h3>Single Product Ads to Buy</h3> </div> <br> <div id="category1"> <div id="cat1_leftside"> <h3> Horizontal Slider Cat 1 </h3> </div> <div id="cat1_rightside"> <h3> </h3> </div> <div id="home_category1_boxes1"> <ol> <h3>Men Dress</h3> </ol> <ol>Men Dress 1</ol> <ol>Men Dress 2</ol> <ol>Men Dress 3</ol> <br> <ol> <h3>Men Accessories</h3> </ol> <ol>Men Accessories1</ol> <ol>Men Accessories2</ol> <ol>Men Accessories3</ol> </div> <div id="home_category1_boxes2"> <img src="images/boxes/cat1/big.jpg" width="376" height="350"></div> <div id="home_category1_boxes3"> <img src="images/boxes/cat1/box1.jpg" width="140px" /> <img src="images/boxes/cat1/box2.jpg" width="140px" /> <img src="images/boxes/cat1/box3.jpg" width="140px" /> <img src="images/boxes/cat1/box4.jpg" width="140px" /> </div> </div> <br> <div id="ads_worldwide"> <h3>Shopping Worldwide</h3> </div> <br> <div id="category2"> <div id="cat2_leftside"> <h3> Horizontal Slider Cat 2 </h3> </div> <div id="cat2_rightside"> <h3> Category 2 Top Brans with 1 big pic and 4 box pics </h3> </div> </div> <br> <div id="ads2"> <h3>Single Product Ads to Buy</h3> </div> <br> <div id="category3"> <div id="cat3_leftside"> <h3> Horizontal Slider Cat 3 </h3> </div> <div id="cat3_rightside"> <h3> Category 3 Top Brans with 1 big pic and 4 box pics </h3> </div> </div> <br> <div id="category4"> <div id="cat4_leftside"> <h3> Horizontal Slider Cat 4 </h3> </div> <div id="cat4_rightside"> <h3> Category 4 Top Brans with 1 big pic and 4 box pics </h3> </div> </div> <br> <div id="ads3"> <h3>Single Product Ads to Buy</h3> </div> <br> <div id="category5"> <div id="cat5_leftside"> <h3> Horizontal Slider Cat 5 </h3> </div> <div id="cat5_rightside"> <h3> Category 5 Top Brans with 1 big pic and 4 box pics </h3> </div> </div> <br> <div id="category6"> <div id="cat6_leftside"> <h3> Horizontal Slider Cat 6 </h3> </div> <div id="cat6_rightside"> <h3> Category 6 Top Brans with 1 big pic and 4 box pics </h3> </div> </div> <br> <div id="ads4"> <h3>Single Product Ads to Buy</h3> </div> <br> <div id="category7"> <div id="cat7_leftside"> <h3> Horizontal Slider Cat 7 </h3> </div> <div id="cat7_rightside"> <h3> Category 7 Top Brans with 1 big pic and 4 box pics </h3> </div> </div> <br> <div id="category8"> <div id="cat8_leftside"> <h3> Horizontal Slider Cat 8 </h3> </div> <div id="cat8_rightside"> <h3> Category 8 Top Brans with 1 big pic and 4 box pics </h3> </div> </div> <br> <div id="ads5"> <h3>Single Product Ads to Buy</h3> </div> <br> <div id="category9"> <div id="cat9_leftside"> <h3> Horizontal Slider Cat 9 </h3> </div> <div id="cat9_rightside"> <h3> Category 9 Top Brans with 1 big pic and 4 box pics </h3> </div> </div> <br> <div id="category10"> <div id="cat10_leftside"> <h3> Horizontal Slider Cat 10 </h3> </div> <div id="cat10_rightside"> <h3> Category 10 Top Brans with 1 big pic and 4 box pics </h3> </div> </div> <br> <div id="footer"> </div> </div> </body> </html>替换undefined时,0.0不是那个慢了(事实上,对我来说它比SlowHeap快)。

我的猜测是因为你用浮点数(FastHeap)填充数组,只要数组包含所有相同类型的项目,就可以执行优化。

一旦引入类型不匹配(Math.random()不是浮点数),V8可能不得不切换到更通用的数组类型,并放弃优化。