Skip to content

Instantly share code, notes, and snippets.

@paulirish
Last active August 1, 2023 15:42
Show Gist options
  • Save paulirish/5438650 to your computer and use it in GitHub Desktop.
Save paulirish/5438650 to your computer and use it in GitHub Desktop.
performance.now() polyfill (aka perf.now())
// @license http://opensource.org/licenses/MIT
// copyright Paul Irish 2015
// Date.now() is supported everywhere except IE8. For IE8 we use the Date.now polyfill
// github.com/Financial-Times/polyfill-service/blob/master/polyfills/Date.now/polyfill.js
// as Safari 6 doesn't have support for NavigationTiming, we use a Date.now() timestamp for relative values
// if you want values similar to what you'd get with real perf.now, place this towards the head of the page
// but in reality, you're just getting the delta between now() calls, so it's not terribly important where it's placed
(function(){
if ("performance" in window == false) {
window.performance = {};
}
Date.now = (Date.now || function () { // thanks IE8
return new Date().getTime();
});
if ("now" in window.performance == false){
var nowOffset = Date.now();
if (performance.timing && performance.timing.navigationStart){
nowOffset = performance.timing.navigationStart
}
window.performance.now = function now(){
return Date.now() - nowOffset;
}
}
})();
@JofArnold
Copy link

CoffeeScript version with +new Date() to accommodate IE8

do ->
  # prepare base perf object
  if typeof window.performance=='undefined'
    window.performance = {}
  if not window.performance.now
    nowOffset = +new Date()
    if performance.timing and performance.timing
      nowOffset = performance.timing.navigationStart
    window.performance.now = ->
      now = +new Date()
      return now - nowOffset

@qxk23
Copy link

qxk23 commented Jul 9, 2013

Wondering if line 15 should be:

if (performance.timing && performance.timing.navigationStart){

@pyronaur
Copy link

pyronaur commented Aug 1, 2013

@JofArnold thanks. Exactly what I needed.

@drewwells
Copy link

Date.now() is not available in IE8. Also, without navigationStart what value is this polyfill? The numbers this polyfill would produce will not be comparable to the real performance.now(). It should do nothing for browsers lacking navigationStart.

@lonce
Copy link

lonce commented May 6, 2014

Thank you!

@ccarterc
Copy link

This makes it easier for testing. Thanks for the script. Now I don't have to have two versions of performance scripts to juggle.

@ianwremmel
Copy link

For those of us in the corporate world, could you provide a license for this gist?

@JordanDelcros
Copy link

Avoiding conditions:

window.performance = (window.performance || {
    offset: Date.now(),
    now: function now(){
        return Date.now() - this.offset;
    }
});

@Markus-ipse
Copy link

@JordanDelcros That doesn't work in IE9, because it has window.performance (but not window.performance.now)

@lukehedger
Copy link

@justluvher
Copy link

thank you~!!!!!!

@bikemule
Copy link

If anyone does Apache Cordova (a.k.a. Phonegap) dev, the iOS web view in there doesn't support performance either. At least not through Evothings workbench. I have yet to test with an actual built Cordova app, but I don't think it will make a difference.

@ti0ma
Copy link

ti0ma commented May 30, 2016

Thank you!! Solved my problem with Opbeat AngularJS plugin. Also thanks to @lukehedger for creating the bower package!

@rubencodes
Copy link

Wonderful! Thanks. Used this to patch support for iOS 8. Would be nice if Polyfill.io offered performance.timing instead of just performance.now polyfill...

@triblondon
Copy link

As @rubencodes implies above, polyfill.io now has a performance.now polyfill, and the benefit is that it will polyfill Date.now for you automatically if needed:

https://polyfill.io/v2/polyfill.min.js?features=performance.now

@sfinktah
Copy link

sfinktah commented Nov 2, 2016

@JofArnold that's not very idiomatic coffee-script, and looks like it needs updating to match the modified gist.

    do ->
      window.performance = {} unless 'performance' of window
      Date.now = if Date.now then Date.now else -> (new Date).getTime()
      unless 'now' of window.performance
        nowOffset = performance.timing?.navigationStart ? Date.now()
        window.performance.now = ->
          Date.now() - nowOffset

2016 what now?

@antoniocapelo
Copy link

^ @ghost just a heads up, the snippet above has a typo: 'perfomance' -> 'performance'

@jimmleon
Copy link

Thanks guys! I had issue with google's recaptcha code.
There was an error 'Cannot find variable performance', that was appearing in ios < 8 devices.
Fixed with @ghost 's code.
*thumbs up for @antoniocapelo 's sharp eye

@dhAlcojor
Copy link

dhAlcojor commented Jun 11, 2019

2017. Passing the baton.

if ( !window.performance || !window.performance.now ) {
  Date.now || ( Date.now = function () {
    return new this().getTime();
  });

  ( window.performance ||
    ( window.performance = {} ) ).now = function () {
      return Date.now() - offset;
    };

  var offset = ( window.performance.timing ||
    ( window.performance.timing = {} ) ).navigatorStart ||
      ( window.performance.timing.navigationStart = Date.now() );
}

There's another typo: it's navigationStart, not navigatorStart

@jalbam
Copy link

jalbam commented Jul 21, 2019

Hello,

I have mixed this polyfill with Aaron Levine's (https://gist.github.com/Aldlevine/3f716f447322edbb3671) and modifier some code:

'use strict';

// @license http://opensource.org/licenses/MIT
// copyright Paul Irish 2015
// Added code by Aaron Levine from: https://gist.github.com/Aldlevine/3f716f447322edbb3671
// Some modifications by Joan Alba Maldonado.
// as Safari 6 doesn't have support for NavigationTiming, we use a Date.now() timestamp for relative values
// if you want values similar to what you'd get with real perf.now, place this towards the head of the page
// but in reality, you're just getting the delta between now() calls, so it's not terribly important where it's placed
// Gist: https://gist.github.com/jalbam/cc805ac3cfe14004ecdf323159ecf40e
// TODO: Think about adding vendor prefixes.
if (!Date.now) { Date.now = function() { return new Date().getTime(); } }
(function()
{
	if (window.performance && window.performance.now) { return; }

	window.performance = window.performance || {};

	if
	(
		window.performance.timing && window.performance.timing.navigationStart &&
		window.performance.mark &&
		window.performance.clearMarks &&
		window.performance.getEntriesByName
	)
	{
		window.performance.now = function()
		{
			window.performance.clearMarks('__PERFORMANCE_NOW__');
			window.performance.mark('__PERFORMANCE_NOW__');
			return window.performance.getEntriesByName('__PERFORMANCE_NOW__')[0].startTime;
		};
	}
	else if ("now" in window.performance === false)
	{
		var nowOffset = Date.now();

		if (window.performance.timing && window.performance.timing.navigationStart)
		{
			nowOffset = window.performance.timing.navigationStart
		}

		window.performance.now = function now()
		{
			return Date.now() - nowOffset;
		}
	}
})();

I have placed it in this gist: https://gist.github.com/jalbam/cc805ac3cfe14004ecdf323159ecf40e

Any comments will be welcome. Thank you very much.

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