Inconsistent delta when using requestAnimationFrame and Date.now() - javascript

I have a simple snippet:
let startTime = -1
let lastNow = -1
let lastTS = -1
const animate = (timeStamp)=>{
requestAnimationFrame(animate)
const now = Date.now()
if(lastTS===-1){
lastTS = timeStamp
lastDate = now
}
const deltaTS = timeStamp - lastTS
lastTS = timeStamp
const deltaNow = now - lastNow
lastNow = now
console.log(deltaTS,deltaNow)
}
animate(-1)
And I see what i expect, the values are somewhat similar, with the timestamp being much more precise
But, when using this exact code in a massive code base, i see wildly inconsistent results. The delta derived from raf's timestamp is consistent with my refresh rate, the one comparing two Date.now() calls varies between 4 and a lot. What could possibly be causing this? I suspect i may have animate(-) firing a few times, but i still don't understand why would these be so oddly spaced out.

The timestamp passed to the callback of requestAnimationFrame is, in Chrome and Firefox at least, the time of the last V-Sync signal and in the specs, the time of the beginning of the rendering frame.
All callbacks in the same rendering frame will share the same timestamp.
So what you see here is probably just that your own callback fires after some heavy ones:
requestAnimationFrame((ts) => {
const now = performance.now();
const diff = now - ts;
console.log("first callback", { ts, now, diff });
while(performance.now() - now < 200) {
// block the event-loop 200ms
}
});
requestAnimationFrame((ts) => {
const now = performance.now();
const diff = now - ts;
console.log("second callback", { ts, now, diff });
});

Related

How many times can you make count += 1 in one second with Javascript?

I am trying to measure how many times i can make "count = count + 1" in one second. But this function breaks browser. Anyone can say why is it happening or have a better method to calculate it?
function counter(){
var count = 0;
var trs = true;
while(trs){
count = count + 1;
setTimeout(() => {trs = false;}, 1000);
}
console.log(count);
}
The reason it crashes is because of infinite loop. JavaScript is event driven + single threaded and in JavaScript execution model, the function must finish before it yields control to another function. Thus, the code while (trs) {...} never yields control to the function defined in setTimeout because it never finishes. trs is always true.
Nice visualization on how the JavaScript execution model works: https://blog.avenuecode.com/understanding-the-javascript-concurrency-model
Here's a better way to do it:
function counter() {
var count = 0
var start = Date.now()
var end = start + 1000
while (Date.now() <= end) {
count = count + 1
}
console.log(count)
}
There is an infinite loop over there. Now, since javascript is single-threaded, the browser will get stuck performing that infinite loop, which may cause the cache filling up very quickly and cause a crash (or not re-render anything).
First, generally speaking, it is better to create the setTimeout only once, before you call while:
var count = 0;
var trs = true;
setTimeout(() => {trs = false;}, 1000);
while(trs){
count = count + 1;
}
console.log(count);
However, this will also cause a crash.
You can try to measure the operations differently, measure how much time it takes for a single count = count + 1 operation to run, then find how many of these can be executed in a second (Although it is not the same as running X consecutive operations, which another parameters could influence the result, but I am assuming you care about a single operation or single function you want to measure).
var count = 0;
var t0 = performance.now()
count = count + 1;
var t1 = performance.now()
console.log(1000/(t1 - t0));
If you want it to be inside a loop, you can also include the value check (with if), which the while does before executing its block.
var count = 0;
var trs=true;
var t0 = performance.now()
if(trs==true){
count = count + 1;
}
var t1 = performance.now()
console.log(1000/(t1 - t0));

How do I make a page no fall asleep when it is no focused on?

I'm making a clicker/tycoon web game but when the page is not focused on, the page will not be active, is there any way to make it so the page doesn't becomes inactive if not focused on, or is there any ways around it?
The browser's setInterval doesn't run at max speed when there is no focus, so to counter that you need to get the window blur/focus events and do the math yourself. Here is an example of how this is done. Click on the window to create focus, then unfocus on the window for a short time, then give the window focus again (repeat).
Note: Don't forget to stop giving cash in the original loop otherwise you will be calculating more than once and giving extra cash.
// The current balance
let balance = 0
// The time the window lost focus
let focusLostTime = null
// The amount of cash per second
let cashPerSec = 2
// Wheter we should calc balance in the main loop
let calcBalance = true
// The output
let balanceOutput = document.getElementById('balance')
window.addEventListener('blur', () => {
// Set the time the window lost focus
focusLostTime = Date.now()
calcBalance = false
})
window.addEventListener('focus', () => {
// If this hasn't been set don't do anything
if(!focusLostTime) return
calcBalance = true
// Calculate the elapsed time
// This will be in seconds and posibly have a decimal
let elapsedTime = (Date.now() - focusLostTime) / 1000
// Multiply the elapsed time by the amount of cash they get per second
balance += elapsedTime * cashPerSec
})
////////////////////////////////////////
// This is just for example update loop
////////////////////////////////////////
// When the last tick was
let lastTick = Date.now()
setInterval(() => {
if (!calcBalance) return
let elapsedTime = (Date.now() - lastTick) / 1000
balance += cashPerSec * elapsedTime
lastTick = Date.now()
balanceOutput.innerText = balance
}, 10)
Balance: <span id="balance"></span>

change a property of an object if the current time exceeds time + 30 seconds - javascript

I currently have the following:
let time = Date.now()
I need to change a property of an object if the current time exceeds time + 30 seconds. I need to make this check every 10 seconds.
let obj = {
timestamp: Date.now(),
has30secExceeded: true or false
}
The property I need to set is has30secExceeded. What is the best way to achieve this? Thanks in advance.
You can use setInterval which accepts a callback and a millisecond delay. Keep in mind that setInterval only schedules the event to be pushed on to the queue at the interval, which mean it may not be called at that exact interval.
let originalTime = Date.now()
let obj = {
has30secExceeded:false
}
setInterval(()=>{
obj.timestamp = Date.now();
if(Date.now() > originalTime + 3000){
obj.has30secExceeded = true;
}
},10000);

Javascript code for making my browser slow down

I'm writing a library for WebWorkers, and I want to test the difference between running a script in the main page thread, versus in one or more workers. The problem is: I can't find out of hand a short function which will strain my browser enough that I can observe the difference.
A quick search didn't return much, but it might just be that I don't really know what to search for; usually I try to optimise my code, not make it slower...
I'm looking for algorithms or patterns that can be easily implemented in pure Javascript, that do not depend on the DOM or XHR, and which can have an argument passed to limit or specify how far the calculation goes (no infinite algorithms); 1s < avg time < 10s.
Extra points if it can be built without recursion and if it does not incur a significant memory hog while still being as processor intensive as possible.
Try using the obvious (and bad) recursive implementation for the Fibonacci sequence:
function fib(x) {
if (x <= 0) return 0;
if (x == 1) return 1;
return fib(x-1) + fib(x-2);
}
Calling it with values of ~30 to ~35 (depending entirely on your system) should produce good "slow down" times in the range you seek. The call stack shouldn't get very deep and the algorithm is something like O(2^n).
/**
* Block CPU for the given amount of seconds
* #param {Number} [seconds]
*/
function slowdown(seconds = 0.5) {
const start = (new Date()).getTime()
while ((new Date()).getTime() - start < seconds * 1000){}
}
slowdown(2)
console.log('done')
Calling this method will slow code down for the given amount of seconds (with ~200ms precision).
Generate an array of numbers in reverse order and sort it.
var slowDown = function(n){
var arr = [];
for(var i = n; i >= 0; i--){
arr.push(i);
}
arr.sort(function(a,b){
return a - b;
});
return arr;
}
This can be called like so:
slowDown(100000);
Or whatever number you want to use.
Check out the benchmarking code referenced by the Google V8 Javascript Engine.
For some reason Bogosort comes to mind. Basically it's a sorting algorithm that consists of:
while not list.isInOrder():
list.randomize()
It has an average complexity of O(n * n!) with little memory, so it should slow things down pretty good.
The main downside is that its running time can be anywhere from O(n) to O(inf) (though really, O(inf) is pretty unlikely).
Everyone seems determined to be complicated. Why not this?
function waste_time(amount) {
for(var i = 0; i < amount; i++);
}
If you're concerned the browser will optimize the loop out of existence entirely, you can make it marginally more complicated:
function waste_time(amount) {
var tot = 0;
for(var i = 0; i < amount; i++)
tot += i;
}
Compute lots of square roots manually?
function sqrt(number, maxDecimal) {
var cDecimal = -1;
var cNumber = 0;
var direction = -1;
while(cNumber * cNumber !== number && cDecimal < maxDecimal) {
direction = -direction;
cDecimal++;
while((cNumber * cNumber - number) / Math.abs(cNumber * cNumber - number) === direction) cNumber += direction * Math.pow(10, -cDecimal);
}
return Math.abs(cNumber);
}
function performTest() {
for(var i = 0; i < 10000; i++) {
sqrt(i, 3);
}
}
Maybe this is what you are looking for:
var threadTest = function(durationMs, outputFkt, outputInterval) {
var startDateTime = (new Date()).getTime();
counter = 0,
testDateTime = null,
since = 0,
lastSince = -1;
do {
testDateTime = (new Date()).getTime();
counter++;
since = testDateTime - startDateTime;
if(typeof outputFkt != 'undefined' && lastSince != since && testDateTime % outputInterval == 0) {
outputFkt(counter, since);
lastSince = since;
}
} while(durationMs > since);
if(typeof outputFkt != 'undefined') {
outputFkt(counter, since);
}
return counter;
}
This method will simply repeat a check in a loop
durationMS - duartion it should run in miliseconds
OPTIONAL:
outputFkt - a callback method, for logging purpose function(currentCount, milisecondsSinceStart)
outputInterval - intervall the output function will be called
I figured since you do not want to test a real function, and even NP-Hard Problems have a ratio between input length and time this could be a easy way. You can measure performance at any interval and of course receive the number of loops as a return value, so you can easily measure how much threads interfere each others performance, with the callback even on a per cycle basis.
As an example here is how i called it (jQuery and Dom usage are here, but as you can see optional)
$(document).ready(function() {
var outputFkt = function(counter, since) {
$('body').append('<p>'+counter+', since '+since+'</p>');
};
threadTest(1000, outputFkt, 20);
});
A last Warning: Of course this function can not be more exact than JS itself. Since modern Browsers can do much more than one cycle in one Milisecond, there will be a little tail that gets cut.
Update
Thinking about it... actually using the ouputFkt callback for more than just output could give great insight. You could pass a method that uses some shared properties, or you could use it to test great memory usage.

HTML5 Canvas performance - calculating loops/frames per second

I know a few questions have been asked like this one before, such as this: Check FPS in JS? - which did work to some degree, I was able to find out how long each loop took to complete.
What I am looking for though is something more readable and controllable. I want to be able to set the refresh rate for the FPS counter to make it slow so it is human readable or as fast as the application can run, so I can use it on some kind of speedometer.
Anyway so here is the code I have right now:
var lastLoop = new Date().getTime();
function updateStage()
{
clearCanvas();
updateStageObjects();
drawStageObjects();
var thisLoop = new Date().getTime();
var fps = (thisLoop - lastLoop);
$('#details').html(fps);
lastLoop = thisLoop;
iteration = setTimeout(updateStage, 1);
}
Am I right to be setting the setTimeout function to a speed of 1 millisecond? I was thinking this will just make it loop as fast as it possibly can.
Should I count every 100 frames or so, find out how many milliseconds it took to run 100 frames then make a calculation to find out how many frames it would have done if the milliseconds were 1000? What would this calculation be?
To make the result more accurate I am guessing I need to display averages as one frame can vary a significant amount, how should I do this?
Any tips are greatly appreciated.
Thanks.
Note that the faster you update your output, the more you will affect your measurement. Although minimal, I try to update my fps output once per second or less unless it's necessary to go faster.
I like to have a low-pass filter on my results so that a temporary hiccup doesn't affect the values too strongly. This is easier to compute and write than a moving average, and doesn't have the problem of an overall average where your 'current' readings are affected by total performance over the entire run (e.g. anomalous readings during startup).
Put together, here's how I usually measure FPS:
var fps = 0, now, lastUpdate = (new Date)*1;
// The higher this value, the less the FPS will be affected by quick changes
// Setting this to 1 will show you the FPS of the last sampled frame only
var fpsFilter = 50;
function drawFrame(){
// ... draw the frame ...
var thisFrameFPS = 1000 / ((now=new Date) - lastUpdate);
if (now!=lastUpdate){
fps += (thisFrameFPS - fps) / fpsFilter;
lastUpdate = now;
}
setTimeout( drawFrame, 1 );
}
var fpsOut = document.getElementById('fps');
setInterval(function(){
fpsOut.innerHTML = fps.toFixed(1) + "fps";
}, 1000);
Ive tried something out,
If you change the
lastUpdate = now
to
lastUpdate = now * 1 - 1;
Your NaN problem is solved! This is also used where the lastUpdate is defined. Probably because it is not able to convert the date to unix timestamp.
The new result will be:
var fps = 0, now, lastUpdate = (new Date)*1 - 1;
// The higher this value, the less the FPS will be affected by quick changes
// Setting this to 1 will show you the FPS of the last sampled frame only
var fpsFilter = 50;
function drawFrame(){
// ... draw the frame ...
var thisFrameFPS = 1000 / ((now=new Date) - lastUpdate);
fps += (thisFrameFPS - fps) / fpsFilter;
lastUpdate = now * 1 - 1;
setTimeout( drawFrame, 1 );
}
var fpsOut = document.getElementById('fps');
setInterval(function(){
fpsOut.innerHTML = fps.toFixed(1) + "fps";
}, 1000);
I've taken the solution(s) posted and enhanced them a little. Have a look here - http://jsfiddle.net/ync3S/
I fixed that NaN error by using Date.now() instead of constructing a new date object each time and trying to reference it. This also prevents some garbage collection necessity.
I neatened up the variable and function names a bit and added some extra commenting - not necessary but nice to have.
I included some drawing code for testing.
I added fpsDesired as a test var for the engine loop.
I started fpsAverage at fpsDesired so with the fpsFilter it doesn't work up from 0 to the real FPS, rather starting at the desired FPS and adjusting from there.
Drawing now blocks incase it already was drawing, and this can be used for pausing and other control functions.
The main block is as follows:
var fpsFilter = 1; // the low pass filter to apply to the FPS average
var fpsDesired = 25; // your desired FPS, also works as a max
var fpsAverage = fpsDesired;
var timeCurrent, timeLast = Date.now();
var drawing = false;
function fpsUpdate() {
fpsOutput.innerHTML = fpsAverage.toFixed(2);
}
function frameDraw() {
if(drawing) { return; } else { drawing = true; }
timeCurrent = Date.now();
var fpsThisFrame = 1000 / (timeCurrent - timeLast);
if(timeCurrent > timeLast) {
fpsAverage += (fpsThisFrame - fpsAverage) / fpsFilter;
timeLast = timeCurrent;
}
drawing = false;
}
setInterval(fpsUpdate, 1000);
fpsUpdate();
setInterval(frameDraw, 1000 / fpsDesired);
frameDraw();
Going to have a tinker and see if I can come up with something smoother, as this thread is near the top in Google results.
Let's see what we can all come up with as a team, and I think it's always neat to not use 3rd party libraries, making the code portable for anyone :)
-Platima
Just set a interval that is resetting the fps counter every second.
var fpsOut, fpsCount;
var draw = function () {
fpsCount++;
..Draw To Canvas..
..Get the fps value: fpsOut
requestAnimationFrame(draw);
};
setInterval(function () {
fpsOut = fpsCount;
fpsCount = 0;
}, 1000);
draw();
If you want real-time updates, consider making it loop again and again in real time. To make it affect the performance less, only update the controlled variable, in this case, the FPS. You can have optional Frame Latency, which I will put here, just in case. Just copy, paste and tweak the code to your needs.
Take note that a single frame lasts for 16.66 miliseconds.
setInterval(function(){var latencybase1 = parseFloat(new Date().getTime());
var latencybase2 = parseFloat(new Date().getTime());
var latency = latencybase2-latencybase1;
var fps = Math.round(1000/latency);
if (latency<16.66)
{document.getElementById("FPS").innerHTML = fps+"
FPS";}
else {document.getElementById("FPS").innerHTML = ""+fps+" FPS";}
document.getElementById("Latency").innerHTML = latency+" ms";}, 0);

Categories

Resources