perf comm str: Avoid sort during insert
authorIan Rogers <irogers@google.com>
Wed, 3 Jul 2024 17:21:16 +0000 (10:21 -0700)
committerNamhyung Kim <namhyung@kernel.org>
Mon, 8 Jul 2024 05:26:27 +0000 (22:26 -0700)
The array is sorted, so just move the elements and insert in order.

Fixes: 13ca628716c6 ("perf comm: Add reference count checking to 'struct comm_str'")
Reported-by: Matt Fleming <matt@readmodwrite.com>
Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Matt Fleming <matt@readmodwrite.com>
Cc: Steinar Gunderson <sesse@google.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Link: https://lore.kernel.org/r/20240703172117.810918-2-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/util/comm.c

index 233f2b6..49b79cf 100644 (file)
@@ -86,14 +86,6 @@ static struct comm_str *comm_str__new(const char *str)
        return result;
 }
 
-static int comm_str__cmp(const void *_lhs, const void *_rhs)
-{
-       const struct comm_str *lhs = *(const struct comm_str * const *)_lhs;
-       const struct comm_str *rhs = *(const struct comm_str * const *)_rhs;
-
-       return strcmp(comm_str__str(lhs), comm_str__str(rhs));
-}
-
 static int comm_str__search(const void *_key, const void *_member)
 {
        const char *key = _key;
@@ -169,9 +161,24 @@ static struct comm_str *comm_strs__findnew(const char *str)
                }
                result = comm_str__new(str);
                if (result) {
-                       comm_strs->strs[comm_strs->num_strs++] = result;
-                       qsort(comm_strs->strs, comm_strs->num_strs, sizeof(struct comm_str *),
-                             comm_str__cmp);
+                       int low = 0, high = comm_strs->num_strs - 1;
+                       int insert = comm_strs->num_strs; /* Default to inserting at the end. */
+
+                       while (low <= high) {
+                               int mid = low + (high - low) / 2;
+                               int cmp = strcmp(comm_str__str(comm_strs->strs[mid]), str);
+
+                               if (cmp < 0) {
+                                       low = mid + 1;
+                               } else {
+                                       high = mid - 1;
+                                       insert = mid;
+                               }
+                       }
+                       memmove(&comm_strs->strs[insert + 1], &comm_strs->strs[insert],
+                               (comm_strs->num_strs - insert) * sizeof(struct comm_str *));
+                       comm_strs->num_strs++;
+                       comm_strs->strs[insert] = result;
                }
        }
        up_write(&comm_strs->lock);