92

I am trying to make a webpage that, when it starts loading, uses an Interval to start a timer.

When the page fully loads, it stops the timer,

but 99% of the time i get time measurements of 0.00 or 0.01 even if it takes longer.

Occasionally, it says something that makes more sense like .28 or 3.10 at some times.

Here is the code if it helps:

var hundredthstimer = 0;
var secondplace = 0;

function addinc(){

    hundredthstimer += 1;
    if (inctimer == 100){
        hundredthstimer = 0;
        secondplace += 1;
    }

}

var clockint = setInterval(addinc, 10);

function init(){
    var bconv1 = document.getElementById("bconverter1");
    var bconv2 = document.getElementById("bconverter2");

    $(bconv2).hide();

    clearInterval(clockint);

    if (inctimer.len !== 2){
        inctimer = "0" + inctimer;
    }
    alert(secondplace + "." + inctimer);
}
onload = init;

So it basically creates a variable called hundredthstimer which is increased by '1' every 10 miliseconds(.01 seconds).

Then, if this number reaches 1000(1 full second), a variable called secondsplace goes up by 1, since that is how many full seconds it has run for.

Then, it alerts secondsplace, a decimal point, and hundredthsplace as the total load time.

But the problem above with incorrect numbers still exists. Why?

HaNdTriX
  • 28,732
  • 11
  • 78
  • 85
austinstout
  • 1,180
  • 1
  • 11
  • 14

6 Answers6

262

Why so complicated? When you can do:

var loadTime = window.performance.timing.domContentLoadedEventEnd- window.performance.timing.navigationStart;

If you need more times check out the window.performance object:

console.log(window.performance);

This will show you the timing object:

connectEnd                 Time when server connection is finished.
connectStart               Time just before server connection begins.
domComplete                Time just before document readiness completes.
domContentLoadedEventEnd   Time after DOMContentLoaded event completes.
domContentLoadedEventStart Time just before DOMContentLoaded starts.
domInteractive             Time just before readiness set to interactive.
domLoading                 Time just before readiness set to loading.
domainLookupEnd            Time after domain name lookup.
domainLookupStart          Time just before domain name lookup.
fetchStart                 Time when the resource starts being fetched.
loadEventEnd               Time when the load event is complete.
loadEventStart             Time just before the load event is fired.
navigationStart            Time after the previous document begins unload.
redirectCount              Number of redirects since the last non-redirect.
redirectEnd                Time after last redirect response ends.
redirectStart              Time of fetch that initiated a redirect.
requestStart               Time just before a server request.
responseEnd                Time after the end of a response or connection.
responseStart              Time just before the start of a response.
timing                     Reference to a performance timing object.
navigation                 Reference to performance navigation object.
performance                Reference to performance object for a window.
type                       Type of the last non-redirect navigation event.
unloadEventEnd             Time after the previous document is unloaded.
unloadEventStart           Time just before the unload event is fired.

Browser Support

More Info

HaNdTriX
  • 28,732
  • 11
  • 78
  • 85
  • 5
    var loadTime = window.performance.timing.domComplete- window.performance.timing.navigationStart; why this is not working? This should give the load time where as what you mentioned gives the DOMContentLoaded time. I tried with this and it gives -(navigationStart) for me – Karthik Surianarayanan Feb 10 '14 at 03:34
  • 1
    for me it works fine. Can you provide some more details (Browser,Version etc.). – HaNdTriX Feb 10 '14 at 09:17
  • 1
    Browser: Chrome & Version: 32.0.1700.102 – Karthik Surianarayanan Feb 10 '14 at 09:18
  • Are you sure your DOM has finished loading when you did the calculation? – HaNdTriX Feb 10 '14 at 09:20
  • The thing you said is working for me. But when i try to access window.performance.timing.domComplete (or) window.performance.timing.loadEventEnd it gives 0, but in my console it prints the value. – Karthik Surianarayanan Feb 10 '14 at 09:20
  • I am executing it in $(document).ready so obviously it must be loaded rite ? – Karthik Surianarayanan Feb 10 '14 at 09:21
  • Please provide a fiddle where we may analyse your code. – HaNdTriX Feb 10 '14 at 09:28
  • http://jsfiddle.net/karthik030491/wy8Zt/ This thing works for me in fiddle but gives the same time for both the calculations. If i use this in my site it is not working :( – Karthik Surianarayanan Feb 10 '14 at 09:36
  • 2
    That both are the same makes sense since domContentLoadedEventEnd and domComplete are the same. Try: document.addEventListener("DOMContentLoaded", function(event) { // Do your calculation here }); (Maybe your jQuery is messed up somehow) – HaNdTriX Feb 10 '14 at 11:00
  • Both of them are not same, in my web page both returns different time. FYI : PerformanceTiming {loadEventEnd: 0, loadEventStart: 0, domComplete: 0, domContentLoadedEventEnd: 1392030687208, domContentLoadedEventStart: 1392030687173…} domComplete: 1392030687914 domContentLoadedEventEnd: 1392030687208 domContentLoadedEventStart: 1392030687173 loadEventEnd: 1392030687915 loadEventStart: 1392030687914 navigationStart: 1392030686388 – Karthik Surianarayanan Feb 10 '14 at 11:13
  • hmmmm yes. Sry about that :). I updated the answer to clarify the difference. – HaNdTriX Feb 10 '14 at 11:39
  • Found a nice library that takes advantage of this API: http://lafikl.github.io/perfBar/ – webXL Sep 04 '14 at 17:35
  • +1 Should be the accepted answer, although I had to add setTimeout to make it work for me: window.onload = function () { window.setTimeout(function () { var loadTime = window.performance.timing.loadEventEnd- window.performance.timing.navigationStart; console.log('Load Time: ' + (loadTime/1000) + 's'); }, 0); } – Tobias Aug 17 '16 at 08:53
  • @Tobias I think you want `loadEventStart`. I'm assuming `loadEventStart` is called after loading is complete but before any `onload` handlers are called. then `loadEventEnd` is called after any `onload` handlers end. so it wouldn't be set yet. if you execute `window.performance.timing.loadEventStart - window.performance.timing.loadEventEnd` the difference is about 10-20ms for me on a typical site – Simon_Weaver Feb 17 '17 at 19:10
  • Interesting that the docs and the recommendation https://www.w3.org/TR/hr-time-2/ has a timeOrigin property, but it is not present in your log. I hate that every time there is a new feature we have to write shims, polyfills, etc... – inf3rno Aug 16 '18 at 06:13
  • I checked. Since then we have a timeOrigin, and the perf object contains totally different things. Better to check the recommendation if somebody wants to work with this object... – inf3rno Aug 16 '18 at 06:16
  • 1
    Note: window.performance.timing is deprecated in the Navigation Timing Level 2 specification (mozilla docs on the subject: https://developer.mozilla.org/en-US/docs/Web/API/Performance/timing). However, it appears the timeOrigin property that should replace it isn't fully supported, so timing is probably stable in the short-run (as of 2019-4-1). – fixermark Apr 01 '19 at 15:53
86

Don't ever use the setInterval or setTimeout functions for time measuring! They are unreliable, and it is very likely that the JS execution scheduling during a documents parsing and displaying is delayed.

Instead, use the Date object to create a timestamp when you page began loading, and calculate the difference to the time when the page has been fully loaded:

<doctype html>
<html>
    <head>
        <script type="text/javascript">
            var timerStart = Date.now();
        </script>
        <!-- do all the stuff you need to do -->
    </head>
    <body>
        <!-- put everything you need in here -->

        <script type="text/javascript">
             $(document).ready(function() {
                 console.log("Time until DOMready: ", Date.now()-timerStart);
             });
             $(window).load(function() {
                 console.log("Time until everything loaded: ", Date.now()-timerStart);
             });
        </script>
    </body>
</html>
Trevor Clarke
  • 1,482
  • 1
  • 11
  • 20
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Ok, so I transformed this a bit so that it would alert the numbers instead. So now, I have some strange numbers like 15 and 1399 the first time, or something else like that. Is the second number in miliseconds? (1/1000 of a second)In that case, what is the first number (time until dom is ready)? From what I see, it is predicting the future by telling when something will be loaded before it happens.... – austinstout Jan 15 '13 at 23:46
  • Wait, I figured the second question out. Now, I only need my confirmation of "is the time until everything loaded in miliseconds" question – austinstout Jan 15 '13 at 23:48
  • Yes, [`Date.now`](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date/now) returns a timestamp in milliseconds. – Bergi Jan 15 '13 at 23:50
  • 8
    Why is this answer so popular? The code uses jQuery, will not be available until far too late in the loading process surely? – Alexander Wigmore Dec 27 '14 at 17:35
  • 2
    @AlexanderWigmore: I have no idea why it's popular either, I guess it's just from the 11k views on the question. That it uses jQuery is absolutely no problem, as it'll need to measure the time to load the script file anyway. And of course you could do without jQuery and attach the listeners for DOMready and window.onload manually. – Bergi Dec 27 '14 at 21:13
45

The answer mentioned by @HaNdTriX is a great, but we are not sure if DOM is completely loaded in the below code:

var loadTime = window.performance.timing.domContentLoadedEventEnd- window.performance.timing.navigationStart; 

This works perfectly when used with onload as:

window.onload = function () {
    var loadTime = window.performance.timing.domContentLoadedEventEnd-window.performance.timing.navigationStart; 
    console.log('Page load time is '+ loadTime);
}

Edit 1: Added some context to answer

Note: loadTime is in milliseconds, you can divide by 1000 to get seconds as mentioned by @nycynik

Samdeesh
  • 905
  • 11
  • 23
  • 2
    Would this be in milliseconds? – NiCk Newman Feb 29 '16 at 01:25
  • 4
    Yep, Returns the time, in milliseconds. You can divide by 1000 to get seconds. ((window.performance.timing.domComplete- window.performance.timing.navigationStart)/1000)+" sec."; – nycynik Aug 30 '16 at 14:45
  • 2
    `navigationStart` begins when you start loading the page in the browser. this has the advantage that it includes all server side processing time (for the main HTML page) and any network latency - which is impossible to calculate with a simple javascript timer started at the beginning of the page – Simon_Weaver Feb 17 '17 at 10:27
  • True enough, but if you're in an extreme legacy browser environment (it wasn't my idea) then anything in PerformanceTiming is out of reach. Using timings initiated with a – user1329482 Mar 09 '18 at 12:14
  • window.performance.timing is apparently depreciated https://developer.mozilla.org/en-US/docs/Web/API/Performance/timing – oleviolin Mar 28 '21 at 00:28
  • 1
    Why does this give me a negative number? – Vincent Sep 17 '21 at 01:16
3

It is hard to make a good timing, because the performance.dominteractive is miscalulated (anyway an interesting link for timing developers).

When dom is parsed it still may load and execute deferred scripts. And inline scripts waiting for css (css blocking dom) has to be loaded also until DOMContentloaded. So it is not yet parsed?

And we have readystatechange event where we can look at readyState that unfortunately is missing "dom is parsed" that happens somewhere between "loaded" and "interactive".

Everything becomes problematic when even not the Timing API gives us a time when dom stoped parsing HTML and starting The End process. This standard say the first point has to be that "interactive" fires precisely after dom parsed! Both Chrome and FF has implemented it when document has finished loading sometime after it has parsed. They seem to (mis)interpret the standars as parsing continues beyond deferred scripts executed while people misinterpret DOMContentLoaded as something hapen before defered executing and not after. Anyway...

My recommendation for you is to read about​ Navigation Timing API. Or go the easy way and choose a oneliner of these, or run all three and look in your browsers console ...

  document.addEventListener('readystatechange', function() { console.log("Fiered '" + document.readyState + "' after " + performance.now() + " ms"); });

  document.addEventListener('DOMContentLoaded', function() { console.log("Fiered DOMContentLoaded after " + performance.now() + " ms"); }, false);

  window.addEventListener('load', function() { console.log("Fiered load after " + performance.now() + " ms"); }, false);

The time is in milliseconds after document started. I have verified with Navigation​ Timing API.

To get seconds for exampe from the time you did var ti = performance.now() you can do parseInt(performance.now() - ti) / 1000

Instead of that kind of performance.now() subtractions the code get little shorter by User Timing API where you set marks in your code and measure between marks.

1

here's an expression that gives the exact value:

window.performance.timing.loadEventEnd-window.performance.timing.navigationStart 
Radagast the Brown
  • 3,156
  • 3
  • 27
  • 40
  • 1
    As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 21 '21 at 11:30
0

We can also use loadEventStart.

window.onload = {
  const performanceTiming = performance.timing;
  const navigationStart = performanceTiming.navigationStart;
  const loadEventStart = performanceTiming.loadEventStart;
  const pageLoadTime = loadEventStart - navigationStart;
  console.log({pageLoadTime});
}
Sanjeet kumar
  • 3,333
  • 3
  • 17
  • 26