Skip to content

[th/setting-to-dbus-fcn] associate NMSetting's C property getters with property info

Thomas Haller requested to merge th/setting-to-dbus-fcn into main

refactor how we convert properties to D-Bus.

  • unify the handling of converting a property to GVariant. Every property (that can be converted) now has a to_dbus_fcn callback.

  • better separate what is the property-meta-data (NMSettInfoProperty) and the property-tyes (NMSettInfoPropertType) by moving gprop_to_dbus_fcn from the property-type to the property-meta-data.

  • NMSetting properties are implemented as GObject properties, but we commonly also add a C getter. Make it possible to hook the C getter to the property-meta-data, this way we can more efficiently get the native value. This is currently implemented as a showcase for boolean and string properties (and not all of them are converted). The advantage is that we no longer need to call g_object_get_property() to first obtain the property as GValue before converting it to GVariant. Instead, we can get the native value (in case of string properties, that for example means that we don't need to copy the string unlike the g_value_set_string()). This makes to_dbus_fcn() more efficient.

  • note that also to compare two properties we currently convert the properties to GVariant (via to_dbus_fcn()) and compare the variants. And for keyfile, we also use the GObject property getters. This is all inefficient. What this branch does, is to associate the C getter with the properties, and this information can be used in the future for comparing properties more efficiently and converting them to keyfile.

  • not all properties are converted, only some to showcase how it could be. If this branch gets accepted, more could be done in a similar fashion.


Here is a patch that I used for simple benchmarking.

From ca06a8402b1eabded1d085d4ab1915451f2d4e56 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Fri, 18 Jun 2021 19:50:21 +0200
Subject: [PATCH 1/1] test: benchmark nm_connection_to_dbus()

  $ DO_PREPARE=1 DO_MAKE=1 WITH_LTO=0 ./test.sh
  $ DO_MAKE=1 ./test.sh

  $ time N_RUN=10000 DO_MAKE=1 N_PERF=40 ./test.sh

Before:

  Performance counter stats for 'src/libnm-core-impl/tests/test-setting' (40 runs):

            597.94 msec task-clock:u              #    0.990 CPUs utilized            ( +-  0.32% )
                 0      context-switches:u        #    0.000 K/sec
                 0      cpu-migrations:u          #    0.000 K/sec
               335      page-faults:u             #    0.560 K/sec                    ( +-  0.10% )
     1,833,800,804      cycles:u                  #    3.067 GHz                      ( +-  0.33% )
     3,706,851,292      instructions:u            #    2.02  insn per cycle           ( +-  0.02% )
       887,290,280      branches:u                # 1483.924 M/sec                    ( +-  0.02% )
         6,365,535      branch-misses:u           #    0.72% of all branches          ( +-  0.55% )

           0.60382 +- 0.00208 seconds time elapsed  ( +-  0.34% )

After:

  Performance counter stats for 'src/libnm-core-impl/tests/test-setting' (40 runs):

            529.58 msec task-clock:u              #    0.993 CPUs utilized            ( +-  1.27% )
                 0      context-switches:u        #    0.000 K/sec
                 0      cpu-migrations:u          #    0.000 K/sec
               337      page-faults:u             #    0.637 K/sec                    ( +-  0.13% )
     1,610,694,059      cycles:u                  #    3.041 GHz                      ( +-  1.24% )
     3,134,739,319      instructions:u            #    1.95  insn per cycle           ( +-  0.01% )
       760,283,280      branches:u                # 1435.635 M/sec                    ( +-  0.01% )
         4,666,630      branch-misses:u           #    0.61% of all branches          ( +-  1.14% )

           0.53328 +- 0.00719 seconds time elapsed  ( +-  1.35% )
---
 src/libnm-core-impl/tests/test-setting.c | 22 ++++++++++++++++
 test.sh                                  | 32 ++++++++++++++++++++++++
 2 files changed, 54 insertions(+)
 create mode 100755 test.sh

diff --git a/src/libnm-core-impl/tests/test-setting.c b/src/libnm-core-impl/tests/test-setting.c
index aba02134ed46..a1395632d893 100644
--- a/src/libnm-core-impl/tests/test-setting.c
+++ b/src/libnm-core-impl/tests/test-setting.c
@@ -4678,6 +4678,28 @@ main(int argc, char **argv)
 {
     nmtst_init(&argc, &argv, TRUE);
 
+    {
+        gs_unref_object NMConnection *connection = NULL;
+        int                           i;
+        int                           n_run;
+
+        connection = nmtst_create_minimal_connection("test1",
+                                                     "ec6731ae-6dc8-40d8-a538-ffd928d750f6",
+                                                     NM_SETTING_WIRED_SETTING_NAME,
+                                                     NULL);
+        nmtst_connection_normalize(connection);
+
+        n_run = _nm_utils_ascii_str_to_int64(g_getenv("N_RUN"), 10, 1, G_MAXINT, 1);
+
+        for (i = 0; i < n_run; i++) {
+            gs_unref_variant GVariant *var = NULL;
+
+            var = nm_connection_to_dbus(connection, NM_CONNECTION_SERIALIZE_ALL);
+            g_assert(var);
+        }
+        return 0;
+    }
+
     g_test_add_func("/libnm/test_connection_uuid", test_connection_uuid);
 
     g_test_add_func("/libnm/settings/test_nm_meta_setting_types_by_priority",
diff --git a/test.sh b/test.sh
new file mode 100755
index 000000000000..9b0d9714052d
--- /dev/null
+++ b/test.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+set -x
+
+build_prepare() {
+    git clean -fdx
+    local llto=--enable-lto
+    test "$WITH_LTO" != 1 && llto=--disable-lto
+    CFLAGS='-O2 -Wno-error=array-bounds' ./autogen.sh --without-more-asserts "$llto"
+}
+
+build_make() {
+    test "$MAKE_FORCE" = 1 && touch src/libnm-core-impl/tests/test-setting.c
+    make -j 10 src/libnm-core-impl/tests/test-setting
+    test "$DO_STRIP" = 1 && strip src/libnm-core-impl/tests/test-setting
+    src/libnm-core-impl/tests/test-setting &>/dev/null
+}
+
+run() {
+    perf stat -r "${N_PERF-1}" -B src/libnm-core-impl/tests/test-setting 1>/dev/null
+}
+
+test "$DO_PREPARE" = 1 && build_prepare
+
+test "$DO_MAKE" = 1 && build_make
+
+run
+
+# DO_PREPARE=1 DO_MAKE=1 WITH_LTO=1 ./test.sh
+# DO_MAKE=1 ./test.sh
+# time N_RUN=10000 DO_MAKE=1 N_PERF=40 ./test.sh
+# time N_RUN=1000 valgrind --tool=callgrind --log-file=valgrind.log src/libnm-core-impl/tests/test-setting
-- 
2.31.1
Edited by Thomas Haller

Merge request reports