High Performance Computing

Quick and easy network bandwidth benchmarking on Linux and MacOS X

A couple years ago, I setup my first gigabit Ethernet network. I wanted to test just how fast it could go with the equipment I gave it (that is, the NICs, cabling, and switches it operated on). Gigabit Ethernet, theoretically, can operate at 1000 Mbit/sec. This translates to 119.209 MiB/sec, units your OS typically displays when doing downloads (1000 Mbit/sec / 8 / 2^20). How close is your network setup to that maximum? Copying files between PCs, while being a very “real world” test, will be limited by how fast your disks can read or write. A specialized tool is needed.

While many system benchmark suites include network testing tools, most are not easily separate from their suites, and are not easy to install and use.

Enter NetStrain. It’s a very simple C application for Linux and MacOS X designed to stress network connections. Unfortunately, it’s not included in most Linux distributions or MacOS X, so you need to download and compile it yourself.

After compiling, use is simple. One machine acts as a server, and another machine acts as a client. Start the server first with:

netstraind -4 9999

This starts a server using IPv4 networking on port 9999 (use a different port if you know this is in use; remember to pick one above 1024 if you’re not running as root). On your client machine, start the client connect to the server (assumed to be running on IP 192.168.1.2 and port 9999):

netstrain -4 192.168.1.2 9999 send

NetStrain will then try to send as much over your network connection as it can as long as the client is running. NetStrain is very spartan, so there are not a lot of options. In addition to sending, you may want to test receiving, as well simultaneously sending and receiving. Check NetStrain’s README for details.

Most likely, you will not get anything near 119.209 MiB/sec—but hopefully, you’ll get better speeds than a normal 100 Mbit connection to make everything worthwhile.

What if you want to make things faster (without buying newer, better hardware)? There are many parameters you can tune on your operating system’s networking stack. However, in most modern operating systems, most of them are already set, or are automatically configured (e.g. TCP window scaling). The one major tunable is something called MTU (Maximum Transmission Unit).

Data is transferred over Ethernet in packets; the MTU defines the size of those packets. A larger packet size means fewer packets are needed to send the same amount of data, reducing the amount of processing that needs to be done by your computer, switches, and routers. Your computer’s NIC, switches, and routers need to support large-size MTUs, a feature often advertised as “Ethernet jumbo frames.” Jeff Atwood wrote an article on the promise and perils of jumbo frames that you may want to read if you’re interested.

Splitting a Sequence into Subsequences with Python

I’m writing a load balancing algorithm for this cluster I’m working on, and have a bunch of things in a Python list sequence. So came the issue, how to divide the list into sublists for each node in the cluster to compute? I came up with the algorithm:


def split_seq_stride(l, n):
  """Splits a sequence l into a list of subsequences containing at least n
  elements each, not preserving order. The first few subsequences may contain
  n+1 elements, containing the last few elements. (Algorithm is good for load
  balancing)"""
  r=[]
  k=len(l)/n
  [r.append(l[i::k]) for i in range(k)]
  return r

which behaves like:

>>> l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> print split_seq_stride(l, 3)
[[1, 4, 7, 10], [2, 5, 8], [3, 6, 9]]

Assuming each task is an equal amount of work, this algorithm is a good load balancing algorithm. it prevents any node from having to do any less significant work than the others.

Probably useful for someone: what about splitting up a sequence in-order, with the last subsequence containing fewer elements? This code segment does just that:


def split_seq(l, n):
  """Splits a sequence l into a list of subsequences containing at most n
  elements each, preserving order. The last subsequence may contain less
  than n elements."""
  r=[]
  [r.append(l[s:s+n]) for s in range(0, len(l), n)]
  return r

which behaves like:

>>> l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> print split_seq(l, 3)
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]

Thanks to yason and others on EFnet’s #python for pointers.

Syndicate content