The most surprising thing about network throughput is that it’s rarely the speed your ISP advertises.
Let’s see what actual data rate looks like in practice. Imagine you’re downloading a large file, say, a Linux ISO. Your browser shows a download speed. That number is a snapshot of throughput. But how do we measure it consistently and understand what influences it?
We use tools that measure the actual bytes transferred over a period. A common one is iperf3. You need two machines: a server and a client.
On the server, you run:
iperf3 -s
This tells iperf3 to listen for incoming connections and report on them.
On the client, you run:
iperf3 -c <server_ip_address> -t 30
This connects to the server, runs the test for 30 seconds, and reports the average data rate. The -c flag specifies the server’s IP, and -t sets the duration.
Here’s a sample output from the client:
Connecting to host <server_ip_address>, port 5201
[ 5] local 192.168.1.100 port 54321 connected with 192.168.1.200 port 5201
[ ID] Interval Transfer Bit-rate
[ 5] 0.00-30.00 sec 3200 MBytes 900 Mbits/sec sender
[ 5] 0.00-30.00 sec 3198 MBytes 899 Mbits/sec receiver
iperf Done.
This shows that over 30 seconds, the test transferred approximately 3200 Megabytes, resulting in a bit-rate of about 900 Megabits per second. This is the actual data rate achieved between these two points.
Throughput isn’t just about your internet connection; it’s the bottleneck performance between two endpoints. The problem it solves is distinguishing theoretical maximums from real-world performance. It tells you how much data can actually move.
Internally, iperf3 works by sending a stream of data (TCP or UDP) between the client and server for a specified duration. It times how long it takes to send a certain amount of data, or how much data can be sent within a time limit. It then calculates the average bit-rate.
The levers you control are primarily the network path itself and the configuration of the test. You can test over Wi-Fi, Ethernet, or even different network segments. You can specify TCP (which is reliable but can be slower due to retransmissions) or UDP (which is faster but can drop packets). For UDP, you can even specify a target bit-rate to see if the network can handle it.
If you run iperf3 -c <server_ip> -u -b 1000M, you’re asking the client to try and send data at 1000 Megabits per second using UDP. The output will show the actual rate achieved and the percentage of packets lost.
A common misconception is that if you have a 1 Gigabit Ethernet connection, you’ll always get 1 Gigabit per second. However, the actual throughput is heavily influenced by the slowest component in the path. This could be your Wi-Fi adapter, a congested switch, the CPU on either the client or server struggling to process packets, or even the storage speed if you’re writing the data to disk.
When using iperf3 to test UDP throughput, if you specify a target bit-rate higher than the network can sustain, you’ll see a significant packet loss percentage in the output. This indicates that the network path is saturated and cannot deliver all the data. The receiver will report a bit-rate that is lower than the target, and the sender will show that it attempted to send at the target rate but couldn’t due to buffer overflows or network congestion. This is distinct from TCP, where the sender automatically adjusts its rate based on acknowledgments from the receiver, and packet loss typically leads to a reduction in the achieved bit-rate rather than a reported failure to meet a target.
The next concept you’ll encounter is latency, which is distinct from throughput but equally critical for network performance.