:: Re: [DNG] "Common knowledge?"-quest…
Top Page
Delete this message
Reply to this message
Author: Rainer Weikusat
Date:  
To: dng
Subject: Re: [DNG] "Common knowledge?"-question
karl@??? writes:

> Katola2:
> ...
>> void another_print_start(char *name, char *what){
>>
>> char c[3] = " :";
>>
>> c[2] = name[0] & ~0x20;
>>
>> write(2, c+2, 1);
>> write(2, name+1, strlen(name) -1);
>> write(2, c, 2);
>> write(2, what, strlen(what));
>>
>> }
>
> Why not just use writev(2) and write it one system call ?


The idea behind writev is to avoid userspace block memory copies prior
to doing a system call which will end up copying all the memory contents
into kernel memory. In order to achieve this, a vector of struct iovec
structures each specifiyng the location and size of a single area is
used. A struct iovec is

struct iovec {
    void *iov_base;
        size_t iov_len;
};


On a 64-bit system, this means that an additional 16 bytes of data need
to be copied by the kernel for every area used by writev. For this to be
worthwhile, the average size of an area should be more than 33 bytes,
otherwise, writev will end up doing more copying than userspace code had
need to create a continuous area before doing the system call. And then,
there's also the userspace code needed to initialize the vector. For the
example above, this would be

iovs->iov_base = c + 2;
iovs->iov_len = 2;
iovs[1].iov_base = name + 1;
iovs[1].iov_len = strlen(name) - 1;
iovs[2].iov_base = c;
iovs[2].iov_len = 2;
iovs[3].iov_base = what;
iovs[3].iov_len = strlen(what);

compared to

name_len = strlen(name);
what_len = strlen(what);
total = name_len + what_len + 3;
p = buf = alloca(total);
memcpy(p, name, name_len);
p += name_len;
*p++ = ' ';
memcpy(p, what, what_len);
p += what_len;
*p++ = ':';
*p = ' ';

that's 3 lines of code less which is "not great". In addition to this,
both write and writev may end up writing less data than requested and
the code for restarting a partially completed writev is more complicated
than the same for write.