properties: Skip value building for nominal case

bus_message_print_all_properties() builds a PROP= string for every
property in the reply so that -p PROP=value filters can be matched
against it, but most queries never need this.

Take the normal `systemctl show` or `systemctl show UNIT` case. In that
case there is no filter. Even with `-p PROP` there is no value filter
since there is no value.

Avoid constructing the string entirely by comparing property names
directly against filter entries.

In my tests with a `systemctl show` over 160 units this brings the
instructions retired from 992.6M down to 960.5M, a reduction of 3.2%.

The same goes for property filters with units. When running:

    systemctl show -p UnitFileState -p ActiveState UNIT

...the instructions retired drops from 9.52M to 9.22M, a reduction of
3.2%. The output in each case is unchanged.
This commit is contained in:
Chris Down
2026-08-01 00:53:16 -07:00
parent 5663ddaed7
commit 248d6cf09d
+29 -9
View File
@@ -344,6 +344,34 @@ static int bus_print_property(const char *name, const char *expected_value, sd_b
return 0;
}
static bool match_filter(char **filter, const char *name, const char **ret_expected_value) {
const char *expected_value = NULL;
assert(name);
assert(ret_expected_value);
if (!filter) {
*ret_expected_value = NULL;
return true;
}
STRV_FOREACH(f, filter) {
const char *p = startswith(*f, name);
if (!p)
continue;
if (*p == '\0') {
*ret_expected_value = NULL;
return true;
}
if (*p == '=' && !expected_value)
expected_value = p + 1;
}
*ret_expected_value = expected_value;
return expected_value != NULL;
}
int bus_message_print_all_properties(
sd_bus_message *m,
bus_message_print_t func,
@@ -360,7 +388,6 @@ int bus_message_print_all_properties(
return r;
while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
_cleanup_free_ char *name_with_equal = NULL;
const char *name, *contents, *expected_value = NULL;
r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
@@ -373,14 +400,7 @@ int bus_message_print_all_properties(
return log_oom();
}
name_with_equal = strjoin(name, "=");
if (!name_with_equal)
return log_oom();
if (!filter ||
strv_contains(filter, name) ||
(expected_value = strv_find_startswith(filter, name_with_equal))) {
if (match_filter(filter, name, &expected_value)) {
r = sd_bus_message_peek_type(m, NULL, &contents);
if (r < 0)
return r;