DPDK patches and discussions
 help / color / mirror / Atom feed
From: Stephen Hemminger <stephen@networkplumber.org>
To: "Mattias Rönnblom" <mattias.ronnblom@ericsson.com>
Cc: dev@dpdk.org
Subject: Re: [dpdk-dev] [RFC 4/4] net/ether: use bitops to speedup comparison
Date: Thu, 16 May 2019 08:32:12 -0700	[thread overview]
Message-ID: <20190516083212.4aaff4c9@hermes.lan> (raw)
In-Reply-To: <95e9a56f-5d33-2a53-033d-d8963193cbea@ericsson.com>

On Thu, 16 May 2019 11:03:10 +0200
Mattias Rönnblom <mattias.ronnblom@ericsson.com> wrote:

> On 2019-05-16 00:19, Stephen Hemminger wrote:
> > Using bit operations like or and xor is faster than a loop
> > on all architectures. Really just explicit unrolling.
> > 
> > Similar cast to uint16 unaligned is already done in
> > other functions here.
> > 
> > Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> > ---
> >   lib/librte_net/rte_ether.h | 17 +++++++----------
> >   1 file changed, 7 insertions(+), 10 deletions(-)
> > 
> > diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
> > index b94e64b2195e..5d9242cda230 100644
> > --- a/lib/librte_net/rte_ether.h
> > +++ b/lib/librte_net/rte_ether.h
> > @@ -78,11 +78,10 @@ struct ether_addr {
> >   static inline int is_same_ether_addr(const struct ether_addr *ea1,
> >   				     const struct ether_addr *ea2)
> >   {
> > -	int i;
> > -	for (i = 0; i < ETHER_ADDR_LEN; i++)
> > -		if (ea1->addr_bytes[i] != ea2->addr_bytes[i])
> > -			return 0;
> > -	return 1;
> > +	const unaligned_uint16_t *w1 = (const uint16_t *)ea1;
> > +	const unaligned_uint16_t *w2 = (const uint16_t *)ea2;
> > +
> > +	return ((w1[0] ^ w2[0]) | (w1[1] ^ w2[1]) | (w1[2] ^ w2[2])) == 0;
> >   }
> >     
> 
> If you want to shave off a couple of instructions, you can switch the 
> three 16-bit loads to one 32-bit and one 16-bit load.
> 
> Something like:
> 
> 	const uint8_t *ea1_b = (const uint8_t *)ea1;
> 	const uint8_t *ea2_b = (const uint8_t *)ea2;
> 	uint32_t ea1_h;
> 	uint32_t ea2_h;
> 	uint16_t ea1_l;
> 	uint16_t ea2_l;
> 
> 	memcpy(&ea1_h, &ea1_b[0], sizeof(ea1_h));
> 	memcpy(&ea1_l, &ea1_b[sizeof(ea1_h)], sizeof(ea1_l));
> 
> 	memcpy(&ea2_h, &ea2_b[0], sizeof(ea2_h));
> 	memcpy(&ea2_l, &ea2_b[sizeof(ea2_h)], sizeof(ea2_l));
> 
> 	return ((ea1_l ^ ea2_l) | (ea1_h ^ ea2_h)) == 0;
> 
> Code is not as clean as your solution though.
> 
> >   /**
> > @@ -97,11 +96,9 @@ static inline int is_same_ether_addr(const struct ether_addr *ea1,
> >    */
> >   static inline int is_zero_ether_addr(const struct ether_addr *ea)
> >   {
> > -	int i;
> > -	for (i = 0; i < ETHER_ADDR_LEN; i++)
> > -		if (ea->addr_bytes[i] != 0x00)
> > -			return 0;
> > -	return 1;
> > +	const unaligned_uint16_t *w = (const uint16_t *)ea;
> > +
> > +	return (w[0] | w[1] | w[2]) == 0;
> >   }
> >   
> >   /**
> >   

You can even do 64 bit load and then mask, which is what Linux kernel
does. But not sure it matters. The cost of the loop is what is expensive

  parent reply	other threads:[~2019-05-16 15:58 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-15 22:19 [dpdk-dev] [RFC 0/4] net/ether: improvements Stephen Hemminger
2019-05-15 22:19 ` Stephen Hemminger
2019-05-15 22:19 ` [dpdk-dev] [RFC 1/4] net/ether: deinline non-critical functions Stephen Hemminger
2019-05-15 22:19   ` Stephen Hemminger
2019-05-16  7:10   ` David Marchand
2019-05-16  7:10     ` David Marchand
2019-05-15 22:19 ` [dpdk-dev] [RFC 2/4] net/ether: add eth_unformat_addr Stephen Hemminger
2019-05-15 22:19   ` Stephen Hemminger
2019-05-16  7:28   ` David Marchand
2019-05-16  7:28     ` David Marchand
2019-05-15 22:19 ` [dpdk-dev] [RFC 3/4] ethdev: use eth_unformat_addr Stephen Hemminger
2019-05-15 22:19   ` Stephen Hemminger
2019-05-16  7:32   ` David Marchand
2019-05-16  7:32     ` David Marchand
2019-05-16 10:19   ` Bruce Richardson
2019-05-16 10:19     ` Bruce Richardson
2019-05-15 22:19 ` [dpdk-dev] [RFC 4/4] net/ether: use bitops to speedup comparison Stephen Hemminger
2019-05-15 22:19   ` Stephen Hemminger
2019-05-16  9:03   ` Mattias Rönnblom
2019-05-16  9:03     ` Mattias Rönnblom
2019-05-16 15:32     ` Stephen Hemminger [this message]
2019-05-16 16:03   ` Bruce Richardson
2019-05-16 16:06     ` Stephen Hemminger
2019-05-16 16:07       ` Bruce Richardson
2019-05-16 16:36         ` Bruce Richardson
2019-05-16 17:04           ` Stephen Hemminger
2019-05-16 20:37             ` Bruce Richardson
2019-05-16 20:41               ` Bruce Richardson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190516083212.4aaff4c9@hermes.lan \
    --to=stephen@networkplumber.org \
    --cc=dev@dpdk.org \
    --cc=mattias.ronnblom@ericsson.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).