On 24/09/2021 12:01, Ilya Maximets wrote:
> 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?

Considering your future plan about the json object. This sounds good.
> 
> Best regards, Ilya Maximets.
> 

Acked-by: Mark D. Gray <mark.d.g...@redhat.com>

_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to