Date: Tue, 9 Apr 2002 19:17:44 -0400
From: Richard A Steenbergen <ras@e-gerbil.net>
[ snip beginning ]
Actually here's an even simpler one. Define a global limit for
this, something like 32MB would be more then reasonable. Then
instead of advertising the space "remaining" in individual
My static buffer presumed that one would regularly see line rate;
that's probably an invalid assumption.
socket buffers, advertise the total space remaining in this
Why bother advertising space remaining? Simply take the total
space -- which is tuned to line rate -- and divide equitably.
Equal division is the primitive way. Monitoring actual buffer
use, a la PSC window-tuning code, is more efficient.
To respect memory, sure, you could impose a global limit and
alloc as needed. But on a "busy enough" server/client, how much
would that save? Perhaps one could allocate 8MB chunks at a
time... but fragmentation could prevent the ability to have a
contiguous 32MB in the future. (Yes, I'm assuming high memory
usage and simplistic paging. But I think that's plausible.)
Honestly... memory is so plentiful these days that I'd gladly
devote "line rate"-sized buffers to the cause on each and every
server that I run.
virtual memory pool. If you overrun your buffer, you might have
the other side send you a few unnecessary bytes that you just
have to drop, but the situation should correct itself very
By allocating 32MB, one stream could achieve line rate with no
wasted space (assuming latency is exactly what we predict, which
we all know won't happen). When another stream or two are
opened, we split the buffer into four. Maybe we drop, like you
suggest, in a RED-like manner. Maybe we flush the queue if it's
not "too full".
Now we have up to four streams, each with an 8MB queue. Need
more streams? Fine, split { one | some | all } of the 8MB
windows into 2MB segments. Simple enough, until we hit the
variable bw*delay times... then we should use intelligence when
splitting, probably via mechanisms similar to the PSC stack.
Granularity of 4 is for example only. I know that would be
non-ideal. One could split 32 MB into 6.0 MB + 7.0 MB + 8.5 MB +
10.5 MB, which would then be halved as needed. Long-running
sessions could be moved between buffer clumps as needed. (i.e.,
if 1.5 MB is too small and 2.0 MB is too large, 1.75 MB fits
nicely into the 7.0 MB area.)
quickly. I don't think this would be "unfair" to any particular
flow, since you've eliminated the concept of one flow
"hogging" the socket buffer and leave it to TCP to work out the
sharing of the link. Second opinions?
Smells to me like ALTQ's TBR (token buffer regulator).
Perhaps also have a dynamically-allocated "tuning" buffer:
Imagine 2000 dialups and 10 DSL connections transferring over a
DS3... use a single "big enough" buffer (few buffers?) to sniff
out each stream's capability, to determine which stream can use
how much more space.