On Wed, May 24, 2023 at 1:11 PM Ilya Maximets <i.maxim...@ovn.org> wrote:

> On 5/23/23 10:09, Ales Musil wrote:
> > The incremental processing is broken for addresses
> > that have mask which could "erase" portion of the address
> > itself e.g. 10.16.0.47/4, after applying the mask with token
> > parser the address becomes 0.0.0.0/4, which is fine for
> > logical flows. However, for the deletion/addition to database
> > we need the original string representation which cannot be
> > built from the parsed token.
> >
> > Use svec instead for the comparison which allows us to keep the
> > original strings.
> >
> > The change to svec shouldn't have any significant performance
> > impact, see the numbers below show. The setup was created by
> > the scale script from Han [0].
> >
> > Numbers with expr:
> > Time spent on processing nb_cfg 1:
> >         ovn-northd delay before processing:     21ms
> >         ovn-northd completion:                  544ms
> >         ovn-controller(s) completion:           544ms
> > Time spent on processing nb_cfg 2:
> >         ovn-northd delay before processing:     17ms
> >         ovn-northd completion:                  537ms
> >         ovn-controller(s) completion:           535ms
> > Time spent on processing nb_cfg 3:
> >         ovn-northd delay before processing:     20ms
> >         ovn-northd completion:                  552ms
> >         ovn-controller(s) completion:           550ms
> > Time spent on processing nb_cfg 4:
> >         ovn-northd delay before processing:     16ms
> >         ovn-northd completion:                  529ms
> >         ovn-controller(s) completion:           528ms
> >
> > Numbers with svec:
> > Time spent on processing nb_cfg 1:
> >         ovn-northd delay before processing:     19ms
> >         ovn-northd completion:                  548ms
> >         ovn-controller(s) completion:           548ms
> > Time spent on processing nb_cfg 2:
> >         ovn-northd delay before processing:     19ms
> >         ovn-northd completion:                  537ms
> >         ovn-controller(s) completion:           537ms
> > Time spent on processing nb_cfg 3:
> >         ovn-northd delay before processing:     15ms
> >         ovn-northd completion:                  522ms
> >         ovn-controller(s) completion:           521ms
> > Time spent on processing nb_cfg 4:
> >         ovn-northd delay before processing:     17ms
> >         ovn-northd completion:                  522ms
> >         ovn-controller(s) completion:           520ms
> >
> > [0]
> https://github.com/hzhou8/ovn-test-script/blob/e1149318201309db6d96ae8d5a33fcfbbe1872a3/test_ovn_controller_scale.sh
> >
> > Fixes: 0d5e0a6ced49 ("northd: Add I-P for syncing SB address sets.")
> > Reported-at: https://bugzilla.redhat.com/2196885
>
> The issue was originally reported on the mailing list.  Please,
> provide the link as well.  And it'd also be nice to credit the
> original reporter.
>

Added in v2.


>
> > Signed-off-by: Ales Musil <amu...@redhat.com>
> > ---
> >  northd/en-sync-sb.c | 66 +++++++++++++++++++++------------------------
> >  1 file changed, 30 insertions(+), 36 deletions(-)
> >
> > diff --git a/northd/en-sync-sb.c b/northd/en-sync-sb.c
> > index 758f00bfd..4bd77b168 100644
> > --- a/northd/en-sync-sb.c
> > +++ b/northd/en-sync-sb.c
> > @@ -22,7 +22,6 @@
> >  #include "openvswitch/util.h"
> >
> >  #include "en-sync-sb.h"
> > -#include "include/ovn/expr.h"
> >  #include "lib/inc-proc-eng.h"
> >  #include "lib/lb.h"
> >  #include "lib/ovn-nb-idl.h"
> > @@ -325,45 +324,40 @@ static void
> >  update_sb_addr_set(const char **nb_addresses, size_t n_addresses,
> >                     const struct sbrec_address_set *sb_as)
> >  {
> > -    struct expr_constant_set *cs_nb_as =
> > -        expr_constant_set_create_integers(
> > -            (const char *const *) nb_addresses, n_addresses);
> > -    struct expr_constant_set *cs_sb_as =
> > -        expr_constant_set_create_integers(
> > -            (const char *const *) sb_as->addresses, sb_as->n_addresses);
> > -
> > -    struct expr_constant_set *addr_added = NULL;
> > -    struct expr_constant_set *addr_deleted = NULL;
> > -    expr_constant_set_integers_diff(cs_sb_as, cs_nb_as, &addr_added,
> > -                                    &addr_deleted);
> > -
> > -    struct ds ds = DS_EMPTY_INITIALIZER;
> > -    if (addr_added && addr_added->n_values) {
> > -        for (size_t i = 0; i < addr_added->n_values; i++) {
> > -            ds_clear(&ds);
> > -            expr_constant_format(&addr_added->values[i],
> EXPR_C_INTEGER, &ds);
> > -            sbrec_address_set_update_addresses_addvalue(sb_as,
> ds_cstr(&ds));
> > -        }
> > +    size_t i;
> > +    char *ip;
> > +
> > +    struct svec svec_nb_as = SVEC_EMPTY_INITIALIZER;
> > +    struct svec svec_sb_as = SVEC_EMPTY_INITIALIZER;
> > +
> > +    for (i = 0; i < n_addresses; i++) {
> > +        svec_add(&svec_nb_as, nb_addresses[i]);
> >      }
> >
> > -    if (addr_deleted && addr_deleted->n_values) {
> > -        for (size_t i = 0; i < addr_deleted->n_values; i++) {
> > -            ds_clear(&ds);
> > -            expr_constant_format(&addr_deleted->values[i],
> > -                                 EXPR_C_INTEGER, &ds);
> > -            sbrec_address_set_update_addresses_delvalue(sb_as,
> ds_cstr(&ds));
> > -        }
> > +
> > +    for (i = 0; i < sb_as->n_addresses; i++) {
> > +        svec_add(&svec_sb_as, sb_as->addresses[i]);
> > +    }
> > +
> > +    struct svec addr_added;
> > +    struct svec addr_deleted;
> > +
> > +    svec_sort(&svec_nb_as);
> > +    svec_sort(&svec_sb_as);
>
> sb_as->addresses is a database column, it's already sorted.
>
> > +    svec_diff(&svec_nb_as, &svec_sb_as, &addr_added, NULL,
> &addr_deleted);
> > +
> > +    SVEC_FOR_EACH (i, ip, &addr_added) {
> > +        sbrec_address_set_update_addresses_addvalue(sb_as, ip);
> > +    }
> > +
> > +    SVEC_FOR_EACH (i, ip, &addr_deleted) {
> > +        sbrec_address_set_update_addresses_delvalue(sb_as, ip);
> >      }
>
> I'm not sure if the svec_diff() function saves any lines of code here.
> But it definitely makes us waste a lot of time.  The workflow here is:
>
> 1. Copy all the addresses from the nb set into svec.
> 2. Copy all the addresses from the sb set into svec.
> 3. Sort.
> 3.1  Sort nb svec.
> 3.2  Sort sb svec.
> 4. svec_diff()
> 4.1. Check that nb set is sorted by comparing each string to the next.
> 4.2  Check that sb set is sorted by comparing each string to the next.
> 4.3  Prepare the diff by comparing strings between nb and sb sets
>      and copy ones that differ.
> 5. Update the sb database entry.
> 6. Destroy svecs and free the copies.
>
> Sounds like way too much data copies and string comparisons to me.
>
> As I pointed out above, the Sb database column is already sorted.
> We can make it a requirement that nb_addresses is sorted before this
> function is called.  This way we will also avoid sorting nb addresses
> if they are also just taken directly from the database.  And we will
> not need to create an extra copy of all of them.
> Then we could open-code the diff function that will just update
> the Sb column whenever the difference is found (addvalue/delvalue
> API doesn't update the record, so we can still safely iterate over it).
>
> This way the workflow will degrade down to steps 3.1 (if needed)
> and 4.3 + 5 combined, but without a copy.
>
> What do you think?
>
> Best regards, Ilya Maximets.
>
>
Sounds like a good idea. I went the svec way because it performed the same
as the
previous implementation as I wasn't sure if the DB value is ordered, now
it's clear.
Also it seems that this suggestion is even faster than the previous one.
Updated in v2.

Thanks,
Ales
-- 

Ales Musil

Senior Software Engineer - OVN Core

Red Hat EMEA <https://www.redhat.com>

amu...@redhat.com    IM: amusil
<https://red.ht/sig>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to