Skip to content

Commit

Permalink
ovsdb-idlc: Make no-op writes to write-only columns cheaper.
Browse files Browse the repository at this point in the history
For 1000 tunnels with CFM enabled, this reduces CPU use from
about 36% to about 30%.

Bug #15171.
Signed-off-by: Ben Pfaff <[email protected]>
Acked-by: Ethan Jackson <[email protected]>
  • Loading branch information
blp committed Mar 6, 2013
1 parent c9e5dfb commit fe19569
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 22 deletions.
46 changes: 35 additions & 11 deletions lib/ovsdb-idl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1826,19 +1826,18 @@ ovsdb_idl_txn_complete(struct ovsdb_idl_txn *txn,
* Takes ownership of what 'datum' points to (and in some cases destroys that
* data before returning) but makes a copy of 'datum' itself. (Commonly
* 'datum' is on the caller's stack.) */
void
ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
const struct ovsdb_idl_column *column,
struct ovsdb_datum *datum)
static void
ovsdb_idl_txn_write__(const struct ovsdb_idl_row *row_,
const struct ovsdb_idl_column *column,
struct ovsdb_datum *datum, bool owns_datum)
{
struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
const struct ovsdb_idl_table_class *class;
size_t column_idx;
bool write_only;

if (ovsdb_idl_row_is_synthetic(row)) {
ovsdb_datum_destroy(datum, &column->type);
return;
goto discard_datum;
}

class = row->table->class;
Expand All @@ -1853,8 +1852,7 @@ ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
if (row->table->idl->verify_write_only && !write_only) {
VLOG_ERR("Bug: Attempt to write to a read/write column (%s:%s) when"
" explicitly configured not to.", class->name, column->name);
ovsdb_datum_destroy(datum, &column->type);
return;
goto discard_datum;
}

/* If this is a write-only column and the datum being written is the same
Expand All @@ -1870,8 +1868,7 @@ ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
* ovsdb_idl_txn_commit().) */
if (write_only && ovsdb_datum_equals(ovsdb_idl_read(row, column),
datum, &column->type)) {
ovsdb_datum_destroy(datum, &column->type);
return;
goto discard_datum;
}

if (hmap_node_is_null(&row->txn_node)) {
Expand All @@ -1889,9 +1886,36 @@ ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
} else {
bitmap_set1(row->written, column_idx);
}
row->new[column_idx] = *datum;
if (owns_datum) {
row->new[column_idx] = *datum;
} else {
ovsdb_datum_clone(&row->new[column_idx], datum, &column->type);
}
(column->unparse)(row);
(column->parse)(row, &row->new[column_idx]);
return;

discard_datum:
if (owns_datum) {
ovsdb_datum_destroy(datum, &column->type);
}
}

void
ovsdb_idl_txn_write(const struct ovsdb_idl_row *row,
const struct ovsdb_idl_column *column,
struct ovsdb_datum *datum)
{
ovsdb_idl_txn_write__(row, column, datum, true);
}

void
ovsdb_idl_txn_write_clone(const struct ovsdb_idl_row *row,
const struct ovsdb_idl_column *column,
const struct ovsdb_datum *datum)
{
ovsdb_idl_txn_write__(row, column,
CONST_CAST(struct ovsdb_datum *, datum), false);
}

/* Causes the original contents of 'column' in 'row_' to be verified as a
Expand Down
5 changes: 4 additions & 1 deletion lib/ovsdb-idl.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -202,6 +202,9 @@ const struct uuid *ovsdb_idl_txn_get_insert_uuid(const struct ovsdb_idl_txn *,
void ovsdb_idl_txn_write(const struct ovsdb_idl_row *,
const struct ovsdb_idl_column *,
struct ovsdb_datum *);
void ovsdb_idl_txn_write_clone(const struct ovsdb_idl_row *,
const struct ovsdb_idl_column *,
const struct ovsdb_datum *);
void ovsdb_idl_txn_delete(const struct ovsdb_idl_row *);
const struct ovsdb_idl_row *ovsdb_idl_txn_insert(
struct ovsdb_idl_txn *, const struct ovsdb_idl_table_class *,
Expand Down
40 changes: 31 additions & 9 deletions ovsdb/ovsdb-idlc.in
Original file line number Diff line number Diff line change
Expand Up @@ -517,34 +517,54 @@ void
print "{"
print " struct ovsdb_datum datum;"
if type.n_min == 1 and type.n_max == 1:
print " union ovsdb_atom key;"
if type.value:
print " union ovsdb_atom value;"
print
print " ovs_assert(inited);"
print " datum.n = 1;"
print " datum.keys = xmalloc(sizeof *datum.keys);"
print " " + type.key.copyCValue("datum.keys[0].%s" % type.key.type.to_string(), keyVar)
print " datum.keys = &key;"
print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)
if type.value:
print " datum.values = xmalloc(sizeof *datum.values);"
print " "+ type.value.copyCValue("datum.values[0].%s" % type.value.type.to_string(), valueVar)
print " datum.values = &value;"
print " "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar)
else:
print " datum.values = NULL;"
txn_write_func = "ovsdb_idl_txn_write_clone"
elif type.is_optional_pointer():
print " union ovsdb_atom key;"
print
print " ovs_assert(inited);"
print " if (%s) {" % keyVar
print " datum.n = 1;"
print " datum.keys = xmalloc(sizeof *datum.keys);"
print " " + type.key.copyCValue("datum.keys[0].%s" % type.key.type.to_string(), keyVar)
print " datum.keys = &key;"
print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)
print " } else {"
print " datum.n = 0;"
print " datum.keys = NULL;"
print " }"
print " datum.values = NULL;"
txn_write_func = "ovsdb_idl_txn_write_clone"
elif type.n_max == 1:
print " union ovsdb_atom key;"
print
print " ovs_assert(inited);"
print " if (%s) {" % nVar
print " datum.n = 1;"
print " datum.keys = &key;"
print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), "*" + keyVar)
print " } else {"
print " datum.n = 0;"
print " datum.keys = NULL;"
print " }"
print " datum.values = NULL;"
txn_write_func = "ovsdb_idl_txn_write_clone"
else:
print " size_t i;"
print
print " ovs_assert(inited);"
print " datum.n = %s;" % nVar
print " datum.keys = xmalloc(%s * sizeof *datum.keys);" % nVar
print " datum.keys = %s ? xmalloc(%s * sizeof *datum.keys) : NULL;" % (nVar, nVar)
if type.value:
print " datum.values = xmalloc(%s * sizeof *datum.values);" % nVar
else:
Expand All @@ -560,8 +580,10 @@ void
valueType = "OVSDB_TYPE_VOID"
print " ovsdb_datum_sort_unique(&datum, %s, %s);" % (
type.key.toAtomicType(), valueType)
print " ovsdb_idl_txn_write(&row->header_, &%(s)s_columns[%(S)s_COL_%(C)s], &datum);" \
% {'s': structName,
txn_write_func = "ovsdb_idl_txn_write"
print " %(f)s(&row->header_, &%(s)s_columns[%(S)s_COL_%(C)s], &datum);" \
% {'f': txn_write_func,
's': structName,
'S': structName.upper(),
'C': columnName.upper()}
print "}"
Expand Down
11 changes: 10 additions & 1 deletion python/ovs/db/types.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
# Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -353,6 +353,15 @@ def copyCValue(self, dst, src):
else:
return "%(dst)s = %(src)s;" % args

def assign_c_value_casting_away_const(self, dst, src):
args = {'dst': dst, 'src': src}
if self.ref_table_name:
return ("%(dst)s = %(src)s->header_.uuid;") % args
elif self.type == StringType:
return "%(dst)s = CONST_CAST(char *, %(src)s);" % args
else:
return "%(dst)s = %(src)s;" % args

def initCDefault(self, var, is_optional):
if self.ref_table_name:
return "%s = NULL;" % var
Expand Down

0 comments on commit fe19569

Please sign in to comment.