Skip to content

Commit 375368a

Browse files
captain5050acmel
authored andcommitted
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 <[email protected]> Tested-by: Arnaldo Carvalho de Melo <[email protected]> Tested-by: Namhyung Kim <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: James Clark <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Kan Liang <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Ravi Bangoria <[email protected]> Cc: Thomas Richter <[email protected]> Cc: Xu Yang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent f3061d5 commit 375368a

File tree

3 files changed

+39
-35
lines changed

3 files changed

+39
-35
lines changed

tools/perf/util/fncache.c

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,58 @@
11
// SPDX-License-Identifier: GPL-2.0-only
22
/* Manage a cache of file names' existence */
3+
#include <pthread.h>
34
#include <stdlib.h>
4-
#include <unistd.h>
55
#include <string.h>
6-
#include <linux/list.h>
6+
#include <unistd.h>
7+
#include <linux/compiler.h>
78
#include "fncache.h"
9+
#include "hashmap.h"
810

9-
struct fncache {
10-
struct hlist_node nd;
11-
bool res;
12-
char name[];
13-
};
11+
static struct hashmap *fncache;
1412

15-
#define FNHSIZE 61
13+
static size_t fncache__hash(long key, void *ctx __maybe_unused)
14+
{
15+
return str_hash((const char *)key);
16+
}
1617

17-
static struct hlist_head fncache_hash[FNHSIZE];
18+
static bool fncache__equal(long key1, long key2, void *ctx __maybe_unused)
19+
{
20+
return strcmp((const char *)key1, (const char *)key2) == 0;
21+
}
1822

19-
unsigned shash(const unsigned char *s)
23+
static void fncache__init(void)
2024
{
21-
unsigned h = 0;
22-
while (*s)
23-
h = 65599 * h + *s++;
24-
return h ^ (h >> 16);
25+
fncache = hashmap__new(fncache__hash, fncache__equal, /*ctx=*/NULL);
26+
}
27+
28+
static struct hashmap *fncache__get(void)
29+
{
30+
static pthread_once_t fncache_once = PTHREAD_ONCE_INIT;
31+
32+
pthread_once(&fncache_once, fncache__init);
33+
34+
return fncache;
2535
}
2636

2737
static bool lookup_fncache(const char *name, bool *res)
2838
{
29-
int h = shash((const unsigned char *)name) % FNHSIZE;
30-
struct fncache *n;
31-
32-
hlist_for_each_entry(n, &fncache_hash[h], nd) {
33-
if (!strcmp(n->name, name)) {
34-
*res = n->res;
35-
return true;
36-
}
37-
}
38-
return false;
39+
long val;
40+
41+
if (!hashmap__find(fncache__get(), name, &val))
42+
return false;
43+
44+
*res = (val != 0);
45+
return true;
3946
}
4047

4148
static void update_fncache(const char *name, bool res)
4249
{
43-
struct fncache *n = malloc(sizeof(struct fncache) + strlen(name) + 1);
44-
int h = shash((const unsigned char *)name) % FNHSIZE;
45-
46-
if (!n)
47-
return;
48-
strcpy(n->name, name);
49-
n->res = res;
50-
hlist_add_head(&n->nd, &fncache_hash[h]);
50+
char *old_key = NULL, *key = strdup(name);
51+
52+
if (key) {
53+
hashmap__set(fncache__get(), key, res, &old_key, /*old_value*/NULL);
54+
free(old_key);
55+
}
5156
}
5257

5358
/* No LRU, only use when bounded in some other way. */

tools/perf/util/fncache.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#ifndef _FCACHE_H
22
#define _FCACHE_H 1
33

4-
unsigned shash(const unsigned char *s);
54
bool file_available(const char *name);
65

76
#endif

tools/perf/util/srccode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include "srccode.h"
1717
#include "debug.h"
1818
#include <internal/lib.h> // page_size
19-
#include "fncache.h"
19+
#include "hashmap.h"
2020

2121
#define MAXSRCCACHE (32*1024*1024)
2222
#define MAXSRCFILES 64
@@ -92,7 +92,7 @@ static struct srcfile *find_srcfile(char *fn)
9292
struct srcfile *h;
9393
int fd;
9494
unsigned long sz;
95-
unsigned hval = shash((unsigned char *)fn) % SRC_HTAB_SZ;
95+
size_t hval = str_hash(fn) % SRC_HTAB_SZ;
9696

9797
hlist_for_each_entry (h, &srcfile_htab[hval], hash_nd) {
9898
if (!strcmp(fn, h->fn)) {

0 commit comments

Comments
 (0)