一個編寫良好的計算機程序經常具備良好的局部性,它們傾向於引用最近引用過的數據項附近的數據項,或者最近引用過的數據項自己,這種傾向性,被稱爲局部性原理。有良好局部性的程序比局部性差的程序運行得更快。git
時間局部性示例github
function sum(arry) { let i, sum = 0 let len = arry.length for (i = 0; i < len; i++) { sum += arry[i] } return sum }
在這個例子中,變量sum在每次循環迭代中被引用一次,所以,對於sum來講,具備良好的時間局部性chrome
空間局部性示例數組
具備良好空間局部性的程序瀏覽器
// 二維數組 function sum1(arry, rows, cols) { let i, j, sum = 0 for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { sum += arry[i][j] } } return sum }
空間局部性差的程序性能
// 二維數組 function sum2(arry, rows, cols) { let i, j, sum = 0 for (j = 0; j < cols; j++) { for (i = 0; i < rows; i++) { sum += arry[i][j] } } return sum }
看一下上面的兩個空間局部性示例,像示例中從每行開始按順序訪問數組每一個元素的方式,稱爲具備步長爲1的引用模式。
若是在數組中,每隔k個元素進行訪問,就稱爲步長爲k的引用模式。
通常而言,隨着步長的增長,空間局部性降低。測試
這兩個例子有什麼區別?區別在於第一個示例是按行掃描數組,每掃描完一行再去掃下一行;第二個示例是按列來掃描數組,掃完一行中的一個元素,立刻就去掃下一行中的同一列元素。code
數組在內存中是按照行順序來存放的,結果就是逐行掃描數組的示例獲得了步長爲 1 引用模式,具備良好的空間局部性;而另外一個示例步長爲 rows,空間局部性極差。內存
運行環境:get
對一個長度爲9000的二維數組(子數組長度也爲9000)進行10次空間局部性測試,時間(毫秒)取平均值,結果以下:
所用示例爲上述兩個空間局部性示例
步長爲 1 | 步長爲 9000 |
---|---|
124 | 2316 |
從以上測試結果來看,步長爲 1 的數組執行時間比步長爲 9000 的數組快了一個數量級。
參考資料: