core: avoid checking sort order for cached settings list

We now have a cached list of NMSettingsConnection instances,
sorted by their autoconnect priority.

However, the sort order nm_settings_connection_cmp_autoconnect_priority()
depends on various properties of the connection:

 - "connection.autoconnect" and "connection.autoconnect-priority"
 - the timestamp
 - "connection.uuid"

These properties almost never change, so it's a waste that every call
to nm_settings_get_connections_sorted_by_autoconnect_priority() needs
to check whether the sort order is still satisfied.

We can do better by tracking when the sort order might have been
destroyed and only check in those (much fewer) cases.

Note that we end up calling nm_settings_get_connections_sorted_by_autoconnect_priority()
a lot, so this makes a difference.
This commit is contained in:
Thomas Haller 2021-06-17 19:29:33 +02:00
parent 252e4a676b
commit 877d2b236f
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
3 changed files with 40 additions and 11 deletions

View file

@ -337,6 +337,7 @@ _nm_settings_connection_set_connection(NMSettingsConnection * self,
nmtst_connection_assert_unchanging(priv->connection);
_getsettings_cached_clear(priv);
_nm_settings_notify_sorted_by_autoconnect_priority_maybe_changed(priv->settings);
/* note that we only return @connection_old if the new connection actually differs from
* before.
@ -2251,6 +2252,8 @@ nm_settings_connection_update_timestamp(NMSettingsConnection *self, guint64 time
_LOGT("timestamp: set timestamp %" G_GUINT64_FORMAT, timestamp);
_nm_settings_notify_sorted_by_autoconnect_priority_maybe_changed(priv->settings);
if (!priv->kf_db_timestamps)
return;

View file

@ -390,6 +390,12 @@ typedef struct {
bool started : 1;
/* Whether NMSettingsConnections changed in a way that affects the comparison
* with nm_settings_connection_cmp_autoconnect_priority_with_data(). In that case,
* we may need to re-sort the connections_cached_list_sorted_by_autoconnect_priority
* list. */
bool sorted_by_autoconnect_priority_maybe_changed : 1;
} NMSettingsPrivate;
struct _NMSettings {
@ -2871,6 +2877,14 @@ impl_settings_reload_connections(NMDBusObject * obj,
/*****************************************************************************/
void
_nm_settings_notify_sorted_by_autoconnect_priority_maybe_changed(NMSettings *self)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE(self);
priv->sorted_by_autoconnect_priority_maybe_changed = TRUE;
}
static void
_clear_connections_cached_list(NMSettingsPrivate *priv)
{
@ -3067,19 +3081,29 @@ nm_settings_get_connections_sorted_by_autoconnect_priority(NMSettings *self, gui
priv->connections_cached_list_sorted_by_autoconnect_priority =
nm_memdup(list_cached, sizeof(NMSettingsConnection *) * (len + 1));
needs_sort = (len > 1);
} else if (!nm_utils_ptrarray_is_sorted(
(gconstpointer *) priv->connections_cached_list_sorted_by_autoconnect_priority,
priv->connections_len,
FALSE,
nm_settings_connection_cmp_autoconnect_priority_with_data,
NULL)) {
/* We cache the sorted list, but we don't monitor all entries whether they
* get modified to invalidate the sort order. So every time we have to check
* whether the sort order is still correct. The vast majority of the time it
* is, and this check is faster than sorting anew. */
needs_sort = TRUE;
} else if (priv->sorted_by_autoconnect_priority_maybe_changed) {
if (!nm_utils_ptrarray_is_sorted(
(gconstpointer *) priv->connections_cached_list_sorted_by_autoconnect_priority,
priv->connections_len,
FALSE,
nm_settings_connection_cmp_autoconnect_priority_with_data,
NULL)) {
/* We cache the sorted list, but we don't monitor all entries whether they
* get modified to invalidate the sort order. So every time we have to check
* whether the sort order is still correct. The vast majority of the time it
* is, and this check is faster than sorting anew. */
needs_sort = TRUE;
}
} else {
nm_assert(nm_utils_ptrarray_is_sorted(
(gconstpointer *) priv->connections_cached_list_sorted_by_autoconnect_priority,
priv->connections_len,
TRUE,
nm_settings_connection_cmp_autoconnect_priority_with_data,
NULL));
}
priv->sorted_by_autoconnect_priority_maybe_changed = FALSE;
if (needs_sort) {
g_qsort_with_data(priv->connections_cached_list_sorted_by_autoconnect_priority,
priv->connections_len,

View file

@ -130,4 +130,6 @@ const char *nm_settings_get_startup_complete_blocked_reason(NMSettings *self,
void nm_settings_kf_db_write(NMSettings *settings);
void _nm_settings_notify_sorted_by_autoconnect_priority_maybe_changed(NMSettings *self);
#endif /* __NM_SETTINGS_H__ */