'How can we measure an XMLHttpRequest request execution time? The time server starts processig to the time response is ready

I am trying to measure the time an asynchronous http request is processed by an http server developed in nodejs. By that I mean the time from which the server informs the client starting to process the request, to the time the server finishes processing and returns the response back to the client.

So, accrding to XMLHttpRequest documentation for readyState I am under the impression that the time difference between when readyState == 3 to readyState == 4 gets me what I want. In practice I get almost 0 to be the time difference between the two. However my expectation, according to the code snippets below is to get something around to 2000+ ms.

Why is that and how can I roughly measure the processing time in practice?

Client side:

<script>
    let begin;
    const xhttp = new XMLHttpRequest();
    xhttp.open("GET", "https://mydomain. com/API", true);
    xhttp.send();
    xhttp.onreadystatechange = function () {
        if (this.readyState == 3) {
            begin = Date.now();
        }

        if (this.readyState == 4 && this.status == 200) {
            console.log("Execution time (ms):" + (Date.now() - begin));
        }
    };
</script>

server side ( as seen, processing a request takes around 2000ms)

let http = require('http');
let url = require('url');
let server = http.createServer(function (req, res) {
    reqReceived++;
    let q = url.parse(req.url, true);
    res.writeHead(200, {
        "Content-Type": "text/html",
        "Access-Control-Allow-Origin": "*"
    });
    setTimeout(() => {
        res.end(`response is ready`);
     }, 2000);

});
server.listen();

You might argue that I should have put writing the head inside the timeout callback, however it would not still make any time difference for the client to receive readyState ==3 and == 4.



Solution 1:[1]

The right readyState to start your timer is 1. Node.JS will send headers only when you call res.end(response is ready);

I tried your code and scan it using Wireshark: screenshot

The row #4 corresponding to the request sent by your client. The #6 is the header is sent by your server with the body.

According to MDN:

  • state 2 => XHR received headers from server
  • state 3 => Response is being loaded (if chunk)
  • state 4 => Response parsed.

By testing 2, 3 or 4, you'll only test the time that XHR will process the response. But "response is ready" is very short and it explain why you got 0ms everytime.

Solution 2:[2]

You can use the following code

  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if(this.readyState == 1) console.time("count");
    if (this.readyState == 4 && this.status == 200) {
      console.timeEnd("count");
    }
  };
  xhttp.open("GET", "https://mydomain. com/API", true);
  xhttp.send();
}

With this, you can check the time after the request has been opened. If you want to count the total time you can move the console.time before the open function call, and you can see on the network tab (chrome browser) that the timing is near the actual timing the browser counts.

  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      console.timeEnd("count");
    }
  };
  console.time("count");
  xhttp.open("GET", "https://mydomain. com/API", true);
  xhttp.send();
}

Note: if you get near 0ms for your request make sure you have disabled the cache of your request from the network tab

Solution 3:[3]

From MDN, readyState = 3 means Response's body is being received. Which I interpret as the request has already processed and the client is now downloading the response.

To achieve what you want I would suggest measure the time difference from when you send the request, just above xhttp.send(), and when the readyState is 3. If it was me, I would extend it to when readyState is 4. This gives more realistic times which an end user might experience and includes the time it takes for the request to go over the network.

As a side note may be try measuring the difference between readyState=2 and readyState=4. Per MDN docs readyState is 2 when the request has been sent and the client has received the headers back, which means the connection has been successful. So, it should give accurate representation of time spent during processing on server side and will eliminate any network delays.

I would love to know your results.

Solution 4:[4]

I would do something like the following:

function timeFetch() {
  let begin
  const xhttp = new XMLHttpRequest()
  xhttp.open("GET", "https://myDomain. com/API", true)
  xhttp.send()
  xhttp.onreadystatechange = function () {
    if (this.readyState == 1) {
      begin = new Date(Date.now())
    }

    if (this.readyState == 4 && this.status == 200) {
      let end = new Date(Date.now())
      console.log(
        "Execution time (ms):" + (begin.getMilliseconds() - end.getMilliseconds()))
    }
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Romain V...
Solution 2 prieston
Solution 3
Solution 4