in qbread, why does qbread only take full blocks for coalescing queues?
(these are only used for the console, and for tcp) for example:
if(q->state & Qcoalesce){
/* when coalescing, 0 length blocks just go away */
b = q->bfirst;
if(BLEN(b) <= 0){
freeb(qremove(q));
goto again;
}
/* grab the first block plus as many
* following blocks as will completely
* fit in the read.
*/
n = 0;
l = &first;
m = BLEN(b);
for(;;) {
*l = qremove(q);
l = &b->next;
n += m;
b = q->bfirst;
if(b == nil)
break;
m = BLEN(b);
if(n+m > len)
break;
}
}
/* code to put extra bytes back on the queue below */
in the typical use with tcp, we're going to have a protocol like 9p or tls
running
on top of tcp, and if it does a read of n bytes, it really does need n bytes.
so
splitting reads rather than blocks would seem less efficient because
copying a partial block <= mss should be much faster than a syscall. (nsec()
with the fd open takes ~7-900ns, but a 1460-byte copy takes ~130ns @ a modest
10gb/s, much less if cache pressure doesn't dominate.)
i noticed this because even with the tcp rx queue full (slow receiver) i was
seeing
twice as many reads as i would have expected. the following code works fine.
if(q->state & Qcoalesce){
/* when coalescing, 0 length blocks just go away */
b = q->bfirst;
if(BLEN(b) <= 0){
freeb(qremove(q));
goto again;
}
/*
* grab the first block and as many following
* blocks as will partially fit in the read
*/
n = 0;
l = &first;
m = BLEN(b);
for(;;) {
*l = qremove(q);
l = &b->next;
n += BLEN(b);
if(n >= len || (b = q->bfirst) == nil)
break;
}
}
/* code to put extra bytes back on the queue below */
is there something or some consideration here that i'm missing?
- erik