systemctl: piece-meal strv extension is expensive
authorLennart Poettering <lennart@poettering.net>
Tue, 26 Jan 2016 18:49:08 +0000 (19:49 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 27 Jan 2016 01:21:28 +0000 (02:21 +0100)
If we have many entries to add to an strv we really should try to be smarter than constantly realloc()ing the strv
array. Instead, grow it exponentially.

src/systemctl/systemctl.c

index 94c99c4..73f5710 100644 (file)
@@ -2658,14 +2658,25 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r
         if (!strv_isempty(globs)) {
                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
                 _cleanup_free_ UnitInfo *unit_infos = NULL;
+                size_t allocated, n;
 
                 r = get_unit_list(bus, NULL, globs, &unit_infos, 0, &reply);
                 if (r < 0)
                         return r;
 
-                for (i = 0; i < r; i++)
-                        if (strv_extend(&mangled, unit_infos[i].id) < 0)
+                n = strv_length(mangled);
+                allocated = n + 1;
+
+                for (i = 0; i < r; i++) {
+                        if (!GREEDY_REALLOC(mangled, allocated, n+2))
+                                return log_oom();
+
+                        mangled[n] = strdup(unit_infos[i].id);
+                        if (!mangled[n])
                                 return log_oom();
+
+                        mangled[++n] = NULL;
+                }
         }
 
         *ret = mangled;