Replace bcopy() to update ether_addr

Marius Strobl marius at alchemy.franken.de
Tue Aug 21 10:26:35 UTC 2012


On Mon, Aug 20, 2012 at 05:46:12PM +0300, Mitya wrote:
> Hi.
> I found some overhead code in /src/sys/net/if_ethersubr.c and 
> /src/sys/netgraph/ng_ether.c
> 
> It contains strings, like bcopy(src, dst, ETHER_ADDR_LEN);
> When src and dst are "struct ether_addr*", and ETHER_ADDR_LEN equal 6.
> This code call every time, when we send Ethernet packet.
> On example, on my machine in invoked nearly 20K per second.
> 
> Why we are use bcopy(), to copy only 6 bytes?
> Answer - in some architectures we are can not directly copy unaligned data.
> 
> I propose this solution.
> 
> In file /usr/src/include/net/ethernet.h add this lines:
> 
> static inline void ether_addr_copy(ether_addr* src, ether_addr* dst) {
> #if defined(__i386__) || defined(__amd64__)
>     *dst = *src;
> #else
>     bcopy(src, dst, ETHER_ADDR_LEN);
> #endif
> }
> 
> On platform i386 gcc produce like this code:
>     leal    -30(%ebp), %eax
>     leal    6(%eax), %ecx
>     leal    -44(%ebp), %edx
>     movl    (%edx), %eax
>     movl    %eax, (%ecx)
>     movzwl  4(%edx), %eax
>     movw    %ax, 4(%ecx)
> And clang produce this:
>     movl    -48(%ebp), %ecx
>     movl    %ecx, -26(%ebp)
>     movw    -44(%ebp), %si
>     movw    %si, -22(%ebp)
> 
> 
> All this variants are much faster, than bcopy()
> 

A bit orthogonal to this but also related to the performance
impact of these bcopy() calls, for !__NO_STRICT_ALIGNMENT
architectures these places probably should use memcpy()
instead as bcopy() additionally has to check for overlap
while the former does not. Overlaps unlikely are an issue
in these cases and at least NetBSD apparently has done the
switch to memcpy() 5.5 years ago.

Marius



More information about the freebsd-hackers mailing list