Why first network call takes more time than subsequent ones? - javascript

I am trying to understand this behavior where first network call takes more than double of subsequent ones. I know that DNS resolving will not take more than 5-50ms and it happens only in the initial call. Considering this info, there shouldn’t be much difference in time taken for the first call and subsequent calls.
I have tested this behavior with some famous URLs in separate incognito windows for each with cache disabled and attached a few screenshots to support my observation below. Can anyone help me understand this behavior?
Note: The readings are taken in full speed internet connection
Thanks in advance

After a few experiments, I found out that Content Download (browser request steps) part of the request is speeding up 1.5-2 times
This looks like a cause of TCP Slow Start algorithm
As it states:
modern browsers either open multiple connections simultaneously or reuse one connection for all files requested from a particular web server
That might be the reason for the first request to be slower than others
Also, #Vishal Vijay made a good addition:
Making initial connection handshake to the server is taking time (DNS Lookup + Initial connection + SSL). Browsers are creating Persistent Connections for HTTP requests and keep it open for some time. If any request came in for the same domain within that time, the browser will try to reuse the same connection for faster response.

In some cases it might be server-side cache mechanism causing subsequent request to process faster, but let's just talk about the browser-side stuffs.
When you hover on the waterfall 'blocks' you will get the time details:
Here is a quick reference for each of the phases (from Google Developers):
Queueing. The browser queues requests when:
There are higher priority requests.
There are already six TCP connections open for this origin, which is the limit. Applies to HTTP/1.0 and HTTP/1.1 only.
The browser is briefly allocating space in the disk cache
Stalled. The request could be stalled for any of the reasons described in Queueing.
DNS Lookup. The browser is resolving the request's IP address.
Proxy negotiation. The browser is negotiating the request with a proxy server.
Request sent. The request is being sent.
ServiceWorker Preparation. The browser is starting up the service worker.
Request to ServiceWorker. The request is being sent to the service worker.
Waiting (TTFB). The browser is waiting for the first byte of a response. TTFB stands for Time To First Byte. This timing includes 1
round trip of latency and the time the server took to prepare the
response.
Content Download. The browser is receiving the response.
Receiving Push. The browser is receiving data for this response via HTTP/2 Server Push.
Reading Push. The browser is reading the local data previously received.
So what's difference between the first and subsequent requests in traditional HTTP/1.1 scenario?
DNS Lookup: It might take more time to resolve DNS for the first request. Subsequent requests will resolve a lot faster using browser DNS cache.
Waiting (TTFB): The first request have to establish TCP connecting to the server. Due to HTTP keep-alive mechanism, subsequent requests to the same server will reuse the existing TCP connection to prevent another TCP handshake, thus reducing three round-trip time compared the first request.
Content Download: Due to TCP slow start, the first request will need more time to download content. Since subsequent requests will reuse the TCP connection, when the TCP window scaled up, the content will be downloaded much faster than the first request.
Thus generally subsequent requests should be much faster than the first request. Actually this leads to a common network optimization strategy: Use as few domains as possible for your website.
HTTP/2 even introduces multiplexing to better reuse a single TCP connection. That's why HTTP/2 will give a performance boost in modern front end world, where we deploy tons of small assets on the CDN servers.

Related

How much overhead does an Ajax request have

I'm working on a web app that needs to process large amounts of data from the server.
The data can be "streamed" and processed in chunks, so to make it faster I break the data up into packets and download each packet with ajax.
I use javascript promises to send the next ajax request right when the previous one receives it's data.
Each packet is about 300KB and there are normally 20 of them in total.
Now my question is, when I don't have the packets broken up (ie I download a single 6MB file) it takes my browser/network about 4 seconds to do it.
However when I break it up into packets it takes the browser about 8 seconds to download all the packets even though the file size is ultimately the same.
I expected there to be some overhead from each request sending new http headers ect... but to be twice as slow was quite a shock.
I tried moving the ajax requests onto a web worker thinking the main thread was possibly delaying them, but the same thing happens.
Is there anyway to speed up this process, or are there any javascript protocols that would keep the connection open.
I know the browser can do this with video streaming, but I wouldn't know how to use that protocol with binary packets.
I believe by default TCP connections in the browser are also subject to TCP congestion controls.
"Slow Start" for example ramps up the rate at which data is read/sent, so not to overwhelm the server and get a baseline of what traffic load the server can handle.
If you break up your 6MB request into many requests, it's possible your paying the "slow start" penalty on each request.
More info here:
https://en.wikipedia.org/wiki/TCP_congestion_control
You could try turning on keep-alive headers on the server and see if this improves things.

Prevent recursive calls of XmlHttpRequest to server

I've been googling for hours for this issue, but did not find any solution.
I am currently working on this app, built on Meteor.
Now the scenario is, after the website is opened and all the assets have been loaded in browser, the browser constantly makes recursive xhr calls to server. These calls are made at the regular interval of 25 seconds.
This can be seen in the Network tab of browser console. See the Pending request of the last row in image.
I can't figure out from where it originates, and why it is invoked automatically even when the user is idle.
Now the question is, How can I disable these automatic requests? I want to invoke the requests manually, i.e. when the menu item is selected, etc.
Any help will be appriciated.
[UPDATE]
In response to the Jan Dvorak's comment:
When I type "e" in the search box, the the list of events which has name starting with letter "e" will be displayed.
The request goes with all valid parameters and the Payload like this:
["{\"msg\":\"sub\",\"id\":\"8ef5e419-c422-429a-907e-38b6e669a493\",\"name\":\"event_Coll_Search_by_PromoterName\",\"params\":[\"e\"]}"]
And this is the response, which is valid.
a["{\"msg\":\"data\",\"subs\":[\"8ef5e419-c422-429a-907e-38b6e669a493\"]}"]
The code for this action is posted here
But in the case of automatic recursive requests, the request goes without the payload and the response is just a letter "h", which is strange. Isn't it? How can I get rid of this.?
Meteor has a feature called
Live page updates.
Just write your templates. They automatically update when data in the database changes. No more boilerplate redraw code to write. Supports any templating language.
To support this feature, Meteor needs to do some server-client communication behind the scenes.
Traditionally, HTTP was created to fetch dead data. The client tells the server it needs something, and it gets something. There is no way for the server to tell the client it needs something. Later, it became needed to push some data to the client. Several alternatives came to existence:
polling:
The client makes periodic requests to the server. The server responds with new data or says "no data" immediately. It's easy to implement and doesn't use much resources. However, it's not exactly live. It can be used for a news ticker but it's not exactly good for a chat application.
If you increase the polling frequency, you improve the update rate, but the resource usage grows with the polling frequency, not with the data transfer rate. HTTP requests are not exactly cheap. One request per second from multiple clients at the same time could really hurt the server.
hanging requests:
The client makes a request to the server. If the server has data, it sends them. If the server doesn't have data, it doesn't respond until it does. The changes are picked up immediately, no data is transferred when it doesn't need to be. It does have a few drawbacks, though:
If a web proxy sees that the server is silent, it eventually cuts off the connection. This means that even if there is no data to send, the server needs to send a keep-alive response anyways to make the proxies (and the web browser) happy.
Hanging requests don't use up (much) bandwidth, but they do take up memory. Nowadays' servers can handle multiple concurrent TCP connections, so it's less of an issue than it was before. What does need to be considered is the amount of memory associated with the threads holding on to these requests - especially when the connections are tied to specific threads serving them.
Browsers have hard limits on the number of concurrent requests per domain and in total. Again, this is less of a concern now than it was before. Thus, it seems like a good idea to have one hanging request per session only.
Managing hanging requests feels kinda manual as you have to make a new request after each response. A TCP handshake takes some time as well, but we can live with a 300ms (at worst) refractory period.
Chunked response:
The client creates a hidden iFrame with a source corresponding to the data stream. The server responds with an HTTP response header immediately and leaves the connection open. To send a message, the server wraps it in a pair of <script></script> tags that the browser executes when it receives the closing tag. The upside is that there's no connection reopening but there is more overhead with each message. Moreover, this requires a callback in the global scope that the response calls.
Also, this cannot be used with cross-domain requests as cross-domain iFrame communication presents its own set of problems. The need to trust the server is also a challenge here.
Web Sockets:
These start as a normal HTTP connection but they don't actually follow the HTTP protocol later on. From the programming point of view, things are as simple as they can be. The API is a classic open/callback style on the client side and the server just pushes messages into an open socket. No need to reopen anything after each message.
There still needs to be an open connection, but it's not really an issue here with the browser limits out of the way. The browser knows the connection is going to be open for a while, so it doesn't need to apply the same limits as to normal requests.
These seem like the ideal solution, but there is one major issue: IE<10 doesn't know them. As long as IE8 is alive, web sockets cannot be relied upon. Also, the native Android browser and Opera mini are out as well (ref.).
Still, web sockets seem to be the way to go once IE8 (and IE9) finally dies.
What you see are hanging requests with the timeout of 25 seconds that are used to implement the live update feature. As I already said, the keep-alive message ("h") is used so that the browser doesn't think it's not going to get a response. "h" simply means "nothing happens".
Chrome supports web sockets, so Meteor could have used them with a fallback to long requests, but, frankly, hanging requests are not at all bad once you've got them implemented (sure, the browser connection limit still applies).

Do AJAX applications that use POST requests always fail in Internet Explorer?

I have recently discovered that problems with intermittent failures for users running my application using Internet Explorer is due to a bug in Internet Explorer. The bug is in the HTTP stack, and should be affecting all applications using POST requests from IE. The result is a failure characterized by a request that seems to hang for about 5 minutes (depending on server type and configuration), then fail from the server end. The browser application will error out of the post request after the server gives up. I will explain the IE bug in detail below.
As far as I can tell this will happen with any application using XMLHttpRequest to send POST requests to the server, if the request is sent at the wrong moment. I have written a sample program that attempts to send the POSTS at just those times. It attempts to send continuous POSTs to the server at the precise moment the server closes the connections. The interval is derived from the Keep-Alive header sent by the server.
I am finding that when running from IE to a server with a bit of latency (i.e. not on the same LAN), the problem occurs after only a few POSTs. When it happens, IE locks up so hard that it has to be force closed. The ticking clock is an indication that the browser is still responding.
You can try it by browsing to: http://pubdev.hitech.com/test.post.php. Please take care that you don't have any important unsaved information in any IE session when you run it, because I am finding that it will crash IE.
The full source can be retrieved at: http://pubdev.hitech.com/test.post.php.txt. You can run it on any server that has php and is configured for persistent connections.
My questions are:
What are other people's experiences with this issue?
Is there a known strategy for working around this problem (other than "use another browser")?
Does Microsoft have better information about this issue than the article I found (see below)?
The problem is that web browsers and servers by default use persistent connections as described in RFC 2616 section 8.1 (see http://www.ietf.org/rfc/rfc2616.txt). This is very important for performance--especially for AJAX applications--and should not be disabled. There is however a small timing hole where the browser may start to send a POST on a previously used connection at the same time the server decides the connection is idle and decides to close it. The result is that the browser's HTTP stack will get a socket error because it is using a closed socket. RFC 2616 section 8.1.4 anticipates this situation, and states, "...clients, servers, and proxies MUST be able to recover from asynchronous close events. Client software SHOULD reopen the transport connection and retransmit the aborted sequence of requests without user interaction..."
Internet Explorer does resend the POST when this happens, but when it does it mangles the request. It sends the POST headers, including the Content-Length of the data as posted, but it does not send the data. This is an improper request, and the server will wait an unspecified amount of time for the promised data before failing the request with an error. I have been able to demonstrate this failure 100% of the time using a C program that simulates an HTTP server, which closes the socket of an incoming POST request without sending a response.
Microsoft seems to acknowledge this failure in http://support.microsoft.com/kb/895954. They say that it affects IE versions 6 through 9. That provide a hotfix for this problem, that has shipped with all versions of IE since IE 7. The hotfix does not seem satisfactory for the following reasons:
It is not enabled unless you use regedit to add a key called FEATURE_SKIP_POST_RETRY_ON_INTERNETWRITEFILE_KB895954 to the registry. This is not something I would expect my users to have to do.
The hotfix does not actually fix the broken POST. Instead, if the socket gets closed as anticipated by the RFC, it simply errors out immediately without trying to resent the POST. The application still fails--it just fails sooner.
The following example is a self contained php program that demonstrates the bug. It attempts to send continuous POSTs to the server at the precise moment the server closes the connections. The interval is derived from the Keep-Alive header sent by the server.
We've encountered this problem with IE on a regular basis. There is no good solution. The only solution that is guaranteed to solve the problem is to ensure that the web server keepalive timeout is higher than the browser keepalive timeout (by default with IE this is 60s). Any situation where the web server is set to a lower value can result in IE attempting to reuse the connection and sending a request that gets rejected with a TCP RST because the socket has been closed. If the web server keepalive timeout value is higher than IE's keepalive timeout then IE's reuse of the connections ensure that the socket won't be closed. With high latency connections you'll have to consider the latency time as the time spent in-transit could be an issue.
Keep in mind however, that increasing the keepalive on the server means that an idle connection is using server sockets for that much longer. So you may need to size the server to handle a large number of inactive idle connections. This can be a problem as it may result in a burst of load to the server that the server isn't able to handle.
Another thing to keep in mind. You note that the RFC section 8.1.4 states :"...clients, servers, and proxies MUST be able to recover from asynchronous close events. Client software SHOULD reopen the transport connection and retransmit the aborted sequence of requests without user interaction..."
You forgot a very important part. Here's the full text:
Client software SHOULD reopen the
transport connection and retransmit the aborted sequence of requests
without user interaction so long as the request sequence is
idempotent (see section 9.1.2). Non-idempotent methods or sequences
MUST NOT be automatically retried, although user agents MAY offer a
human operator the choice of retrying the request(s). Confirmation by
user-agent software with semantic understanding of the application
MAY substitute for user confirmation. The automatic retry SHOULD NOT
be repeated if the second sequence of requests fails
An HTTP POST is non-idempotent as defined by 9.1.2. Thus the behavior of the registry hack is actually technically correct per the RFC.
No, generally POST works in IE. It may be an issue, what you are saying,
but it isn't such a major issue to deserve this huge a post.
And when you issue POST ajax request, to make sure every browser inconsistency is covered, just use jquery.
One more thing:
Noone sane will tell you to "use another browser" because IE is widely used and needs to be taken care of (well, except IE6 and for some, maybe even some newer versions)
So, POST has to work in IE, but to make yourself covered for unexpected buggy behavior, use jquery and you can sleep well.
I have never encountered this issue. And our clients mostly runs IE6.
I suspect you've configured your keep-alive timer too long. Most people configure it to be under 1 second because persistent connections are only meant to speed up page loading not service Ajax calls.
If you have keep-alive configured too long you'll face much more severe problems than IE crashing - your server will run out file descriptors to open sockets!*
* note: Incidentally, opening and not closing connections to HTTP servers is a well known DOS attack that tries to force the server to reach its max open socket limit. Which is why most server admins also configure connection timeouts to avoid having sockets open for too long.

WebSockets: useful for reducing overhead?

I am building a dynamic search (updated with every keystroke): my current scheme is to, at each keystroke, send a new AJAX request to the server and get data back in JSON.
I considered opening a WebSocket for every search "session" in order to save some overhead.
I know that this will save time, but the question is, is it really worth it, considering those parameters:
80ms average ping time
166ms: time between each keystroke, assuming the user types relatively fast
A worst-case transfer rate of 1MB/s, with each data pack that has to be received on every keystroke being no more than 1KB.
The app also takes something like 30-40ms to weld the search results to the DOM.
I found this: HTTP vs Websockets with respect to overhead, but it was a different use case.
Will websockets reduce anything besides the pure HTTP overhead? How much is the HTTP overhead (assuming no cookies and minimal headers)?
I guess that HTTP requests open a new network socket on each request, while the WebSocket allows us to use only one all the time. If my understanding is correct, what is the actual overhead of opening a new network socket?
It seems like WebSockets provide a better performance in situations like yours.
Web Socked
small handshake header
full duplex communication after the handshake.
After the connection is established, only 2 bytes are added per transmitted request/response
Http
Http headers are sent along with each request
On the other hand, WebSocket is a relatively new technology. It would be wise to investigate web browser support potential network related issues.
Ref:
http://websocket.org/quantum.html
http://www.youtube.com/watch?v=Z897fkPn7Rw
http://en.wikipedia.org/wiki/WebSocket#Browser_support

How keep-alive of HTTP can/is play role in AJAX application

"keep-alive" its there in HTTP. Some says it good should be used, but i am unable to get to any conclusion.
So please provide your input/answer/views so i can get some ground for this,
What it does?
Scenario where it should and should not be done?
How it can make AJAX application better ?
Risks DO's and DONT's if any?
Thank you all for inputs.
First off if your connection to the server is using HTTP/1.1 then you are most likely already using "keep-alive".
What is it? Logically HTTP is a connectionless protocol. That is each request/response to the server creates a new connection, does its business and drops the connection. However in HTTP/1.1 the default behaviour is to keep the connection open for use by subsequent requests to the server. The "keep-alive" header was added to HTTP/1.0 to allow this behaviour to be opted into, in HTTP/1.1 the server needs to opt-out by closing the connection itself and/or sending a "connection-close" header in response.
Why is it beneficial? Creating a connection especially one that needs to be authenticated can take some time. By re-using an existing connection the setup and authentication effort is much reduced.
How can it make your AJAX app better? You are probably already benefitting from it.
What are the risks? When making a connection through a shared appliance which may make a connection to the server in the clients behalf it is possible for other clients to re-use the connection, however that also makes it possible for other clients to use a connection that the server has authenticated for a different user.
It keeps the TCP socket to the client open, so you have not reestablish connection to send another HTTP request;
Keep-alive improves http performance when there are many requests in a row. It should not been used however if the requests are rare (server normally closes connection if there are no more requests coming from a client during some period of time).
Well, if your AJAX application sends a lot of requests to the server keep-alives improve its performance.
There is a risk of sockets depletion on server side, so server has rights to interrupt even keep-alive connections.
Really it boils down to questions of performance and resource.
Using a high(er) keep alive reduces latency on requests. This is particularly an issue if you are running over SSL where there additional handshakes to establish a connection.
OTOH, this will mean that there additional server processes.threads sitting idle, waiting for a subsequent request or the keep-alive to expire. This can hog memory and therefore slow down your server.
So you really need to play around and see what's acceptable in terms in browser performance vs server load.
Authentication (basic/digest/session based) is not relevant - it is the request which is authenticated - not the socket connection.
Note that the last time I did a fresh Apache install it came with a default setting of 5 seconds for the keep alive. This is ridiculously long for a non-ajax site.
C.

Categories

Resources