[ENet-discuss] Packet throttling: it's the little things...
Lee Salzman
lsalzman at gmail.com
Sun Dec 19 16:49:37 PST 2010
ENet has had a packet throttling mechanism since the beginning that
allowed the amount of unreliable packets sent over the link to scale up
or down depending on a % representing the current quality of the
connection. Only % of the queued unreliable packets would get sent
through, the rest it would actually discard. Since the packets are
unreliable, it is perfectly legal to drop them, and advantageous to do
so when it helps reduce network congestion. This % floated up or down
depending on whether reliable packets or periodic pings (which are just
null reliable packets) took above or below average amount of time to get
acknowledged. Keep that in mind.
But I could never figure out a similar simple scheme for reliable
packets. I always thought I needed good bandwidth capacity estimates of
the connection so that I could know how much reliable data to send on
any given call to enet_host_service. Then some silly scheme about
measuring the average time between enet_host_service calls so I would
know how much more data budget to allocate to reliable data to send
again, since I reasoned you need to know the rate at which data was
getting sent to fit in within the estimated budget. And that brought up
questions like, over what timescales do you measure the rate and the
budget, and how do you fit that into the programmer interface of ENet
which is based on a polling enet_host_service call? And then the
mechanism wouldn't cooperate with the unreliable packet throttling very
well since it is a different metric, unless I changed the metric for
unreliable packets too which would require a crapload of empirical
testing to tune right again... I was not looking forward to any such
thing, so for years the throttle has remained as it is, rather than me
risk that.
Now, there is a reliable data window size in ENet that affords some
static flow control. The window size is constant so does not float up or
down in response to connection quality at all. There were some
provisions in the code to assign a fixed window size based on the user
provided bandwidth numbers, which I don't think anyone (even me)
seriously uses at this point. But this also creates nasty antagonism if
you send a lot of reliable data that overwhelms the link: suddenly ENet
sees your ping times skyrocketing, so the throttle slows unreliable
traffic down to almost nothing but keeps flooding the connection with
reliable data, so just kinda sucks. But that games I was using it for
were based on unreliable traffic with only limited reliable traffic, so
it never really mattered except occasionally. Also keep that in mind.
Then I was just for one reason or another reading an article on some TCP
mechanism, and there was a sentence in it that struck me like a brick in
the head: the window size in TCP floated up or down in response to
congestion. See where this is going? Ouch, the answer was staring me
right in the face the whole time:
throttle % * window size = throttled window size
The feedback would be more or less perfect: if the throttled window size
was still too large to prevent congestion, ping times would end up
increasing, and throttle % will just keep going down until the effective
window size is low enough to stabilize the connection again. If ping
times improve, the throttle opens up again. And the throttle % should
already be well tuned with no need to mess with it. The window was the
only mechanism I ever needed to handle flow control, I just needed to
link it to the throttle.
Problem solved in one damned line of code. Oh, how blind I was. :( -> :)
Thoughts?
Lee
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cubik.org/pipermail/enet-discuss/attachments/20101220/9acafe99/attachment.html>
More information about the ENet-discuss
mailing list