Measuring PC serial port latency
Back at the previous post I discovered some pretty nasty latency issues with USB Serial ports, where the default settings would make byte level responses unfeasible. For this reason I decided to test the delay times of different serial ports I have laying around my PC, with some unexpected results and oddities.
November 2024: At the request of someone interested via e-mail, binaries for Windows XP are now available.
Measuring latency
For this purpose I wrote a small C++ program that opens a given serial port, configures all the commonly used baud rates, and measures the time it takes to send a single byte and read it back (provided the RX/TX lines are tied together) and test it against the expected minimum time it would take to read back a byte. In essence, the time it takes to transmit it, start and stop bits included.
Windows binaries may be downloaded below and source code is available on the source code repository
Binary | |
---|---|
Windows 10 and above (64 bit) | Download |
Windows XP and above (32 bit) | Download |
The output of the application looks as follows:
COM6 (USB Serial Port)
Vendor: FTDI
Times measured in us
Speed Ideal Minimum Average Maximum Delta
110: 90909 430 1006 1808 -89902
300: 33333 39028 40058 43010 6724
600: 16666 19972 21211 22139 4544
1200: 8333 10038 11010 12013 2677
2400: 4166 4997 5896 6564 1730
4800: 2083 2830 3285 4040 1202
9600: 1041 1419 2004 2880 962
14400: 694 995 1226 2057 532
19200: 520 988 1250 2068 729
38400: 260 857 1011 1976 751
56000: 178 420 1006 1989 827
57600: 173 853 1007 2039 834
115200: 86 578 1009 2005 922
128000: 78 578 1007 1990 929
256000: 39 418 1003 1991 964
Pretty straightforward. The first column has the baud rate, the “Minimum” and “Maximum” columns have the minimum and maximum delay measured during the test, and the “Average” column has the average delay measured across the 256 bytes written / read to the serial port.
Special mention to the “Ideal” column that shows the ideal delay that would be expected if the byte is ready and read just as soon as it has been transmitted over the wire. Also the “Delta” column is the result of subtracting the “Ideal” value to the “Average” value. A delta of 0 would mean no delay at all, a positive delta means the byte is received some time after the stop bit was transmitted and a negative delta means the byte was received before the stop bit was expected to be transmitted. That first row will make sense later.
Now on to the test cases.
FTDI FT232RL (default settings)
Running the test with the configuration windows assigns it out of the box we get some depressing results (all times in μs)
Speed | Ideal | Avg. | Δ |
---|---|---|---|
110 | 90909 | 15906 | -75002 |
300 | 33333 | 47862 | 14528 |
600 | 16666 | 31883 | 15216 |
1200 | 8333 | 15952 | 7619 |
2400 | 4166 | 15900 | 11733 |
4800 | 2083 | 15900 | 13817 |
9600 | 1041 | 15898 | 14857 |
14400 | 694 | 15943 | 15249 |
19200 | 520 | 15894 | 15373 |
38400 | 260 | 15902 | 15641 |
56000 | 178 | 15902 | 15723 |
57600 | 173 | 15900 | 15726 |
115200 | 86 | 15898 | 15811 |
128000 | 78 | 15898 | 15820 |
256000 | 39 | 15892 | 15853 |
First the bad news, delta times (Δ) are simply awful. Almost none of them manages to fall below 10000 μs with most of them nearing 16000 μs.
Second, the first row, the one at 110 baud, has learned how to time travel with a negative delta so big it would mean we got back the entire byte even before the first bit has been transmitted, and without read errors! So this requires breaking out the logic analyzer.
After finding the magical U
character (Hex: 0x55) we discover that this
FTDI chip when asked to run at 110 bps it will silently configure itself to run
at 115200 bps instead.
Now, measuring any other actually working transmission we confirm that indeed the delay between bytes is close to what the application has measured. In this example we measure the delay between 0x55 and 0x56 at 9600 bps.
Around 15 ms of delay between bytes. Unacceptable.
FTDI FT232RL (low latency settings)
Next due to the unacceptable delay of the previous test, the FTDI chip is configured to have the lowest delay allowed, 1 ms, instead of the default 16 ms that the previous test has clearly shown it were being hindering the performance.
The new results are more acceptable, hovering around 1 ms on most cases.
Speed | Ideal | Avg. | Δ |
---|---|---|---|
110 | 90909 | 1006 | -89902 |
300 | 33333 | 40058 | 6724 |
600 | 16666 | 21211 | 4544 |
1200 | 8333 | 11010 | 2677 |
2400 | 4166 | 5896 | 1730 |
4800 | 2083 | 3285 | 1202 |
9600 | 1041 | 2004 | 962 |
14400 | 694 | 1226 | 532 |
19200 | 520 | 1250 | 729 |
38400 | 260 | 1011 | 751 |
56000 | 178 | 1006 | 827 |
57600 | 173 | 1007 | 834 |
115200 | 86 | 1009 | 922 |
128000 | 78 | 1007 | 929 |
256000 | 39 | 1003 | 964 |
The 110 baud bug is still there but we already know what it is, so no big deal.
SiLABS CP210x
Another USB to Serial chip, this time from Silicon Labs. The results are just like the default configuration FTDI, disappointing.
Speed | Ideal | Avg. | Δ |
---|---|---|---|
110 | 90909 | 38176 | -52732 |
300 | 33333 | 38185 | 4852 |
600 | 16666 | 22166 | 5499 |
1200 | 8333 | 14790 | 6457 |
2400 | 4166 | 9930 | 5763 |
4800 | 2083 | 8702 | 6619 |
9600 | 1041 | 8029 | 6987 |
14400 | 694 | 8137 | 7442 |
19200 | 520 | 8120 | 7599 |
38400 | 260 | 8235 | 7974 |
56000 | 178 | 8264 | 8085 |
57600 | 173 | 8204 | 8030 |
115200 | 86 | 8301 | 8214 |
128000 | 78 | 8250 | 8172 |
256000 | 39 | 8169 | 8129 |
Again the 110 baud configuration fails silently and uses the next thing, in this case the 300 baud config, and all the deltas hoover around the 8 ms mark.
Sadly, trying to disable the read buffer or reducing the latency, does nothing
to improve the latency, making the CP210x
series unusable for some purposes.
Motherboard COM port
Last, the COM port that my motherboard comes equipped with showed the strangest results so far
Speed | Ideal | Avg. | Δ |
---|---|---|---|
110 | 90909 | T! | T! |
300 | 33333 | T! | T! |
600 | 16666 | 85191 | 68525 |
1200 | 8333 | 42968 | 34635 |
2400 | 4166 | 21644 | 17477 |
4800 | 2083 | 11081 | 8998 |
9600 | 1041 | 5749 | 4707 |
14400 | 694 | 3885 | 3190 |
19200 | 520 | 3092 | 2571 |
38400 | 260 | 1413 | 1153 |
56000 | 178 | 961 | 782 |
57600 | 173 | 972 | 799 |
115200 | 86 | 495 | 409 |
128000 | 78 | E! | E! |
256000 | 39 | E! | E! |
First off, 110 and 300 baud are apparently supported (driver allows me to open the port with that configuration) but no data is ever received (Timeout) so yet another serial port oddity to add to the mix.
Then it seems that the fastest the baud rate, the lower the latency, making this port the absolute fastest of the ones tested… at 115200 bps.
And last, the non-standard 128000 and 256000 baud rates are not supported, but this time the driver is kind enough to let me know about it.
Like the CP210x
disabling the RX / TX buffers does nothing to improve the
latency but in this case, some baud rates are actually usable.
Conclusion
Serial ports on PC kinda suck if you are trying to minimize latency with very small payloads, getting into absurd territory if payloads are 1 or 2 bytes long.
Also, 110 bps is a cursed configuration. All the devices reported accepting that configuration when in reality all of them managed to screw it up in one way or another.