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

Reply via email to