Thursday, October 21, 2010
The limits of sleeping
Testing “Project: Wolowizard” isn't easy, what with dealing with The Protocol Stack From Hell™ and clarifying which optional fields of certain messages are mandatory, further complicated by the fact that some optional mandatory fields are optional if other optional mandatory fields are included, but there's also a feature that if used, means you may not include an optional mandatory field, but if you do, then you need to set another optional optional field.
It's all very confusing.
But while I'm waiting for the first extended test run to finish (24 hours of continous tests), I decided to investigate a particular phenomenon I've noticed when developing the testing program.
We need a way to test various message rates and one of the easiest is somethine like:
for count = 1 , 1000 do endpoint:send(msg) sim.sleep(thepausethatrefreshes) end
If I want to send 10 messages per second, then
thepausethatrefreshes
will be 0.1
(sleep for a
tenth of a second); if I want 1000 messages per second, then
thepausethatrefreshes
will be 0.001
. It's an easy
way to dial up or down the number of messages per second sent.
The sim.sleep()
function (we're using Lua to script our test scenarios) is really a
wrapper around the C function nanosleep()
, which, in theory,
allows a very fine resolution (to the nanosecond) but in reality is limited
to the hardware on the system.
And in my testing, I've found that at best, I can get only about 100
messages per second. I wrote a program to test the limits of
nanosleep()
and found that on our particular testing platform,
the lowest I can go is 0.01 seconds (my Linux system, on the other hand, can
go as low as 0.002).
As a second test, I just blasted out messages as fast as possible and was able to get a sustained (that is, actually sent and acknowledged) 1,500 per second (or one every 0.0006 seconds). I have to rethink my approach here. I think what may work is to send groups of messages before pausing a bit.
So, if I wanted to send 1,000 messages per second, I would need to write something like:
function thousand_per_second() for pauses = 1,50 do for msgs = 1 , 20 do endpoint:send(msg) end sim.sleep(0.02) end end
This sends twenty messages per batch, then pauses 0.02 seconds between batches, to give us approximately 1,000 per second (actually, a bit less due to processing overhead).