Мне довелось увидеть высказывание о том, что избегание чтения атрибута длины массива на каждой итерации экономит время выполнения.
Но я не думаю, что это имеет значение, и провел эксперимент.
Тогда я встретил вопросы.
Вот код.
// Function to get the execution time.
function testFunction (func) {
console.time(func.name)
for (let i = 0; i < 100; i++) {
func()
}
console.timeEnd(func.name)
}
// Init the array to iterate.
let arr = []
for (let i = 0; i < 10000000; i++) {
arr.push(0)
}
function loopWithSavedLength () {
let len = arr.length
for (let i = 0; i < len; i++) {
arr[i] = i
}
}
function loopWithoutSavedLength() {
for (let i = 0; i < arr.length; i++) {
arr[i] = i
}
}
testFunction(loopWithoutSavedLength)
testFunction(loopWithSavedLength)
И вывод очень странный:
loopWithoutSavedLength: 889.633ms
loopWithSavedLength: 1023.269ms
Я много раз пробовал под Node.js 9.8.0 (с v8 6.2.414.46-node.21) и loopWithoutSavedLengthвремя выполнения всегда короче цикла loopWithSavedLength.
Я выполняю тот же сценарий в консоли chrome 66.0.3359.181 (с v8 6.6.346.32), и они почти не совпадают.
loopWithoutSavedLength: 1475.060302734375ms
loopWithSavedLength: 1493.14892578125ms
Тогда я подумал, что это может быть проблема с назначением ипроверить пустой цикл.
Вот новый код.
function assignmentLoopWithSavedLength () {
let len = arr.length
for (let i = 0; i < len; i++) {
arr[i] = i
}
}
function assignmentLoopWithoutSavedLength () {
for (let i = 0; i < arr.length; i++) {
arr[i] = i
}
}
function emptyLoopWithSavedLength () {
let len = arr.length
for (let i = 0; i < len; i++) {}
}
function emptyLoopWithoutSavedLength () {
for (let i = 0; i < arr.length; i++) {}
}
testFunction(emptyLoopWithSavedLength)
testFunction(emptyLoopWithoutSavedLength)
testFunction(assignmentLoopWithSavedLength)
testFunction(assignmentLoopWithoutSavedLength)
Результаты в файле node.js:
emptyLoopWithSavedLength: 580.978ms
emptyLoopWithoutSavedLength: 584.923ms
assignmentLoopWithSavedLength: 1046.899ms
assignmentLoopWithoutSavedLength: 901.542ms
Результаты в консоли Chrome:
emptyLoopWithSavedLength: 584.126953125ms
emptyLoopWithoutSavedLength: 892.776123046875ms
assignmentLoopWithSavedLength: 1455.418212890625ms
assignmentLoopWithoutSavedLength: 1449.7529296875ms
Позже я понял, что значение, хранящееся в arr, может влиять на последствия, и это оказывает влияние.
Новый код здесь:
let arr = []
function initArr () {
arr = []
for (let i = 0; i < 10000000; i++) {
arr.push(0)
}
}
function testFunction (func) {
initArr()
console.time(func.name)
for (let i = 0; i < 100; i++) {
func()
}
console.timeEnd(func.name)
}
Результат в node.js:
emptyLoopWithSavedLength: 560.739ms
emptyLoopWithoutSavedLength: 1134.274ms
assignmentLoopWithSavedLength: 1841.544ms
assignmentLoopWithoutSavedLength: 1609.649ms
Результат в консоли Chrome:
emptyLoopWithSavedLength: 592.8720703125ms
emptyLoopWithoutSavedLength: 910.886962890625ms
assignmentLoopWithSavedLength: 1457.467041015625ms
assignmentLoopWithoutSavedLength: 1488.855224609375ms
Теперь возникает новый вопрос.
В заключение:
1. Почему в файле node.js время loopWithoutSavedLength всегда меньше, чем loopWithSavedLength, независимо от того, какие элементы массива инициализируются равными 0 или нет?
2. Почему создается новый массив и инициализируетсяего элементы в 0 имеют другое значение?