NodeJS对重复函数调用的执行更快

时间:2018-11-06 22:04:45

标签: node.js

我正在用NodeJS编写合并排序的JavaScript实现,因为本机V8 sort函数使用快速排序,在最坏的情况下它不如合并排序有效。为了测试性能,我制作了一个由10000个元素组成的数组,这些元素已预先排序(最坏情况是快速排序),并确定了使用这两个函数对该列表进行排序所花费的时间。在一次执行中,本机sort函数大约需要16毫秒,而我的实现大约需要9毫秒。但是,当同时执行两次100次时,本机sort平均大约需要2.1毫秒,而我的const { performance } = require('perf_hooks'); function merge(a, b, func) { const array = new Array(a.length + b.length); let aIndex = 0; let bIndex = 0; while(aIndex + bIndex < array.length) { if(aIndex >= a.length || func(a[aIndex], b[bIndex]) > 0) { array[aIndex + bIndex] = b[bIndex++]; } else { array[aIndex + bIndex] = a[aIndex++]; } } return array; } function mergeSort(list, func) { if(list.length <= 1) { return list; } const half = list.length / 2; return merge(mergeSort(list.slice(0, half), func), mergeSort(list.slice(half), func), func); } function time(func, iters) { let sum = 0; for(let i = 0; i < iters; i++) { let startTime = performance.now(); func(); sum += performance.now() - startTime; } return sum / iters; } const arr = [...Array(10000).keys()]; const sortFunc = (a, b) => a - b; console.log("JavaScript built-in sort execution time, one iteration:") console.log(time(() => arr.sort(sortFunc), 1)); // ~16 console.log("Manually implemented merge sort execution time, one iteration:") console.log(time(() => mergeSort(arr, sortFunc), 1)); // ~9 console.log(); console.log("JavaScript built-in sort average execution time, 100 iterations:") console.log(time(() => arr.sort(sortFunc), 100)); // ~2.1 console.log("Manually implemented merge sort average execution time, 100 iterations:") console.log(time(() => mergeSort(arr, sortFunc), 100)); // ~4.3 大约需要4.3毫秒。这是我的代码:

sort

为什么重复执行一次却比一次执行快得多?为什么这种改进对于本机slice函数更明显?

编辑:通过跟踪数组索引而不是使用sort方法,我能够使算法更有效。现在,在预排序数组上使用我的代码时,它始终击败v8的本机const { performance } = require('perf_hooks'); function merge(a, b, func) { const array = new Array(a.length + b.length); let aIndex = 0; let bIndex = 0; while(aIndex + bIndex < array.length) { if(aIndex >= a.length || func(a[aIndex], b[bIndex]) > 0) { array[aIndex + bIndex] = b[bIndex++]; } else { array[aIndex + bIndex] = a[aIndex++]; } } return array; } function mergeSortRec(list, func, start, limit) { if (limit === 1) { return [list[start]]; } const half = limit / 2 | 0; return merge(mergeSortRec(list, func, start, half), mergeSortRec(list, func, half + start, limit - half), func); } function mergeSort(list, func) { return mergeSortRec(list, func, 0, list.length); } function time(func) { let startTime = performance.now(); func(); return performance.now() - startTime; } const sortFunc = (a, b) => a - b; console.log(); console.log("--- Sequential array ---"); console.log(); const sequenceArr = [...Array(10000).keys()]; console.log("JavaScript built-in sort execution time, one iteration:"); console.log(time(() => sequenceArr.slice(0).sort(sortFunc))); console.log("Manually implemented merge sort execution time, one iteration:"); console.log(time(() => mergeSort(sequenceArr, sortFunc))); let sum = 0; for(let i = 0; i < 100; i++) { const array = sequenceArr.slice(0); sum += time(() => array.sort(sortFunc)); } console.log("JavaScript built-in sort average execution time, 100 iterations:"); console.log(sum / 100); sum = 0; for(let i = 0; i < 100; i++) { sum += time(() => mergeSort(sequenceArr, sortFunc)) } console.log("Manually implemented merge sort average execution time, 100 iterations:"); console.log(sum / 100); console.log(); console.log("--- Randomized array ---"); console.log(); const randomArrays = new Array(101); for(let i = 0; i < 101; i++) { randomArrays[i] = new Array(10000); for(let j = 0; j < 10000; j++) { randomArrays[i][j] = Math.random() * 5000 | 0; } } console.log("JavaScript built-in sort execution time, one iteration:"); console.log(time(() => randomArrays[100].slice(0).sort(sortFunc))); console.log("Manually implemented merge sort execution time, one iteration:"); console.log(time(() => mergeSort(randomArrays[100], sortFunc))); sum = 0; for(let i = 0; i < 100; i++) { const array = randomArrays[i].slice(0) sum += time(() => array.sort(sortFunc)); } console.log("JavaScript built-in sort average execution time, 100 iterations:"); console.log(sum / 100); sum = 0; for(let i = 0; i < 100; i++) { sum += time(() => mergeSort(randomArrays[i], sortFunc)) } console.log("Manually implemented merge sort average execution time, 100 iterations:"); console.log(sum / 100); ,但在随机数组上却不出所料。这是那些有兴趣的代码:

dataframe

0 个答案:

没有答案