English 日本語
INTERSTELLAR TECH BLOG

Measuring network performance between Linux, Mac, and Windows terminals (iperf/ntttcp)

closeup photo of black analog speedometer

Hello, this is Agata.

In this article, we will be looking at how to measure network performance between Linux, Mac and Windows terminals.

However, if you are using Windows, please go to Microsoft’s page.

https://learn.microsoft.com/en-us/azure/virtual-network/virtual-network-bandwidth-testing?tabs=windows

It seems that people are measuring using iperf3 on Windows without worrying about it, but as this Microsoft article explains, because it is not running on Windows’ native API, there is a possibility that the results will differ from the actual performance.
Windows users should refer to the above Microsoft article and use ntttcp.

Of course, iperf3 is not compatible with Windows to Linux or Windows to Mac.
For Linux, the Linux version of ntttcp has been released, so use this.
Unfortunately, the Mac version of ntttcp does not appear to have been released. If you want to measure between Mac and Windows, you may have to use iperf, although it is not accurate.

When measuring on Linux or Mac

So, let’s get back on track and look at measuring on Linux or Mac.

To measure, you need to install iperf3 on both of the two devices you want to measure.

There is a server side and a client side of iperf3, but you can switch between them using options, so you can install the same version on both.

Installation

First, let’s install ipef3.

Linux (Ubuntu)

we will use Ubuntu as an example.

sudo apt install iperf3

Mac

brew install iperf3

Measurement

The process is basically the same for both Linux and Mac.

One of the two devices is designated as the server, and the other as the client. You can decide which one is which as you like.

Start iperf3 in server mode on the device that will be the server, and start iperf3 in client mode on the device that will be the client.

If your firewall is enabled, disable it or open the port used by iperf3 (the default is 5201).

Use the following command to start the server side first.

iperf3 -s

Execution results

The following execution results will be displayed on the client side.

Connecting to host 192.168.0.1, port 5201
[  5] local 192.168.0.129 port 50893 connected to 192.168.0.1 port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  75.9 MBytes   636 Mbits/sec                  
[  5]   1.00-2.00   sec  61.0 MBytes   511 Mbits/sec                  
[  5]   2.00-3.00   sec  68.8 MBytes   578 Mbits/sec                  
[  5]   3.00-4.00   sec  71.2 MBytes   598 Mbits/sec                  
[  5]   4.00-5.00   sec  67.0 MBytes   560 Mbits/sec                  
[  5]   5.00-6.00   sec  70.0 MBytes   589 Mbits/sec                  
[  5]   6.00-7.00   sec  72.9 MBytes   610 Mbits/sec                  
[  5]   7.00-8.00   sec  60.0 MBytes   503 Mbits/sec                  
[  5]   8.00-9.00   sec  72.8 MBytes   610 Mbits/sec                  
[  5]   9.00-10.00  sec  63.9 MBytes   538 Mbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-10.00  sec   683 MBytes   573 Mbits/sec                  sender
[  5]   0.00-10.02  sec   682 MBytes   571 Mbits/sec                  receiver

iperf Done.

Other

Setting the measurement time

If you start it as it is, the measurement time is set to 10 seconds. This may cause measurement errors to increase due to temporary fluctuations in network load.

Therefore, it may be better to set the measurement time to a longer time, such as 60 seconds.

The measurement time can be set using the -t option.

iperf3 -c 192.168.8.3 -t 60

Measuring in the opposite direction

Incidentally, when you start the client normally, the data is sent from the client to the server and measured.

If you want to measure the speed in the opposite direction for some reason, you can switch it by simply adding -R to the client side options.

iperf3 -c 192.168.0.1 -R
Connecting to host 192.168.0.1, port 5201
Reverse mode, remote host 192.168.0.1 is sending
[  5] local 192.168.0.129 port 51116 connected to 192.168.0.1 port 5201
[ ID] Interval           Transfer     Bitrate
[  5]   0.00-1.00   sec  76.8 MBytes   641 Mbits/sec                  
[  5]   1.00-2.00   sec  79.2 MBytes   667 Mbits/sec                  
[  5]   2.00-3.00   sec  81.0 MBytes   677 Mbits/sec                  
[  5]   3.00-4.00   sec  80.6 MBytes   676 Mbits/sec                  
[  5]   4.00-5.00   sec  80.4 MBytes   674 Mbits/sec                  
[  5]   5.00-6.00   sec  80.4 MBytes   674 Mbits/sec                  
[  5]   6.00-7.00   sec  78.9 MBytes   662 Mbits/sec                  
[  5]   7.00-8.00   sec  76.5 MBytes   644 Mbits/sec                  
[  5]   8.00-9.00   sec  80.2 MBytes   671 Mbits/sec                  
[  5]   9.00-10.00  sec  78.1 MBytes   657 Mbits/sec                  
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bitrate         Retr
[  5]   0.00-10.02  sec   795 MBytes   666 Mbits/sec   12            sender
[  5]   0.00-10.00  sec   792 MBytes   664 Mbits/sec                  receiver

iperf Done.

JSON output

If you are planning to process the data in some way later, it may be more convenient to output it in JSON format.

As you can see from the following sample, it is output in more detail.

iperf3 -c 192.168.0.1 -J
{
	"start":	{
		"connected":	[{
				"socket":	5,
				"local_host":	"192.168.0.129",
				"local_port":	51240,
				"remote_host":	"192.168.0.1",
				"remote_port":	5201
			}],
		"version":	"iperf 3.18",
		"system_info":	"Darwin Agata-MacBook-Pro.local 23.6.0 Darwin Kernel Version 23.6.0: Thu Sep 12 23:34:49 PDT 2024; root:xnu-10063.141.1.701.1~1/RELEASE_X86_64 x86_64",
		"timestamp":	{
			"time":	"Fri, 31 Jan 2025 05:12:25 UTC",
			"timesecs":	1738300345
		},
		"connecting_to":	{
			"host":	"192.168.0.1",
			"port":	5201
		},
		"cookie":	"2lmxmjdwqnodwixbylwsplixxex4geldlzo6",
		"tcp_mss_default":	1448,
		"target_bitrate":	0,
		"fq_rate":	0,
		"sock_bufsize":	0,
		"sndbuf_actual":	131072,
		"rcvbuf_actual":	131072,
		"test_start":	{
			"protocol":	"TCP",
			"num_streams":	1,
			"blksize":	131072,
			"omit":	0,
			"duration":	60,
			"bytes":	0,
			"blocks":	0,
			"reverse":	0,
			"tos":	0,
			"target_bitrate":	0,
			"bidir":	0,
			"fqrate":	0,
			"interval":	1
		}
	},
	"intervals":	[{
			"streams":	[{
					"socket":	5,
					"start":	0,
					"end":	1.004466,
					"seconds":	1.0044660568237305,
					"bytes":	72351744,
					"bits_per_second":	576240429.49773228,
					"omitted":	false,
					"sender":	true
				}],
			"sum":	{
				"start":	0,
				"end":	1.004466,
				"seconds":	1.0044660568237305,
				"bytes":	72351744,
				"bits_per_second":	576240429.49773228,
				"omitted":	false,
				"sender":	true
			}
		}, {
			"streams":	[{
					"socket":	5,
					"start":	1.004466,
					"end":	2.002778,
					"seconds":	0.998311996459961,
					"bytes":	73007104,
					"bits_per_second":	585044388.99971151,
					"omitted":	false,
					"sender":	true
				}],
			"sum":	{
				"start":	1.004466,
				"end":	2.002778,
				"seconds":	0.998311996459961,
				"bytes":	73007104,
				"bits_per_second":	585044388.99971151,
				"omitted":	false,
				"sender":	true
			}
		}, {
			"streams":	[{
					"socket":	5,
.
.
.
PAGE TOP