On 9/24/21 11:12, Mark Gray wrote:
> On 23/09/2021 01:13, Ilya Maximets wrote:
>> ovsdb-server spends a lot of time cloning atoms for various reasons,
>> e.g. to create a diff of two rows or to clone a row to the transaction.
>> All atoms, except for strings, contains a simple value that could be
>> copied in efficient way, but duplicating strings every time has a
>> significant performance impact.
>>
>> Introducing a new reference-counted structure 'ovsdb_atom_string'
>> that allows to not copy strings every time, but just increase a
>> reference counter.
>>
>> Changes in ovsdb/ovsdb-idlc.in are a bit brute-force-like, but I
>> didn't manage to write anything better.  And this part is very hard
>> to understand and debug, so maybe it's better to keep it in this
>> more or less understandable shape.
>>
>> This change allows to increase transaction throughput in benchmarks
>> up to 2x for standalone databases and 3x for clustered databases, i.e.
>> number of transactions that ovsdb-server can handle per second.
>> It also noticeably reduces memory consumption of ovsdb-server.
>>
> 
> Great!
> 
>> Next step will be to consolidate this structure with json strings,
>> so we will not need to duplicate strings while converting database
>> objects to json and back.
>>
>> Signed-off-by: Ilya Maximets <i.maxim...@ovn.org>
>> ---
>>
>> There is a small conflict in lib/db-ctl-base.c with the 'set
>> optimizations' patch-set, but it can be easily resolved if
>> someone wants to try these patches together>
>>  lib/db-ctl-base.c      |  11 +--
>>  lib/ovsdb-cs.c         |   2 +-
>>  lib/ovsdb-data.c       |  45 ++++++-----
>>  lib/ovsdb-data.h       |  29 ++++++-
>>  lib/ovsdb-idl.c        |   3 +-
>>  ovsdb/ovsdb-idlc.in    | 179 ++++++++++++++++++++++++++++-------------
>>  ovsdb/ovsdb-server.c   |   6 +-
>>  ovsdb/ovsdb-util.c     |  16 ++--
>>  ovsdb/rbac.c           |   8 +-
>>  python/ovs/db/data.py  |  43 +++++++---
>>  python/ovs/db/types.py |   7 +-
>>  tests/test-ovsdb.c     |  14 ++--
>>  12 files changed, 244 insertions(+), 119 deletions(-)
>>
>> diff --git a/lib/db-ctl-base.c b/lib/db-ctl-base.c
>> index 77cc76a9f..713487797 100644
>> --- a/lib/db-ctl-base.c
>> +++ b/lib/db-ctl-base.c
>> @@ -247,15 +247,15 @@ record_id_equals(const union ovsdb_atom *name, enum 
>> ovsdb_atomic_type type,
>>                   const char *record_id)
>>  {
>>      if (type == OVSDB_TYPE_STRING) {
>> -        if (!strcmp(name->string, record_id)) {
>> +        if (!strcmp(name->s->string, record_id)) {
>>              return true;
>>          }
>>  
>>          struct uuid uuid;
>>          size_t len = strlen(record_id);
>>          if (len >= 4
>> -            && uuid_from_string(&uuid, name->string)
>> -            && !strncmp(name->string, record_id, len)) {
>> +            && uuid_from_string(&uuid, name->s->string)
>> +            && !strncmp(name->s->string, record_id, len)) {
>>              return true;
>>          }
>>  
>> @@ -318,11 +318,12 @@ get_row_by_id(struct ctl_context *ctx,
>>          if (!id->key) {
>>              name = datum->n == 1 ? &datum->keys[0] : NULL;
>>          } else {
>> -            const union ovsdb_atom key_atom
>> -                = { .string = CONST_CAST(char *, id->key) };
>> +            union ovsdb_atom key_atom = {
>> +                .s = ovsdb_atom_string_create(CONST_CAST(char *, id->key)) 
>> };
>>              unsigned int i = ovsdb_datum_find_key(datum, &key_atom,
>>                                                    OVSDB_TYPE_STRING);
>>              name = i == UINT_MAX ? NULL : &datum->values[i];
>> +            ovsdb_atom_destroy(&key_atom, OVSDB_TYPE_STRING);
>>          }
>>          if (!name) {
>>              continue;
>> diff --git a/lib/ovsdb-cs.c b/lib/ovsdb-cs.c
>> index 659d49dbf..fcb6fe1b3 100644
>> --- a/lib/ovsdb-cs.c
>> +++ b/lib/ovsdb-cs.c
>> @@ -1833,7 +1833,7 @@ server_column_get_string(const struct server_row *row,
>>  {
>>      ovs_assert(server_columns[index].type.key.type == OVSDB_TYPE_STRING);
>>      const struct ovsdb_datum *d = &row->data[index];
>> -    return d->n == 1 ? d->keys[0].string : default_value;
>> +    return d->n == 1 ? d->keys[0].s->string : default_value;
>>  }
>>  
>>  static bool
>> diff --git a/lib/ovsdb-data.c b/lib/ovsdb-data.c
>> index 1f491a98b..0ed8f01b6 100644
>> --- a/lib/ovsdb-data.c
>> +++ b/lib/ovsdb-data.c
>> @@ -74,7 +74,7 @@ ovsdb_atom_init_default(union ovsdb_atom *atom, enum 
>> ovsdb_atomic_type type)
>>          break;
>>  
>>      case OVSDB_TYPE_STRING:
>> -        atom->string = xmemdup("", 1);
>> +        atom->s = ovsdb_atom_string_create_nocopy(xmemdup("", 1));
>>          break;
>>  
>>      case OVSDB_TYPE_UUID:
>> @@ -136,7 +136,7 @@ ovsdb_atom_is_default(const union ovsdb_atom *atom,
>>          return atom->boolean == false;
>>  
>>      case OVSDB_TYPE_STRING:
>> -        return atom->string[0] == '\0';
>> +        return atom->s->string[0] == '\0';
> 
> perhaps a helper function would allow you to hide some of this from a
> client. e.g.
> 
> char *ovsdb_atom_string_get(struct ovsdb_atom)

I thought about this, but we have only a handful of places where it is
used.  Another thing is that I want to replace it with json object later
that will have a json_string() access method.  So, it should be fine for
now to not introduce a method that will be replaced anyway.

Also, it seems like it should not be used at all directly, but should be
accessed only through datum/atom APIs, even though it is used in a few
places directly in current code.  So, I don't feel like making it easy
to use.

What do you think?

Best regards, Ilya Maximets.
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to