Skip to content

Instantly share code, notes, and snippets.

@runspired
Created July 12, 2016 19:34
Show Gist options
  • Save runspired/9aa4c107df8a021d2fe7fe8cdb2bb456 to your computer and use it in GitHub Desktop.
Save runspired/9aa4c107df8a021d2fe7fe8cdb2bb456 to your computer and use it in GitHub Desktop.
requestIdleCallback timing guarantees
var lastFlushed = undefined;
function floodScheduler(n) {
for (var i = 0; i < 10; i++) {
for (var j = 0; j < n; j++) {
var fn = function logPos(i, j) {
var thisFlush = (i * n) + j;
if (lastFlushed || lastFlushed === 0) {
if (lastFlushed + 1 !== thisFlush) {
console.error('Order MisMatch', lastFlushed, thisFlush, i, j);
}
}
lastFlushed = thisFlush;
}.bind(null, i, j)
setTimeout(fn, i);
}
}
var now = performance.now();
for (var id = 0; id < 10; id++) {
var fn = function logIdlePos(start, i) {
var elapsed = performance.now() - start;
// we allow a little jiggle
if (elapsed > i + 5) {
console.error('Idle Callback Delayed Too Long', start, elapsed, i);
}
lastFlushed = 'idle-' + i;
}.bind(undefined, now, id);
requestIdleCallback(fn, { timeout: id });
}
}
floodScheduler(10000);
@runspired
Copy link
Author

function testRIC() {
  var count = 0;
  function runUntil(time) {
    if (performance.now() > time) { console.log('ric', count); return; }
    requestIdleCallback(function() { count++; runUntil(time); }, { timeout: 0 });
  }
  runUntil(performance.now() + 100);
}
function testTimeout() {
  var count = 0;
  function runUntil(time) {
    if (performance.now() > time) { console.log('timeout', count); return; }
    setTimeout(function() { count++; runUntil(time); }, 0);
  }
  runUntil(performance.now() + 100);
}

additional test showing speed of rIC vs setTimeout

screen shot 2016-07-12 at 9 30 32 pm

@runspired
Copy link
Author

Effects of racing the two:

function race(tm) {
  requestIdleCallback(function() { console.log('idle'); }, { timeout: tm });
  setTimeout(function() { console.log('timeout'); }, tm);
}

screen shot 2016-07-12 at 9 41 37 pm

@runspired
Copy link
Author

Showing that any setTimeout gets in the way of rIC.

function race(tm) {
  requestIdleCallback(function() { console.log('idle'); }, { timeout: tm });
  setTimeout(function() { console.log('timeout'); }, tm);
  setTimeout(function() { console.log('timeout'); }, tm + 1);
  setTimeout(function() { console.log('timeout'); }, tm + 2);
  setTimeout(function() { console.log('timeout'); }, tm + 3);
  setTimeout(function() { console.log('timeout'); }, tm + 4);
  setTimeout(function() { console.log('timeout'); }, tm + 5);
}

screen shot 2016-07-12 at 10 06 39 pm

@runspired
Copy link
Author

Testing against raf

window.stopTest = false;
function delay(amount) {
  var start = performance.now();
  var now = performance.now();;
  while (now - start < amount) {
    now = performance.now();
  }
  return 'delayed!';
}
function test() {
  requestAnimationFrame(function() {
    console.log('frame', performance.now());
    delay(16);
    if (!window.stopTest) { test(); }
  });
}
function testIdle() {
  requestIdleCallback(function() {
    console.log('idle', performance.now());
    if (!window.stopTest) { testIdle(); }
  }, { timeout: 0 });
}
test();
testIdle();
setTimeout(function() { window.stopTest = true; }, 160);

@runspired
Copy link
Author

Showing that with raf we can still get 60FPS despite pushing 15.5ms of work within it.

window.stopTest = false;
window.lastFlush = performance.now();
function delay(amount) {
  var start = performance.now();
  var now = performance.now();;
  while (now - start < amount) {
    now = performance.now();
  }
  return 'delayed!';
}
function test() {
  requestAnimationFrame(function() {
    var now = performance.now();
    console.log('frame', now - window.lastFlush);
    window.lastFlush = now;
    delay(15.5);
    if (!window.stopTest) { test(); }
  });
}

test();
setTimeout(function() { window.stopTest = true; }, 5000);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment