Cheat Sheet on Curl Performance Metrics: how to benchmark server latency with curl — Speed Test Demon
Tags: cloudfront, cloudinary, aws, cdn
Published: 2021-08-22 04:49:53

---
title: Cheat Sheet on Curl Performance Metrics: how to benchmark server latency with curl — Speed Test Demon
published: true
date: 2021-07-01 05:48:08 UTC
tags: cloudfront,cloudinary,aws,cdn
canonical_url: https://speedtestdemon.com/a-guide-to-curls-performance-metrics-how-to-analyze-a-speed-test-result/
---

### 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 does](https://speedtestdemon.com/a-guide-to-curls-performance-metrics-how-to-analyze-a-speed-test-result/#What_does_curls_time_pretransfer_mean)[time\_pretransfer mean?](https://speedtestdemon.com/a-guide-to-curls-performance-metrics-how-to-analyze-a-speed-test-result/#What_does_curls_time_pretransfer_mean)"

(by the way, you can follow me on [twitter, Analyzing Software Performance](https://twitter.com/SpeedTestDemon) for new posts like these, or [email subscribe](https://speedtestdemon.com/))

- **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](https://man7.org/linux/man-pages/man1/curl.1.html).

I also have a section for each metric with more in-depth analysis. See sections with title “What does…”.

![](https://cdn-images-1.medium.com/max/1024/0*kZ6XSS6uABFSAwfE.jpeg)

### 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](https://github.com/speedtestdemon/speed-tests/blob/master/curl-format.txt) 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](http://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](https://speedtestdemon.com/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](https://twitter.com/SpeedTestDemon) (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!](https://speedtestdemon.com/wordpress-free-jetpack-cdn-faster-than-amazon-aws-cdn-cloudfront/)  
 [Is a premium CDN like CloudFront worth it, instead of a free CDN?](https://speedtestdemon.com/is-a-premium-cdn-like-cloudfront-worth-it-instead-of-a-free-cdn/)  
[CDN Speed Tests (Testing Methodology)](https://speedtestdemon.com/testing-methodology/)

[Cloudinary vs CloudFront: Cloudinary crushes Amazon Web Services!](https://speedtestdemon.com/cloudinary-cdn-totally-smokes-amazon-aws-cdn-cloudfront/)  
 [Python CDN Speed Test Script](https://speedtestdemon.com/python-cdn-speed-test-script/): I use this to automate the collection of metrics about CDNs.