perf dsos: When adding a dso into sorted dsos maintain the sort order
authorIan Rogers <irogers@google.com>
Wed, 3 Jul 2024 17:21:17 +0000 (10:21 -0700)
committerNamhyung Kim <namhyung@kernel.org>
Mon, 8 Jul 2024 05:26:29 +0000 (22:26 -0700)
dsos__add would add at the end of the dso array possibly requiring a
later find to re-sort the array. Patterns of find then add were
becoming O(n*log n) due to the sorts. Change the add routine to be
O(n) rather than O(1) but to maintain the sorted-ness of the dsos
array so that later finds don't need the O(n*log n) sort.

Fixes: 3f4ac23a9908 ("perf dsos: Switch backing storage to array from rbtree/list")
Reported-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Steinar Gunderson <sesse@google.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Matt Fleming <matt@readmodwrite.com>
Link: https://lore.kernel.org/r/20240703172117.810918-3-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/util/dsos.c

index ab3d0c01dd63971199659c22624e7d38d2ed2a9a..a69a9c6612008fa22a6f5026f1ae90c6ae4eed3c 100644 (file)
@@ -203,11 +203,27 @@ int __dsos__add(struct dsos *dsos, struct dso *dso)
                dsos->dsos = temp;
                dsos->allocated = to_allocate;
        }
-       dsos->dsos[dsos->cnt++] = dso__get(dso);
-       if (dsos->cnt >= 2 && dsos->sorted) {
-               dsos->sorted = dsos__cmp_long_name_id_short_name(&dsos->dsos[dsos->cnt - 2],
-                                                                &dsos->dsos[dsos->cnt - 1])
-                       <= 0;
+       if (!dsos->sorted) {
+               dsos->dsos[dsos->cnt++] = dso__get(dso);
+       } else {
+               int low = 0, high = dsos->cnt - 1;
+               int insert = dsos->cnt; /* Default to inserting at the end. */
+
+               while (low <= high) {
+                       int mid = low + (high - low) / 2;
+                       int cmp = dsos__cmp_long_name_id_short_name(&dsos->dsos[mid], &dso);
+
+                       if (cmp < 0) {
+                               low = mid + 1;
+                       } else {
+                               high = mid - 1;
+                               insert = mid;
+                       }
+               }
+               memmove(&dsos->dsos[insert + 1], &dsos->dsos[insert],
+                       (dsos->cnt - insert) * sizeof(struct dso *));
+               dsos->cnt++;
+               dsos->dsos[insert] = dso__get(dso);
        }
        dso__set_dsos(dso, dsos);
        return 0;