summaryrefslogtreecommitdiff
path: root/ovsdb/storage.c
diff options
context:
space:
mode:
authorIlya Maximets <i.maximets@ovn.org>2021-08-24 21:00:38 +0200
committerIlya Maximets <i.maximets@ovn.org>2021-09-01 00:14:42 +0200
commit0de882954032aa37dc943bafd72c33324aa0c95a (patch)
tree9d3f8253b4a9895d6e58bbf3fe1eea340765db17 /ovsdb/storage.c
parentb0bca6f27aae845c3ca8b48d66a7dbd3d978162a (diff)
downloadopenvswitch-0de882954032aa37dc943bafd72c33324aa0c95a.tar.gz
raft: Don't keep full json objects in memory if no longer needed.
Raft log entries (and raft database snapshot) contains json objects of the data. Follower receives append requests with data that gets parsed and added to the raft log. Leader receives execution requests, parses data out of them and adds to the log. In both cases, later ovsdb-server reads the log with ovsdb_storage_read(), constructs transaction and updates the database. On followers these json objects in common case are never used again. Leader may use them to send append requests or snapshot installation requests to followers. However, all these operations (except for ovsdb_storage_read()) are just serializing the json in order to send it over the network. Json objects are significantly larger than their serialized string representation. For example, the snapshot of the database from one of the ovn-heater scale tests takes 270 MB as a string, but 1.6 GB as a json object from the total 3.8 GB consumed by ovsdb-server process. ovsdb_storage_read() for a given raft entry happens only once in a lifetime, so after this call, we can serialize the json object, store the string representation and free the actual json object that ovsdb will never need again. This can save a lot of memory and can also save serialization time, because each raft entry for append requests and snapshot installation requests serialized only once instead of doing that every time such request needs to be sent. JSON_SERIALIZED_OBJECT can be used in order to seamlessly integrate pre-serialized data into raft_header and similar json objects. One major special case is creation of a database snapshot. Snapshot installation request received over the network will be parsed and read by ovsdb-server just like any other raft log entry. However, snapshots created locally with raft_store_snapshot() will never be read back, because they reflect the current state of the database, hence already applied. For this case we can free the json object right after writing snapshot on disk. Tests performed with ovn-heater on 60 node density-light scenario, where on-disk database goes up to 97 MB, shows average memory consumption of ovsdb-server Southbound DB processes decreased by 58% (from 602 MB to 256 MB per process) and peak memory consumption decreased by 40% (from 1288 MB to 771 MB). Test with 120 nodes on density-heavy scenario with 270 MB on-disk database shows 1.5 GB memory consumption decrease as expected. Also, total CPU time consumed by the Southbound DB process reduced from 296 to 256 minutes. Number of unreasonably long poll intervals reduced from 2896 down to 1934. Acked-by: Dumitru Ceara <dceara@redhat.com> Acked-by: Han Zhou <hzhou@ovn.org> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Diffstat (limited to 'ovsdb/storage.c')
-rw-r--r--ovsdb/storage.c4
1 files changed, 1 insertions, 3 deletions
diff --git a/ovsdb/storage.c b/ovsdb/storage.c
index d727b1eac..9e32efe58 100644
--- a/ovsdb/storage.c
+++ b/ovsdb/storage.c
@@ -268,9 +268,7 @@ ovsdb_storage_read(struct ovsdb_storage *storage,
struct json *schema_json = NULL;
struct json *txn_json = NULL;
if (storage->raft) {
- bool is_snapshot;
- json = json_nullable_clone(
- raft_next_entry(storage->raft, txnid, &is_snapshot));
+ json = raft_next_entry(storage->raft, txnid);
if (!json) {
return NULL;
} else if (json->type != JSON_ARRAY || json->array.n != 2) {