First I tried different transfer methods (Samba and SSH) with no change, so it wasn't the transfer method.
Then I tested the storage. I changed to a fast USB hard drive, moved the USB hard drive around the USB hub in case of power/throughput issues, but was eventually satisfied it wasn't storage when I could get 22 megabyte throughput with a hdparm -t. I should have just done that first.
Next I suspected either USB or wifi.
A lot of forum posts suggest to try dwc_otg.speed=1 in cmdline.txt however that reduces the chipset to USB1 speeds (11Mb/sec) which wasn't a compromise I was willing to make. There was mention of something called FIQ from 2011/2012, but these improvements are included in the latest (2014-01-07) Raspbian image, so there's no need to tinker with FIQ anymore.
I wondered if it was the wifi signal, so I moved the Pi right next to the router, but no change. I plugged in an ethernet cable and the speed improved immensely. So it was either USB or wifi.
Searching around, I read many reports of people having problem with these Realtek RTL8188CUS (driver 8192cu) wifi dongles. There were several suggestions to make a file like /etc/modprobe.d/8192cu.conf and turn off the adaptor's power management features with the contents:
options 8192cu rtw_power_mgnt=0 rtw_enusbss=0
I tried this but still no luck, transfers still sat at 57kb/sec.
At this point I remembered my other Raspberry Pi was using a different USB wifi adaptor, an RaLink RT5370 (driver rt2800usb). I tried this dongle and the speed instantly improved. We can now rule out USB and wifi signal, and place the blame on the wifi adaptor.
I have two of these Realtek adaptors, a black one with EDUP on it, and a white one with COMFAST on it. Both produced the slow transfer speed, so it wasn't unique to this one adaptor.
As best I can figure out, either Realtek's driver or the implementation of the wifi hardware is rubbish, and there's no way it can be fixed.
I've ordered another RaLink dongle off eBay.