mirror of
https://github.com/openvswitch/ovs
synced 2025-10-21 14:49:41 +00:00
ovsdb-idlc: Make no-op writes to write-only columns cheaper.
For 1000 tunnels with CFM enabled, this reduces CPU use from about 36% to about 30%. Bug #15171. Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Ethan Jackson <ethan@nicira.com>
This commit is contained in:
@@ -1826,10 +1826,10 @@ ovsdb_idl_txn_complete(struct ovsdb_idl_txn *txn,
|
|||||||
* Takes ownership of what 'datum' points to (and in some cases destroys that
|
* Takes ownership of what 'datum' points to (and in some cases destroys that
|
||||||
* data before returning) but makes a copy of 'datum' itself. (Commonly
|
* data before returning) but makes a copy of 'datum' itself. (Commonly
|
||||||
* 'datum' is on the caller's stack.) */
|
* 'datum' is on the caller's stack.) */
|
||||||
void
|
static void
|
||||||
ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
|
ovsdb_idl_txn_write__(const struct ovsdb_idl_row *row_,
|
||||||
const struct ovsdb_idl_column *column,
|
const struct ovsdb_idl_column *column,
|
||||||
struct ovsdb_datum *datum)
|
struct ovsdb_datum *datum, bool owns_datum)
|
||||||
{
|
{
|
||||||
struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
|
struct ovsdb_idl_row *row = CONST_CAST(struct ovsdb_idl_row *, row_);
|
||||||
const struct ovsdb_idl_table_class *class;
|
const struct ovsdb_idl_table_class *class;
|
||||||
@@ -1837,8 +1837,7 @@ ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
|
|||||||
bool write_only;
|
bool write_only;
|
||||||
|
|
||||||
if (ovsdb_idl_row_is_synthetic(row)) {
|
if (ovsdb_idl_row_is_synthetic(row)) {
|
||||||
ovsdb_datum_destroy(datum, &column->type);
|
goto discard_datum;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class = row->table->class;
|
class = row->table->class;
|
||||||
@@ -1853,8 +1852,7 @@ ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
|
|||||||
if (row->table->idl->verify_write_only && !write_only) {
|
if (row->table->idl->verify_write_only && !write_only) {
|
||||||
VLOG_ERR("Bug: Attempt to write to a read/write column (%s:%s) when"
|
VLOG_ERR("Bug: Attempt to write to a read/write column (%s:%s) when"
|
||||||
" explicitly configured not to.", class->name, column->name);
|
" explicitly configured not to.", class->name, column->name);
|
||||||
ovsdb_datum_destroy(datum, &column->type);
|
goto discard_datum;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is a write-only column and the datum being written is the same
|
/* If this is a write-only column and the datum being written is the same
|
||||||
@@ -1870,8 +1868,7 @@ ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
|
|||||||
* ovsdb_idl_txn_commit().) */
|
* ovsdb_idl_txn_commit().) */
|
||||||
if (write_only && ovsdb_datum_equals(ovsdb_idl_read(row, column),
|
if (write_only && ovsdb_datum_equals(ovsdb_idl_read(row, column),
|
||||||
datum, &column->type)) {
|
datum, &column->type)) {
|
||||||
ovsdb_datum_destroy(datum, &column->type);
|
goto discard_datum;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hmap_node_is_null(&row->txn_node)) {
|
if (hmap_node_is_null(&row->txn_node)) {
|
||||||
@@ -1889,9 +1886,36 @@ ovsdb_idl_txn_write(const struct ovsdb_idl_row *row_,
|
|||||||
} else {
|
} else {
|
||||||
bitmap_set1(row->written, column_idx);
|
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->unparse)(row);
|
||||||
(column->parse)(row, &row->new[column_idx]);
|
(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
|
/* Causes the original contents of 'column' in 'row_' to be verified as a
|
||||||
|
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -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 *,
|
void ovsdb_idl_txn_write(const struct ovsdb_idl_row *,
|
||||||
const struct ovsdb_idl_column *,
|
const struct ovsdb_idl_column *,
|
||||||
struct ovsdb_datum *);
|
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 *);
|
void ovsdb_idl_txn_delete(const struct ovsdb_idl_row *);
|
||||||
const struct ovsdb_idl_row *ovsdb_idl_txn_insert(
|
const struct ovsdb_idl_row *ovsdb_idl_txn_insert(
|
||||||
struct ovsdb_idl_txn *, const struct ovsdb_idl_table_class *,
|
struct ovsdb_idl_txn *, const struct ovsdb_idl_table_class *,
|
||||||
|
@@ -517,34 +517,54 @@ void
|
|||||||
print "{"
|
print "{"
|
||||||
print " struct ovsdb_datum datum;"
|
print " struct ovsdb_datum datum;"
|
||||||
if type.n_min == 1 and type.n_max == 1:
|
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
|
||||||
print " ovs_assert(inited);"
|
print " ovs_assert(inited);"
|
||||||
print " datum.n = 1;"
|
print " datum.n = 1;"
|
||||||
print " datum.keys = xmalloc(sizeof *datum.keys);"
|
print " datum.keys = &key;"
|
||||||
print " " + type.key.copyCValue("datum.keys[0].%s" % type.key.type.to_string(), keyVar)
|
print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)
|
||||||
if type.value:
|
if type.value:
|
||||||
print " datum.values = xmalloc(sizeof *datum.values);"
|
print " datum.values = &value;"
|
||||||
print " "+ type.value.copyCValue("datum.values[0].%s" % type.value.type.to_string(), valueVar)
|
print " "+ type.value.assign_c_value_casting_away_const("value.%s" % type.value.type.to_string(), valueVar)
|
||||||
else:
|
else:
|
||||||
print " datum.values = NULL;"
|
print " datum.values = NULL;"
|
||||||
|
txn_write_func = "ovsdb_idl_txn_write_clone"
|
||||||
elif type.is_optional_pointer():
|
elif type.is_optional_pointer():
|
||||||
|
print " union ovsdb_atom key;"
|
||||||
print
|
print
|
||||||
print " ovs_assert(inited);"
|
print " ovs_assert(inited);"
|
||||||
print " if (%s) {" % keyVar
|
print " if (%s) {" % keyVar
|
||||||
print " datum.n = 1;"
|
print " datum.n = 1;"
|
||||||
print " datum.keys = xmalloc(sizeof *datum.keys);"
|
print " datum.keys = &key;"
|
||||||
print " " + type.key.copyCValue("datum.keys[0].%s" % type.key.type.to_string(), keyVar)
|
print " " + type.key.assign_c_value_casting_away_const("key.%s" % type.key.type.to_string(), keyVar)
|
||||||
print " } else {"
|
print " } else {"
|
||||||
print " datum.n = 0;"
|
print " datum.n = 0;"
|
||||||
print " datum.keys = NULL;"
|
print " datum.keys = NULL;"
|
||||||
print " }"
|
print " }"
|
||||||
print " datum.values = NULL;"
|
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:
|
else:
|
||||||
print " size_t i;"
|
print " size_t i;"
|
||||||
print
|
print
|
||||||
print " ovs_assert(inited);"
|
print " ovs_assert(inited);"
|
||||||
print " datum.n = %s;" % nVar
|
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:
|
if type.value:
|
||||||
print " datum.values = xmalloc(%s * sizeof *datum.values);" % nVar
|
print " datum.values = xmalloc(%s * sizeof *datum.values);" % nVar
|
||||||
else:
|
else:
|
||||||
@@ -560,8 +580,10 @@ void
|
|||||||
valueType = "OVSDB_TYPE_VOID"
|
valueType = "OVSDB_TYPE_VOID"
|
||||||
print " ovsdb_datum_sort_unique(&datum, %s, %s);" % (
|
print " ovsdb_datum_sort_unique(&datum, %s, %s);" % (
|
||||||
type.key.toAtomicType(), valueType)
|
type.key.toAtomicType(), valueType)
|
||||||
print " ovsdb_idl_txn_write(&row->header_, &%(s)s_columns[%(S)s_COL_%(C)s], &datum);" \
|
txn_write_func = "ovsdb_idl_txn_write"
|
||||||
% {'s': structName,
|
print " %(f)s(&row->header_, &%(s)s_columns[%(S)s_COL_%(C)s], &datum);" \
|
||||||
|
% {'f': txn_write_func,
|
||||||
|
's': structName,
|
||||||
'S': structName.upper(),
|
'S': structName.upper(),
|
||||||
'C': columnName.upper()}
|
'C': columnName.upper()}
|
||||||
print "}"
|
print "}"
|
||||||
|
@@ -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");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -353,6 +353,15 @@ class BaseType(object):
|
|||||||
else:
|
else:
|
||||||
return "%(dst)s = %(src)s;" % args
|
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):
|
def initCDefault(self, var, is_optional):
|
||||||
if self.ref_table_name:
|
if self.ref_table_name:
|
||||||
return "%s = NULL;" % var
|
return "%s = NULL;" % var
|
||||||
|
Reference in New Issue
Block a user