我正在使用NodeJ并需要调用无限功能,但我不知道什么是最佳性能。
递归功能
function test(){
//my code
test();
}
的setInterval
setInterval(function(){
//my code
},60);
的setTimeout
function test(){
//my code
setTimeout(test,60);
}
我希望在不崩溃服务器的情况下获得最佳性能。我的代码有几个算术运算。
感谢任何优化javascript性能的建议。
答案 0 :(得分:14)
小心..你的第一个代码会阻止JavaScript事件循环。
基本上在JS中就像应该处理的函数列表。当您致电setTimeout
,setInterval
或process.nextTick
时,您会在此列表中添加指定功能,并在适当时间到来时对其进行处理..
第一种情况下的代码永远不会停止,因此永远不会让事件列表中的其他函数被处理。
第二和第三个案例很好......但差别不大。
如果你的函数需要处理10毫秒,间隔将是你的60毫秒..
所以区别在于你的功能启动之间的延迟,这在一些基于区间的系统中很重要,比如游戏,拍卖,股票市场......等等。
祝你的递归好运: - )
答案 1 :(得分:10)
如前所述,无休止的递归函数会导致堆栈溢出。时间触发的回调将在具有清晰堆栈的自己的上下文中执行。
setInterval
对于递归setTimeout
的更准确的定期调用非常有用,但是,有一个缺点:即使抛出了未捕获的异常,也会触发回调。这通常每60毫秒产生几个字节长的日志条目,每天产生1'440'000个条目。此外,负载较重的setInterval
回调可能会导致无响应的脚本甚至是漏洞系统。
如果没有捕获到任何异常,则在从函数返回之前立即递归setTimeout
将不执行。它将保证从回调函数返回后的其他任务的时间范围,而与函数的执行时间无关。
答案 2 :(得分:6)
不确定你想要完成什么,但这里是一个安全的"使用递归的方式... https://stackoverflow.com/questions/24208676/how-to-use-recursion-in-javascript/24208677
/*
this will obviously crash... and all recursion is at risk of running out of call stack and breaking your page...
function recursion(c){
c = c || 0;
console.log(c++);
recursion(c);
}
recursion();
*/
// add a setTimeout to reset the call stack and it will run "forever" without breaking your page!
// use chrome's heap snapshot tool to prove it to yourself. :)
function recursion(c){
setTimeout(function(c){
c = c || 0;
console.log(c++);
recursion(c);
},0,c);
}
recursion();
// another approach is to use event handlers, but that ultimately uses more code and more resources
答案 3 :(得分:1)
假设Jan Juna描述了“性能延迟”,我尝试了这个简单的脚本来检查吞吐量方面是否存在任何差异:
时间间隔:
const max = 50;
const timer = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 100, 150, 200, 250, 300, 400, 500];
function crono(timer) {
return new Promise(resolve => {
const exit = [];
let i = 0
setInterval(() => i++, timer);
setInterval(() => {
exit.push(i);
i = 0;
if (exit.length === max) {
const sum = exit.reduce((a, b) => (a + b), 0);
const avg = sum / exit.length;
console.log(`${timer} = ${avg}`);
resolve(avg)
}
}, 1000);
});
}
Promise.all(timer.map(crono)).then(process.exit);
超时:
const max = 50;
const timer = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50, 100, 150, 200, 250, 300, 400, 500];
function crono(timer) {
return new Promise(resolve => {
const exit = [];
let i = 0
const redo = () => {
i++
setTimeout(redo, timer);
}
setInterval(() => {
exit.push(i);
i = 0;
if (exit.length === max) {
const sum = exit.reduce((a, b) => (a + b), 0);
const avg = sum / exit.length;
console.log(`${timer} = ${avg}`);
resolve(x)
}
}, 1000);
redo();
});
}
Promise.all(timer.map(crono)).then(process.exit);
这是nodejs 8.11的输出:在吞吐量方面没有任何区别:
答案 4 :(得分:0)
递归函数导致堆栈溢出。那不是你想要的。
您展示的setInterval
和setTimeout
方式相同,只是setInterval
更清晰。
我建议setInterval
。 (毕竟,这就是它的用途。)
答案 5 :(得分:0)
递归setTimeout
保证了两次执行之间的延迟,setInterval
–不会。
让我们比较两个代码片段。第一个使用setInterval
:
let i = 1;
setInterval(function() {
func(i);
}, 100);
第二个使用递归setTimeout
:
let i = 1;
setTimeout(function run() {
func(i);
setTimeout(run, 100);
}, 100);
对于setInterval
,内部调度程序将每100毫秒运行func(i)
。
func
到setInterval
调用之间的实际延迟小于代码中的时间!
这很正常,因为执行func's
所花费的时间“消耗”了间隔的一部分。
func's
的执行时间可能比我们预期的要长,并且可能会花费超过100毫秒的时间。
在这种情况下,引擎等待func
完成,然后检查调度程序,如果时间到了,则立即再次运行它。
在极端情况下,如果函数执行的时间总是超过delay
毫秒,则调用将完全没有暂停。
递归setTimeout
保证固定的delay
(此处为100毫秒)。
答案 6 :(得分:-3)
//使用setInterval函数
$Model->actsAs
1000毫秒=1秒; 属性如style.width等;