On 9/2/22 15:26, Dumitru Ceara wrote:
> On 8/24/22 19:26, Ilya Maximets wrote:
>> Filling arrays of switches and routers for load balancers
>> one-by-one is not very efficient.  Copying them in bulk
>> allows to save a noticeable amount of time in setups with
>> large load balancer groups.
>>
>> Signed-off-by: Ilya Maximets <[email protected]>
>> ---
> 
> The patch makes complete sense.  I would change a few minor things, I
> think.  Please see below.
> 
>>  lib/lb.c        | 16 ++++++++++------
>>  lib/lb.h        |  8 ++++----
>>  northd/northd.c | 41 +++++++++++++++++++++++++++++------------
>>  3 files changed, 43 insertions(+), 22 deletions(-)
>>
>> diff --git a/lib/lb.c b/lib/lb.c
>> index 7b0ed1abe..fe6070a40 100644
>> --- a/lib/lb.c
>> +++ b/lib/lb.c
>> @@ -239,23 +239,27 @@ ovn_northd_lb_find(struct hmap *lbs, const struct uuid 
>> *uuid)
>>  }
>>  
>>  void
>> -ovn_northd_lb_add_lr(struct ovn_northd_lb *lb, struct ovn_datapath *od)
>> +ovn_northd_lb_add_lr(struct ovn_northd_lb *lb, size_t n,
>> +                     struct ovn_datapath **ods)
>>  {
>> -    if (lb->n_allocated_nb_lr == lb->n_nb_lr) {
>> +    while (lb->n_allocated_nb_lr <= lb->n_nb_lr + n) {
>>          lb->nb_lr = x2nrealloc(lb->nb_lr, &lb->n_allocated_nb_lr,
>>                                 sizeof *lb->nb_lr);
>>      }
> 
> Neat!
> 
>> -    lb->nb_lr[lb->n_nb_lr++] = od;
>> +    memcpy(&lb->nb_lr[lb->n_nb_lr], ods, n * sizeof *ods);
>> +    lb->n_nb_lr += n;
>>  }
>>  
>>  void
>> -ovn_northd_lb_add_ls(struct ovn_northd_lb *lb, struct ovn_datapath *od)
>> +ovn_northd_lb_add_ls(struct ovn_northd_lb *lb, size_t n,
>> +                     struct ovn_datapath **ods)
>>  {
>> -    if (lb->n_allocated_nb_ls == lb->n_nb_ls) {
>> +    while (lb->n_allocated_nb_ls <= lb->n_nb_ls + n) {
>>          lb->nb_ls = x2nrealloc(lb->nb_ls, &lb->n_allocated_nb_ls,
>>                                 sizeof *lb->nb_ls);
>>      }
>> -    lb->nb_ls[lb->n_nb_ls++] = od;
>> +    memcpy(&lb->nb_ls[lb->n_nb_ls], ods, n * sizeof *ods);
>> +    lb->n_nb_ls += n;
>>  }
>>  
>>  void
>> diff --git a/lib/lb.h b/lib/lb.h
>> index 832ed31fb..d7bc28e18 100644
>> --- a/lib/lb.h
>> +++ b/lib/lb.h
>> @@ -88,10 +88,10 @@ struct ovn_northd_lb_backend {
>>  struct ovn_northd_lb *ovn_northd_lb_create(const struct nbrec_load_balancer 
>> *);
>>  struct ovn_northd_lb * ovn_northd_lb_find(struct hmap *, const struct uuid 
>> *);
>>  void ovn_northd_lb_destroy(struct ovn_northd_lb *);
>> -void
>> -ovn_northd_lb_add_lr(struct ovn_northd_lb *lb, struct ovn_datapath *od);
>> -void
>> -ovn_northd_lb_add_ls(struct ovn_northd_lb *lb, struct ovn_datapath *od);
>> +void ovn_northd_lb_add_lr(struct ovn_northd_lb *lb, size_t n,
>> +                          struct ovn_datapath **ods);
>> +void ovn_northd_lb_add_ls(struct ovn_northd_lb *lb, size_t n,
>> +                          struct ovn_datapath **ods);
>>  
>>  struct ovn_controller_lb {
>>      const struct sbrec_load_balancer *slb; /* May be NULL. */
>> diff --git a/northd/northd.c b/northd/northd.c
>> index b66843581..c202d27d5 100644
>> --- a/northd/northd.c
>> +++ b/northd/northd.c
>> @@ -3845,7 +3845,9 @@ struct ovn_lb_group {
>>      struct hmap_node hmap_node;
>>      struct uuid uuid;
>>      size_t n;
>> -    struct ovn_northd_lb *lbs[];
>> +    struct ovn_northd_lb **lbs;
>> +    size_t n_od;
>> +    struct ovn_datapath **ods;
>>  };
>>  
>>  static struct ovn_lb_group *
>> @@ -3883,12 +3885,11 @@ build_lbs(struct northd_input *input_data, struct 
>> hmap *datapaths,
>>  
>>      NBREC_LOAD_BALANCER_GROUP_TABLE_FOR_EACH (nbrec_lb_group,
>>                                 input_data->nbrec_load_balancer_group_table) 
>> {
>> -        size_t size = sizeof *lb_group +
>> -            nbrec_lb_group->n_load_balancer * sizeof(struct ovn_northd_lb 
>> *);
>> -
>> -        lb_group = xzalloc(size);
>> +        lb_group = xzalloc(sizeof *lb_group);
>>          lb_group->uuid = nbrec_lb_group->header_.uuid;
>>          lb_group->n = nbrec_lb_group->n_load_balancer;
>> +        lb_group->lbs = xzalloc(lb_group->n * sizeof *lb_group->lbs);
>> +        lb_group->ods = xzalloc(hmap_count(datapaths) * sizeof 
>> *lb_group->ods);
> 
> In an unfortunate case when LB groups are used for a subset of datapaths
> and the number of datapaths that don't use LB groups is significant then
> this is inefficient.  I'd go for x2nrealloc() below, when populating
> 'lb_group->ods'.

Maybe.  OTOH, the number of LB groups is, likely, not that big, and the
number of datapaths is also not that huge.  2n realloc will actually end
up allocating more memory in a general case, I think.  But I can change
this part if you think otherwise.  I just didn't want to introduce yet
another variable to track the array size.  And it will be 2 extra variables
if we'll allocate separate arrays for switches and routers.

> 
>>  
>>          for (size_t i = 0; i < nbrec_lb_group->n_load_balancer; i++) {
>>              const struct uuid *lb_uuid =
>> @@ -3910,19 +3911,25 @@ build_lbs(struct northd_input *input_data, struct 
>> hmap *datapaths,
>>              const struct uuid *lb_uuid =
>>                  &od->nbs->load_balancer[i]->header_.uuid;
>>              lb = ovn_northd_lb_find(lbs, lb_uuid);
>> -            ovn_northd_lb_add_ls(lb, od);
>> +            ovn_northd_lb_add_ls(lb, 1, &od);
>>          }
>>  
>>          for (size_t i = 0; i < od->nbs->n_load_balancer_group; i++) {
>>              nbrec_lb_group = od->nbs->load_balancer_group[i];
>>              lb_group = ovn_lb_group_find(lb_groups,
>>                                           &nbrec_lb_group->header_.uuid);
>> -            for (size_t j = 0; j < lb_group->n; j++) {
>> -                ovn_northd_lb_add_ls(lb_group->lbs[j], od);
>> -            }
>> +            lb_group->ods[lb_group->n_od++] = od;
>>          }
>>      }
>>  
>> +    HMAP_FOR_EACH (lb_group, hmap_node, lb_groups) {
>> +        for (size_t j = 0; j < lb_group->n; j++) {
>> +            ovn_northd_lb_add_ls(lb_group->lbs[j], lb_group->n_od,
>> +                                 lb_group->ods);
>> +        }
>> +        lb_group->n_od = 0;
>> +    }
>> +
>>      HMAP_FOR_EACH (od, key_node, datapaths) {
>>          if (!od->nbr) {
>>              continue;
>> @@ -3932,7 +3939,7 @@ build_lbs(struct northd_input *input_data, struct hmap 
>> *datapaths,
>>              const struct uuid *lb_uuid =
>>                  &od->nbr->load_balancer[i]->header_.uuid;
>>              lb = ovn_northd_lb_find(lbs, lb_uuid);
>> -            ovn_northd_lb_add_lr(lb, od);
>> +            ovn_northd_lb_add_lr(lb, 1, &od);
>>              build_lrouter_lb_ips(od, lb);
>>          }
>>  
>> @@ -3940,12 +3947,20 @@ build_lbs(struct northd_input *input_data, struct 
>> hmap *datapaths,
>>              nbrec_lb_group = od->nbr->load_balancer_group[i];
>>              lb_group = ovn_lb_group_find(lb_groups,
>>                                           &nbrec_lb_group->header_.uuid);
>> +            lb_group->ods[lb_group->n_od++] = od;
>>              for (size_t j = 0; j < lb_group->n; j++) {
>> -                ovn_northd_lb_add_lr(lb_group->lbs[j], od);
>>                  build_lrouter_lb_ips(od, lb_group->lbs[j]);
>>              }
>>          }
>>      }
>> +
>> +    HMAP_FOR_EACH (lb_group, hmap_node, lb_groups) {
>> +        for (size_t j = 0; j < lb_group->n; j++) {
>> +            ovn_northd_lb_add_lr(lb_group->lbs[j], lb_group->n_od,
>> +                                 lb_group->ods);
>> +        }
>> +        lb_group->n_od = 0;
> 
> This is a bit confusing.  That's because we reuse the 'lb_group->ods'
> array; we use it first for switches and then for routers.  I think I'd
> just add two array (like we do for 'struct ovn_northd_lb').  It's more
> verbose but there's no ambiguity then.

LB group will be destroyed and re-created, so we can avoid re-setting
the value here.  I was trying to avoid having too many variables.
And since both are datapaths, we can re-use the same array and not
re-allocate it twice.  Either way is fine for me, but having one array
is slightly more efficient.  What do you think?

> 
>> +    }
>>  }
>>  
>>  static void
>> @@ -4130,7 +4145,7 @@ build_lswitch_lbs_from_lrouter(struct hmap *datapaths, 
>> struct hmap *lbs)
>>                     }
>>                  }
>>                  if (!installed) {
>> -                    ovn_northd_lb_add_ls(lb, od);
>> +                    ovn_northd_lb_add_ls(lb, 1, &od);
>>                  }
>>                  if (lb->nlb) {
>>                      od->has_lb_vip |= lb_has_vip(lb->nlb);
>> @@ -15403,6 +15418,8 @@ northd_destroy(struct northd_data *data)
>>  
>>      struct ovn_lb_group *lb_group;
>>      HMAP_FOR_EACH_POP (lb_group, hmap_node, &data->lb_groups) {
>> +        free(lb_group->lbs);
>> +        free(lb_group->ods);
>>          free(lb_group);
>>      }
>>      hmap_destroy(&data->lb_groups);
> 

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to