Skip to content

Instantly share code, notes, and snippets.

@paulirish
Last active August 1, 2023 15:42
Show Gist options
  • Star 96 You must be signed in to star a gist
  • Fork 17 You must be signed in to fork a gist
  • 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;
}
}
})();
@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'

@DimLeon
Copy link

DimLeon commented Nov 22, 2018

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