[PATCH v2 05/18] perf db-export: Store symbol database IDs in a hashmap
From: Ian Rogers
Date: Tue Oct 27 2026 - 19:18:06 EST
Currently, db-export reserves sizeof(u64) bytes ahead of every allocated
struct symbol via symbol_conf.priv_size and accesses the database ID at
a negative offset via symbol__priv(). This adds 8 bytes to every loaded
symbol across all DSOs even when only a subset of symbols are exported,
and negative-offset pointer arithmetic ahead of struct symbol is
incompatible with wrapping struct symbol in DECLARE_RC_STRUCT(symbol).
Store exported symbol database IDs in an on-demand sym_db_ids hashmap in
struct db_export instead of using symbol__priv().
Signed-off-by: Ian Rogers <irogers@xxxxxxxxxx>
---
tools/perf/util/db-export.c | 68 ++++++++++++++++++++++++++++++-------
tools/perf/util/db-export.h | 8 +++++
2 files changed, 63 insertions(+), 13 deletions(-)
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index 732369fe0046..6ebc060bdb8f 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -4,21 +4,37 @@
* Copyright (c) 2014, Intel Corporation.
*/
+#include "db-export.h"
+
#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
#include <stdlib.h>
+#include <linux/err.h>
+
+#include "call-path.h"
+#include "callchain.h"
+#include "comm.h"
#include "dso.h"
+#include "event.h"
#include "evsel.h"
+#include "hashmap.h"
#include "machine.h"
-#include "thread.h"
-#include "comm.h"
-#include "symbol.h"
#include "map.h"
-#include "event.h"
+#include "symbol.h"
#include "thread-stack.h"
-#include "callchain.h"
-#include "call-path.h"
-#include "db-export.h"
+#include "thread.h"
+
+static size_t sym_ptr_hash(long key, void *ctx __maybe_unused)
+{
+ return hash_bits((size_t)key, 16);
+}
+
+static bool sym_ptr_equal(long key1, long key2, void *ctx __maybe_unused)
+{
+ return key1 == key2;
+}
int db_export__init(struct db_export *dbe)
{
@@ -28,6 +44,8 @@ int db_export__init(struct db_export *dbe)
void db_export__exit(struct db_export *dbe)
{
+ hashmap__free(dbe->sym_db_ids);
+ dbe->sym_db_ids = NULL;
call_return_processor__free(dbe->crp);
dbe->crp = NULL;
}
@@ -156,15 +174,41 @@ int db_export__dso(struct db_export *dbe, struct dso *dso,
return 0;
}
+/*
+ * Return the database export ID assigned to @sym in @dbe->sym_db_ids, or 0
+ * if @sym has not been exported yet.
+ */
+u64 db_export__symbol_db_id(struct db_export *dbe, struct symbol *sym)
+{
+ long db_id = 0;
+
+ if (sym && dbe->sym_db_ids)
+ hashmap__find(dbe->sym_db_ids, (long)sym, &db_id);
+ return (u64)db_id;
+}
+
int db_export__symbol(struct db_export *dbe, struct symbol *sym,
struct dso *dso)
{
- u64 *sym_db_id = symbol__priv(sym);
+ long db_id;
- if (*sym_db_id)
+ if (db_export__symbol_db_id(dbe, sym))
return 0;
- *sym_db_id = ++dbe->symbol_last_db_id;
+ if (!dbe->sym_db_ids) {
+ dbe->sym_db_ids =
+ hashmap__new(sym_ptr_hash, sym_ptr_equal, NULL);
+ if (IS_ERR(dbe->sym_db_ids)) {
+ int err = PTR_ERR(dbe->sym_db_ids);
+
+ dbe->sym_db_ids = NULL;
+ return err;
+ }
+ }
+
+ db_id = ++dbe->symbol_last_db_id;
+ if (hashmap__set(dbe->sym_db_ids, (long)sym, db_id, NULL, NULL))
+ return -ENOMEM;
if (dbe->export_symbol)
return dbe->export_symbol(dbe, sym, dso);
@@ -192,12 +236,10 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
}
if (al->sym) {
- u64 *db_id = symbol__priv(al->sym);
-
err = db_export__symbol(dbe, al->sym, dso);
if (err)
return err;
- *sym_db_id = *db_id;
+ *sym_db_id = db_export__symbol_db_id(dbe, al->sym);
*offset = al->addr - symbol__start(al->sym);
}
}
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
index 1abbfd398e3a..2e0cf2dfa281 100644
--- a/tools/perf/util/db-export.h
+++ b/tools/perf/util/db-export.h
@@ -21,6 +21,8 @@ struct call_return_processor;
struct call_path_root;
struct call_path;
struct call_return;
+struct hashmap;
+struct symbol;
struct export_sample {
union perf_event *event;
@@ -63,6 +65,11 @@ struct db_export {
u64 th_in_id, u64 comm_in_id, int flags);
struct call_return_processor *crp;
struct call_path_root *cpr;
+ /**
+ * @sym_db_ids: Hashmap mapping struct symbol pointers to their
+ * exported 64-bit database IDs.
+ */
+ struct hashmap *sym_db_ids;
u64 evsel_last_db_id;
u64 machine_last_db_id;
u64 thread_last_db_id;
@@ -90,6 +97,7 @@ int db_export__comm_thread(struct db_export *dbe, struct comm *comm,
struct thread *thread);
int db_export__dso(struct db_export *dbe, struct dso *dso,
struct machine *machine);
+u64 db_export__symbol_db_id(struct db_export *dbe, struct symbol *sym);
int db_export__symbol(struct db_export *dbe, struct symbol *sym,
struct dso *dso);
int db_export__branch_type(struct db_export *dbe, u32 branch_type,
--
2.56.0.313.g2479322e68-goog