Up to Main Index Up to Journal for February, 2019
JOURNAL FOR THURSDAY 28TH FEBRUARY, 2019
______________________________________________________________________________
SUBJECT: One-liners and ring buffers
DATE: Thu 28 Feb 22:42:23 GMT 2019
This week has been, hrm… not full of joy and wonders :( I have managed to
squeeze in a little time for WolfMUD, and have just enough time left for one
last journal entry this month.
As I mentioned in my last post[1], I’ve been trying to fight off this nasty
one-liner:
seq 1 1000000 | xargs -n1 bash -c 'netcat -z 172.16.1.1 4001'
Actually that is a poor example, it’s spinning up a bash shell each time it
executes netcat. That’s an artifact from where I was testing different sleep
delays using 'netcat -z 172.16.1.1 4001;sleep 1;' and varying the sleep time.
A better, or nastier — depending on how you look at it, example would be:
seq 1000000 | xargs -P8 -n1 -i@ netcat -z 172.16.1.1 4001
How is the fight going? I can fend off the one-liner across ethernet with the
CPU[2] running at about 30% with most of that being kernel processes and
software interrupts:
top - 22:25:41 up 7 days, 6:36, 5 users, load average: 0.15, 0.17, 0.23
Tasks: 157 total, 1 running, 156 sleeping, 0 stopped, 0 zombie
%Cpu(s): 2.1 us, 4.3 sy, 0.0 ni, 89.8 id, 0.3 wa, 0.0 hi, 3.5 si, 0.0 st
MiB Mem : 7432.3 total, 1070.7 free, 1950.7 used, 4410.8 buff/cache
MiB Swap: 2304.0 total, 2304.0 free, 0.0 used. 5099.7 avail Mem
PID USER PR NI VIRT RES SHR SWAP S %CPU %MEM TIME+ COMMAND
16889 diddymus 20 0 104.7m 7.8m 2.8m 0.0m S 30.6 0.1 0:42.43 server
This is using Go 1.12 that was just released. To put that into some sort of
perspective, the server is accepting and rejecting 3,000 connection attempts
per second. Not too bad, but also not terrific — I’m just using one machine to
throw traffic at the server. Most of the CPU time is spent in syscalls that
handle accepting and closing the network connections — and I don’t see how I
can optimise that.
I still say using iptables is a much better idea…
As part of my solution I’ve implemented a ring buffer for recording connection
attempts. The implementation is a fixed size (uses an array) power of 2 ring
buffer with free running indexes and bit-masking instead of modulo arithmetic.
All of the methods will inline and it’s turned out to be quite fast :)
Although I don’t need all of the functionality, the ring buffer is complete.
It has copious comments and tests so that other people can reuse it if they
want to. The tests will need fixing up if the array size is changed. Changing
the ring buffer to use a slice instead of an array is also trivial, but
performance will suffer. You can’t say I haven’t warned you now :P
I’m still working on improving the actual limiter. All of the testing,
benchmarking, tweaking performance, commenting the code and updating the
configuration documentation is taking some time. However, the ring buffer,
with tests, has just been pushed out to the public dev branch for those
interested in taking a look.
I also want to see how my Raspberry Pi3 running the server fares against the
i7 running the one-liner, but I haven’t had time — yet! ;)
--
Diddymus
[1] Journal for Saturday 23rd February: 23.html
[2] Client: i7-860 @ 2.80GHz, Server: i5-2400 @ 3.10GHz
Up to Main Index Up to Journal for February, 2019