properties: Skip unnecessary per property filtering (#43146)

In total this can save ~18% CPU on `systemctl show` nominal queries in
my tests.
This commit is contained in:
Chris Down
2026-08-01 13:30:59 -07:00
committed by GitHub
2 changed files with 39 additions and 13 deletions
+29 -9
View File
@@ -345,6 +345,34 @@ static int bus_print_property(
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,
@@ -361,7 +389,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);
@@ -374,14 +401,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;
+10 -4
View File
@@ -2337,6 +2337,7 @@ static int show_one(
.io_read_bytes = UINT64_MAX,
.io_write_bytes = UINT64_MAX,
};
bool collect_found_properties;
int r;
assert(path);
@@ -2388,13 +2389,18 @@ static int show_one(
if (r < 0)
return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
r = bus_message_print_all_properties(reply, print_property, arg_properties, arg_print_flags, &found_properties);
/* The found properties set is expensive and only used for debug logging, so collect it only when needed. */
collect_found_properties = DEBUG_LOGGING && !strv_isempty(arg_properties);
r = bus_message_print_all_properties(reply, print_property, arg_properties, arg_print_flags,
collect_found_properties ? &found_properties : NULL);
if (r < 0)
return bus_log_parse_error(r);
STRV_FOREACH(pp, arg_properties)
if (!set_contains(found_properties, *pp))
log_debug("Property %s does not exist.", *pp);
if (collect_found_properties)
STRV_FOREACH(pp, arg_properties)
if (!set_contains(found_properties, *pp))
log_debug("Property %s does not exist.", *pp);
return 0;
}