diff options
author | Thomas Haller <thaller@redhat.com> | 2019-11-21 09:04:53 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-11-21 14:02:58 +0100 |
commit | dc8e12aedff06f7435f164c22d85a9417b2459f8 (patch) | |
tree | 29d968d850ab9b4c84d96bf3f5acd8ae12a93ae1 | |
parent | ce45a0b8f096430df932c1b16e8d6558d5ece07e (diff) | |
download | NetworkManager-th/libnm-dns-entry-cleanup.tar.gz |
libnm: avoid extra memory allocations in NMDnsEntryth/libnm-dns-entry-cleanup
NMDnsEntry is a simple object with a few fields. It has literally
no logic, it only exists to hold the information.
Let's spend some effort compacting the data. We don't need an extra
memory allocation for the (immutable) interface name. We can just append
it to the NMDnsEntry allocation. Likewise, we don't need full strv
arrays, just embed all the strings in one memory allocation using
nm_utils_strv_dup_inline().
-rw-r--r-- | libnm/nm-dns-manager.c | 56 |
1 files changed, 37 insertions, 19 deletions
diff --git a/libnm/nm-dns-manager.c b/libnm/nm-dns-manager.c index 09d4c83230..a809fc88e6 100644 --- a/libnm/nm-dns-manager.c +++ b/libnm/nm-dns-manager.c @@ -21,14 +21,18 @@ G_DEFINE_BOXED_TYPE (NMDnsEntry, nm_dns_entry, nm_dns_entry_ref, nm_dns_entry_unref) struct NMDnsEntry { - char *interface; - char **nameservers; - char **domains; + const char **nameservers; + const char **domains; int ref_count; int priority; bool vpn:1; + bool has_interface:1; + bool has_nameservers:1; + bool has_domains:1; + + char interface[0]; }; /** @@ -46,16 +50,25 @@ nm_dns_entry_new (const char *interface, gboolean vpn) { NMDnsEntry *entry; + gsize l; + + l = interface ? strlen (interface) + 1u : 0u; + + entry = g_malloc (sizeof (NMDnsEntry) + l); + entry->ref_count = 1, + entry->priority = priority, + entry->vpn = vpn, + entry->nameservers = nm_utils_strv_dup_inline (nameservers, -1); + entry->domains = nm_utils_strv_dup_inline (domains, -1); + + /* for empty arrays, we don't allocation a strv array. However, we + * need to remember whether the array was NULL or empty. */ + entry->has_nameservers = (!!nameservers); + entry->has_domains = (!!domains); - entry = g_slice_new (NMDnsEntry); - *entry = (NMDnsEntry) { - .ref_count = 1, - .interface = g_strdup (interface), - .priority = priority, - .vpn = vpn, - .nameservers = g_strdupv ((char **) nameservers), - .domains = g_strdupv ((char **) domains), - }; + entry->has_interface = (!!interface); + if (interface) + memcpy (entry->interface, interface, l); return entry; } @@ -96,10 +109,9 @@ nm_dns_entry_unref (NMDnsEntry *entry) if (!g_atomic_int_dec_and_test (&entry->ref_count)) return; - g_free (entry->interface); - g_strfreev (entry->nameservers); - g_strfreev (entry->domains); - g_slice_free (NMDnsEntry, entry); + g_free (entry->nameservers); + g_free (entry->domains); + g_free (entry); } /** @@ -118,7 +130,7 @@ nm_dns_entry_get_interface (NMDnsEntry *entry) g_return_val_if_fail (entry, 0); g_return_val_if_fail (entry->ref_count > 0, 0); - return entry->interface; + return entry->has_interface ? entry->interface : NULL; } /** @@ -137,7 +149,10 @@ nm_dns_entry_get_nameservers (NMDnsEntry *entry) g_return_val_if_fail (entry, 0); g_return_val_if_fail (entry->ref_count > 0, 0); - return (const char *const*) entry->nameservers; + return entry->nameservers + ?: ( entry->has_nameservers + ? (const char *const*) &entry->nameservers + : NULL); } /** @@ -156,7 +171,10 @@ nm_dns_entry_get_domains (NMDnsEntry *entry) g_return_val_if_fail (entry, 0); g_return_val_if_fail (entry->ref_count > 0, 0); - return (const char *const*) entry->domains; + return entry->domains + ?: ( entry->has_domains + ? (const char *const*) &entry->domains + : NULL); } /** |