Re: [PATCH] bind.2, mount_setattr.2, openat2.2, perf_event_open.2, pidfd_send_signal.2, recvmmsg.2, seccomp_unotify.2, select_tut.2, sendmmsg.2, set_thread_area.2, sysctl.2, bzero.3, getaddrinfo.3, getaddrinfo_a.3, getutent.3, mbrtowc.3, mbsinit.3, rti...

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Wilco,

On 1/6/23 03:26, Wilco Dijkstra wrote:
Hi Alex,

Many projects redefine those functions themselves, with alternative names, so
it's hard to really count how much is the intention of projects to use it,
rather than actual use.  Since the standards don't guarantee such functions,
projects that care a lot, use a portable name (one that isn't reserved;
sometimes they don't even know that there's a GNU extension with that name and
use a weird one, such as cpymem() by nginx).

Yeah portability is a big issue with these non-standard functions. So even if you
aren't considering the large cost of supporting these functions in C libraries, there
are also costs in making applications portable, precisely because not all C libraries
will support it...

The thing is that those APIs are better (imagine that they were all standard,
and were all equally known by programmers; which ones would you use?).  Some
programmers will want to use the better APIs, independently of libc providing it
or not.  In some cases, for high performance programs, good APIs are even more
relevant.  Not implementing them in libc, will only mean that projects will roll
their own.

No, the use of non-standard functions is the problem here. bzero was deprecated
more than 20 years ago, do you think C libraries will add support and optimize it
even if they never supported it before?

Which C libraries never supported bzero(3)? It was in POSIX once, so I guess it's supported everywhere in Unix(-like) systems (you can see that I don't care at all about other systems). Even if only for backwards compatibility, the removal from POSIX will have not affected the portability of bzero(3) in source code (even where libc has removed it, the compiler will provide support).

If it's non-standard, it's never going to
happen.

So, I don't think that's a real problem yet. We're not yet (or I believe so) in a point where bzero(3) is non-portable in source code.


If we continue with the mempcpy vs memcpy example of nginx, I presume
nginx implements cpymem() similar to this:

#if HAVE_MEMPCPY_SUPPORT
   return mempcpy (p, q, n);
#else
   return memcpy (p, q, n) + n;
#endif

The define would be set by a special configure check.

Even simpler: it is unconditionally defined to memcpy() + len in a macro.

The reason (I guess) is that they didn't even know that mempcpy() exists.


Now if nginx got say 10% faster from using mempcpy then that would
be great and it would be worth the trouble. However there is no difference
since compilers typically generate identical code for these cases.

Actually, gcc optimizes differently. When you call mempcpy(3), since it knows it exists, it calls it or replaces it by memcpy(3)+len, depending on optimization flags. When you call memcpy(3)+len, since it doesn't know if mempcpy(3) is available, it keeps the memcpy(3) call always.

So what's
the point of mempcpy exactly?

The point of mempcpy(3) is that it's the simplest libc API to catenate strings when you know the length of the source strings, and you also want to know the length of the resulting string, and you know there will be no truncation.

Example:

src/nxt_h1proto.c:2287:    p = nxt_cpymem(p, r->method->start, r->method->length);
src/nxt_h1proto.c-2288-    *p++ = ' ';
src/nxt_h1proto.c:2289:    p = nxt_cpymem(p, r->target.start, r->target.length);
src/nxt_h1proto.c:2290:    p = nxt_cpymem(p, " HTTP/1.1\r\n", 11);
src/nxt_h1proto.c:2291:    p = nxt_cpymem(p, "Connection: close\r\n", 19);


Any other function will either be slower (stpcpy(3) will likely be slower), or make the code more complex (memcpy(3) will require adding +... everywhere).

I'm not saying that this will be significantly faster than memcpy(3), but it will be at least as fast (and negligibly faster if libc optimized mempcpy(3), but that's negligible).


By all means, create your own special copy interface function - it's just sugar.
But deciding that mempcpy is great and then being forced to do extra work
to make it portable for no gain is what I find insane...

From a source code point of view, they let programmers write better/simpler source code than memcpy(3) or memset(3). That's sugar... yes. IMO, it's worth it.


Where do you suggest that we put such function?  In or out of libc?

Well you mentioned that nginx and many other programs already define their
own memcpy variants. It's perfectly reasonable to do what you proposed and
create a library of inline string functions using standard calls as primitives.
If it is a freely usable and portable, any project that likes it could just add it.

Having it in libc rather than an external library has the benefit that it will have support from the compiler (better warnings and optimizations).

But yes, for the time being, I'll keep developing such an external library.


Cheers,
Wilco

--
<http://www.alejandro-colomar.es/>

Attachment: OpenPGP_signature
Description: OpenPGP digital signature


[Index of Archives]     [Kernel Documentation]     [Netdev]     [Linux Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux