mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-28 09:06:11 -05:00
perf fncache: Switch to using hashmap
The existing fncache can get large in testing situations. As the bucket array is a fixed size this leads to it degrading to O(n) performance. Use a regular hashmap that can dynamically reallocate its array. Before: ``` $ time perf test "Parsing of PMU event table metrics" 10.3: Parsing of PMU event table metrics : Ok 10.4: Parsing of PMU event table metrics with fake PMUs : Ok real 0m14.132s user 0m17.806s sys 0m0.557s ``` After: ``` $ time perf test "Parsing of PMU event table metrics" 10.3: Parsing of PMU event table metrics : Ok 10.4: Parsing of PMU event table metrics with fake PMUs : Ok real 0m13.287s user 0m13.026s sys 0m0.532s ``` Committer notes: root@number:~# grep -m1 'model name' /proc/cpuinfo model name : AMD Ryzen 9 9950X3D 16-Core Processor root@number:~# Before: root@number:~# time perf test "Parsing of PMU event table metrics" 10.3: Parsing of PMU event table metrics : Ok 10.4: Parsing of PMU event table metrics with fake PMUs : Ok real 0m9.277s user 0m9.979s sys 0m0.055s root@number:~# After: root@number:~# time perf test "Parsing of PMU event table metrics" 10.3: Parsing of PMU event table metrics : Ok 10.4: Parsing of PMU event table metrics with fake PMUs : Ok real 0m9.296s user 0m9.361s sys 0m0.063s root@number:~# Signed-off-by: Ian Rogers <irogers@google.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Tested-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@linaro.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Cc: Thomas Richter <tmricht@linux.ibm.com> Cc: Xu Yang <xu.yang_2@nxp.com> Link: https://lore.kernel.org/r/20250512194622.33258-2-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
committed by
Arnaldo Carvalho de Melo
parent
f3061d5267
commit
375368a961
@@ -1,53 +1,58 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* Manage a cache of file names' existence */
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <linux/list.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/compiler.h>
|
||||
#include "fncache.h"
|
||||
#include "hashmap.h"
|
||||
|
||||
struct fncache {
|
||||
struct hlist_node nd;
|
||||
bool res;
|
||||
char name[];
|
||||
};
|
||||
static struct hashmap *fncache;
|
||||
|
||||
#define FNHSIZE 61
|
||||
|
||||
static struct hlist_head fncache_hash[FNHSIZE];
|
||||
|
||||
unsigned shash(const unsigned char *s)
|
||||
static size_t fncache__hash(long key, void *ctx __maybe_unused)
|
||||
{
|
||||
unsigned h = 0;
|
||||
while (*s)
|
||||
h = 65599 * h + *s++;
|
||||
return h ^ (h >> 16);
|
||||
return str_hash((const char *)key);
|
||||
}
|
||||
|
||||
static bool fncache__equal(long key1, long key2, void *ctx __maybe_unused)
|
||||
{
|
||||
return strcmp((const char *)key1, (const char *)key2) == 0;
|
||||
}
|
||||
|
||||
static void fncache__init(void)
|
||||
{
|
||||
fncache = hashmap__new(fncache__hash, fncache__equal, /*ctx=*/NULL);
|
||||
}
|
||||
|
||||
static struct hashmap *fncache__get(void)
|
||||
{
|
||||
static pthread_once_t fncache_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
pthread_once(&fncache_once, fncache__init);
|
||||
|
||||
return fncache;
|
||||
}
|
||||
|
||||
static bool lookup_fncache(const char *name, bool *res)
|
||||
{
|
||||
int h = shash((const unsigned char *)name) % FNHSIZE;
|
||||
struct fncache *n;
|
||||
long val;
|
||||
|
||||
hlist_for_each_entry(n, &fncache_hash[h], nd) {
|
||||
if (!strcmp(n->name, name)) {
|
||||
*res = n->res;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (!hashmap__find(fncache__get(), name, &val))
|
||||
return false;
|
||||
|
||||
*res = (val != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void update_fncache(const char *name, bool res)
|
||||
{
|
||||
struct fncache *n = malloc(sizeof(struct fncache) + strlen(name) + 1);
|
||||
int h = shash((const unsigned char *)name) % FNHSIZE;
|
||||
char *old_key = NULL, *key = strdup(name);
|
||||
|
||||
if (!n)
|
||||
return;
|
||||
strcpy(n->name, name);
|
||||
n->res = res;
|
||||
hlist_add_head(&n->nd, &fncache_hash[h]);
|
||||
if (key) {
|
||||
hashmap__set(fncache__get(), key, res, &old_key, /*old_value*/NULL);
|
||||
free(old_key);
|
||||
}
|
||||
}
|
||||
|
||||
/* No LRU, only use when bounded in some other way. */
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef _FCACHE_H
|
||||
#define _FCACHE_H 1
|
||||
|
||||
unsigned shash(const unsigned char *s);
|
||||
bool file_available(const char *name);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include "srccode.h"
|
||||
#include "debug.h"
|
||||
#include <internal/lib.h> // page_size
|
||||
#include "fncache.h"
|
||||
#include "hashmap.h"
|
||||
|
||||
#define MAXSRCCACHE (32*1024*1024)
|
||||
#define MAXSRCFILES 64
|
||||
@@ -92,7 +92,7 @@ static struct srcfile *find_srcfile(char *fn)
|
||||
struct srcfile *h;
|
||||
int fd;
|
||||
unsigned long sz;
|
||||
unsigned hval = shash((unsigned char *)fn) % SRC_HTAB_SZ;
|
||||
size_t hval = str_hash(fn) % SRC_HTAB_SZ;
|
||||
|
||||
hlist_for_each_entry (h, &srcfile_htab[hval], hash_nd) {
|
||||
if (!strcmp(fn, h->fn)) {
|
||||
|
||||
Reference in New Issue
Block a user