Cheat Sheet on Curl Performance Metrics: how to benchmark server latency with curl — Speed Test Demon
I wrote this cheatsheet mainly because I was mildly frustrated googling for 10+ minutes trying to figure out what in the world does time_pretransfer mean??? Try googling it. I'll wait. It's abstruse! Ugh!
The top Google result for “ curl time_pretransfer meaning" is this StackOverflow post, where they quote the curl man page and are still very confused (as was I): What is the meaning of time_pretransfer, I checked man page of curl, it says "it took from the start until the file transfer is just about to begin",I don't understand very well
That’s right-even if you “RTFM” (Read the Fine Manual), the curl man page itself is totally unhelpful about the meaning of time_pretransfer.
You’d think somebody would’ve written a good article on the curl metrics by now!
I finally figured out what time_pretransfer meant...after using my brrrr-rrrrain and the speed of light (0.186 miles/microsecond). But nobody had the right answer for it. And I do. Hence this article.
While here’s the full cheatsheet, there is also an explainer section I wrote on each of the metrics. If you’re interested in learning how I solve the meaning of time_pretransfer, jump down to the section " What doestime_pretransfer mean?"
(by the way, you can follow me on twitter, Analyzing Software Performance for new posts like these, or email subscribe)
- time_namelookup : how long DNS lookup took (translating domain name to IP address)
- time_connect : how long TCP handshake took (done by both HTTP and HTTPS)
- time_appconnect : how long SSL handshake took (only for HTTPS)
- time_redirect : how long the redirect took. It is 0 if there is no redirect. Need "-L" flag in curl to redirect.
- time_pretransfer : This is essentially an alias for either time_appconnect or time_connect (depending on HTTP or HTTPS). It is only useful as a delineator of when the specific request to the server has begun.
- time_starttransfer : This is when the server is ready to deliver bytes. Same as TTFB (Time To First Byte). It includes time_pretransfer, just subtract time_pretransfer from the time_starttransfer to get the amount of time spent in this phase
- : The total time of the entire curl call. Calculate time_total - time_starttransfer to get the data transfer (a.k.a. download) time.
These are also all the available metrics to be printed out, according to curl’s Linux man page.
I also have a section for each metric with more in-depth analysis. See sections with title “What does…”.
Curl speed test example
Here is a typical curl speed test output. Important to note: it is to an HTTPS URL. That factor is relevant to time_appconnect and time_pretransfer.
Get the curl-format.txt
from github and then run this curl command in order to get the output
$ curl -L -w "@curl-format.txt" -o tmp -s $YOUR_URL
time_namelookup : 0.001654s
time_connect : 0.054957s
time_appconnect : 0.156267s
time_pretransfer : 0.156494s
time_redirect : 0.000000s
time_starttransfer : 0.219013s
All time numbers are cumulative since the start of the curl. They are all in seconds.
Couple important notes about the curl command:
- The -o tmp is actually really important in order to actually download the file. If you tried to be smart and pass -o /dev/null , what curl does is it skips the download of the file because it interprets /dev/null to mean you're not download the file. And it would mean you get a download time of nearly 0 seconds (the delta between time_total and time_starttransfer.
- The -L flag is actually important in order to make curl follow redirections.
What does curl’s time_namelookup mean?
Thankfully this is an easy one to analyze. It is just DNS lookup time. The end result of this is just an IP address of the destination server that the curl program should talk to. No connection to the destination server has been made yet.
Note that this metric is actually important to factor in a speed test! You might be surprised if you think this is something as banal as DNS lookup.
Usually the DNS lookup goes by extremely quickly because the computer has probably cached the result. The computer caches because the results rarely change. For example, if there’s an A record for a domain that resolves to an IP, the computer can easily cache it — it’s maximum 32 bytes for the whole entry (and most computers have gigabytes of memory).
However, the DNS lookup time can take a while if the computer hasn’t cached it, especially if the destination website doesn’t have a lot of traffic, because it means the routers in-between doesn’t have the DNS lookup cached so they can’t return the result quickly. I’ve had one speed test where it was as much as 56% of the total download time (0.122108 seconds / 0.217073 seconds). Actually, wow, that’s an incredibly high percentage. I’m surprised it got that high. That was on a newbie website of mine, so it was a very low traffic website. The next DNS lookup took only 0.001408s seconds. It definitely got cached.
It is crucially important for CDN speed tests that the DNS operation is performed by curl. DNS lookups are how the CDN finds the IP address of the server closest to you. So for the same domain path, the IP address is going to be wildly different depending on your location. Although there is a way to exclude DNS lookup from the curl operation by giving curl an IP address as part of the input, you shouldn’t do it. DNS lookups are very important to how CDNs function!
That was rather interesting to write about. I am probably going to be doing DNS performance testing at some point, although this seems to be much harder to test than just plain CDN performance tests.
What does curl’s time_connect mean?
Time_connect is how long it takes to establish a TCP connection to the destination server. In the previous step, the DNS lookup, all we got back was an IP address. Now, at this step, there are actual sockets created, and data is ready to transfer between the client and server.
Note that this procedure is done for every request, for both HTTP and HTTPS and no matter which server you’re getting your request from (Google, Facebook, Microsoft, or any random guy’s WordPress server).
What does curl’s time_appconnect mean?
This is how long the SSL handshake takes, only measured for HTTPS requests. If you make a curl to an HTTP URL, curl will report a 0.000… for time_appconnect.
Note that this procedure is done for every HTTPS request, regardless of purpose or which server is responding, even if it’s Google.
Also, no idea why it’s called time_appconnect. That seems like a misnomer. Maybe better is “time_sslconnect”.
What does curl’s time_pretransfer mean?
time_pretransfer is essentially equal to either time_appconnect (HTTPS) or time_connect (HTTP) - depending on whether the request is HTTPS or HTTP. That's all it is. Nothing happens between time_pretransfer and the previous stage.
This was the one that really confused me. I was having a hard time understanding, until I realized something…the time lapse from the previous stage is far too short for there to be any network activity.
Why am I so confident that there is only CPU involved? Because the time lapse between time_pretransfer and time_appconnect is so small, even if data was traveling in a straight line between two points at the speed of light, there could not possibly be round-trip network transfer.
Here’s the math breakdown. First note that in the example curl output, the time difference between time_pretransfer and time_appconnect is only 227 microseconds. If you try it yourself, it could even be as low as 27 microseconds (as seen on a curl output on a curl’s github issue).
Second thing to note, what is the speed of light per microsecond? The speed of light is 186,000 miles per . Converting that to microseconds….there’s 1 million microseconds in a second, so 186,000 miles/sec * 1 sec / 1,000,000 microseconds = 0.186 miles per microsecond.
Finally, multiply the numbers we get 227 microseconds * 0.186 miles/microsecond = 42 miles.
Wait, 42 miles??
And that time is roundtrip, so one-way is only 21 miles.
Yeah…I seriously doubt there’s a server or datacenter that close to where I live. I’m in a major US city but not the usual suspects SF, NYC, LA, Chicago or Dallas.
What is probably going on here is curl is getting itself ready to receive bytes — and that’s it. There can’t possibly be any bytes exchanged as part of the time between time_pretransfer and time_appconnect.
So, time_pretransfer is really just the same as either time_connect or time_appconnect depending on whether the call was HTTP or HTTPS. As such, it seems the only purpose of time_pretransfer is to make it easier to clearly analyze how long it took for the server to begin transferring bytes. This is calculated by “time_starttransfer — time_pretransfer”….which brings us to the next metric, “time_starttransfer”.
What does curl’s time_starttransfer mean?
The time duration “time_starttransfer — time_pretransfer” is basically latency. It specifically measures how quickly the server can respond to this particular curl request. If you’re a backend engineer, this is the one metric you’ll pay a lot of attention to. All the other metrics are just normal TCP or SSL stuff for every server, and as a backend engineer, there’s not a lot you can do to affect the performance of those aside from renting more expensive servers.
Time_starttransfer is essentially the same as Time To First Byte (TTFB), which means how long it took for the server to prepare the response. If you’re a backend engineer, you’ll be familiar with that term too. Look, it’s just latency OK. And very important to get latency down.
OK lets walk through an example of what time_starttransfer metric would mean for CDNs. If you were requesting a file from a CDN, then this phase is how long it took for the CDN to prepare that file for you. Either the CDN has cached the file in memory so it can return it quickly to you. Or it has cached it in the SSD layer so it needs a little more time. Or maybe it doesn’t have it cached at all, so it has to make a HTTP/HTTPS request of its own to the origin server where the file is supposed to be located. So, this step is very crucial to analyze the difference between CDNs — everything else is going to be more or less the same.
One more example. Let’s say you were making an API request to Google Translate API to get back the French translation of an English sentence. Then this particular step (time_starttransfer — time_pretransfer) is how long it took for Google to translate. All previous steps are just normal TCP connection setup common to every other request.
Mkay? Time_starttransfer is just the latency of the server. We’re almost done going through every metric. Last two are time_redirect and time_total which are straightforward.
What does curl’s time_redirect mean?
If there was no redirect, this value is 0.000.
If there was a redirect, then you will see the amount of time that redirecting took.
Here’s a simple input to curl you can use to see how long a redirect might take: “google.com”, which gets redirected to www.google.com
For our purpose of speed testing CDNs, it’s important that time_redirect is 0 because redirecting is not really a relevant factor for a CDN’s download speed.
An important thing to note: if you’re interested in measuring redirect time, you want to make sure the redirect is happening at the right step. When I ran curl on google.com, time_redirect should've been on step 2 (right after time_namelookup). Here was the output I got:
curl -L -w "@curl-format.txt" -o /dev/null -s google.com
time_namelookup : 0.006038s
time_connect : 0.069728s
time_appconnect : 0.000000s
time_pretransfer : 0.069885s
time_redirect : 0.069052s
time_starttransfer : 0.161169s
Another important thing — you need -L flag to curl in order for it to follow redirects, or else it won't redirect. It's an easy mistake to make, because curl won't complain loudly it got a redirect but didn't follow. Your only clue is if 0.000 is in time_redirect but you expected it to be non-zero.
What does curl’s time_total mean?
Thankfully this one’s a really simple one to understand. This is just how long the entire download took — starting from the DNS lookup request all the way until the client has sent a FIN connection tear down since all the bytes have been downloaded.
By the way, if you are using curl to test CDN speeds, you should know that doing just one curl is by far not enough to measure a CDN’s delivery speed. The two metrics you should measure are “1st download speed” vs “cached downloads speed”, which means doing about 11 curl calls to the same URL. I have a more in-depth article explaining my testing methodology.
Final Thoughts
If you want a quick summary of each metric, refer to the cheat sheet at the top of the page.
If you have any questions, send me an email (hello /at/ speedtestdemon \dot/ com )or hit me up on Twitter (I love Twitter and I use it actively):
If you wanna get email notifications of new posts, you can subscribe
Related Essays
Jetpack CDN vs Amazon Web Services CloudFront: Jetpack surprisingly faster!
Is a premium CDN like CloudFront worth it, instead of a free CDN?
CDN Speed Tests (Testing Methodology)
Cloudinary vs CloudFront: Cloudinary crushes Amazon Web Services!
Python CDN Speed Test Script: I use this to automate the collection of metrics about CDNs.
Top comments (0)