From: Ian Rogers <irogers@google.com>
To: irogers@google.com, acme@kernel.org, namhyung@kernel.org
Cc: adrian.hunter@intel.com, haghdoost@uber.com,
james.clark@linaro.org, jolsa@kernel.org,
linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
mingo@redhat.com, peterz@infradead.org
Subject: [PATCH v2 16/18] perf session: Add dso__session() and session-scoped allocation wrappers
Date: Tue, 27 Oct 2026 16:15:10 -0700 [thread overview]
Message-ID: <20261027231513.816148-17-irogers@google.com> (raw)
In-Reply-To: <20261027231513.816148-1-irogers@google.com>
Add explicit session-scoped memory allocation wrappers:
- perf_session__malloc(session, size)
- perf_session__zalloc(session, size)
- perf_session__calloc(session, nmemb, size)
- perf_session__realloc(session, ptr, size)
- perf_session__strdup(session, s)
When an allocation fails and returns NULL, if a non-NULL struct
perf_session is provided, the wrapper invokes perf_session__shrink() to
evict unreferenced symbols, DSOs, and cached debuginfo across the
session's machines and then retries the allocation once. This avoids
the thrashing overhead of periodic heuristic shrinking while allowing
perf to recover from memory exhaustion.
Also plumb a back-pointer from struct dsos to its owning struct machine
so machine__session(machine) and dso__session(dso) can resolve the
active perf_session.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/dso.c | 7 ++++
tools/perf/util/dso.h | 2 ++
tools/perf/util/dsos.c | 1 +
tools/perf/util/dsos.h | 1 +
tools/perf/util/machine.c | 1 +
tools/perf/util/machine.h | 5 +++
tools/perf/util/session.c | 70 +++++++++++++++++++++++++++++++++++++++
tools/perf/util/session.h | 6 ++++
8 files changed, 93 insertions(+)
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index be257c77ab0a..c19de9ab4b24 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1911,6 +1911,13 @@ void dso__delete(struct dso *dso)
RC_CHK_FREE(dso);
}
+struct perf_session *dso__session(const struct dso *dso)
+{
+ struct dsos *dsos = dso ? RC_CHK_ACCESS(dso)->dsos : NULL;
+
+ return dsos ? machine__session(dsos->machine) : NULL;
+}
+
bool dso__can_shrink_symbols(const struct dso *dso)
{
const char *name;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 64a118ea2524..5fa059ba6cf1 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -19,6 +19,7 @@
struct machine;
struct map;
struct perf_env;
+struct perf_session;
#define DSO__NAME_KALLSYMS "[kernel.kallsyms]"
#define DSO__NAME_KCORE "[kernel.kcore]"
@@ -802,6 +803,7 @@ static inline refcount_t *dso__refcnt(struct dso *dso)
bool dso__can_shrink_symbols(const struct dso *dso);
size_t dso__shrink(struct dso *dso);
+struct perf_session *dso__session(const struct dso *dso);
char *dso__filename_with_chroot(const struct dso *dso, const char *filename);
diff --git a/tools/perf/util/dsos.c b/tools/perf/util/dsos.c
index 30ecc9a19244..8f3e3f3c6ce3 100644
--- a/tools/perf/util/dsos.c
+++ b/tools/perf/util/dsos.c
@@ -18,6 +18,7 @@ void dsos__init(struct dsos *dsos)
{
init_rwsem(&dsos->lock);
+ dsos->machine = NULL;
dsos->cnt = 0;
dsos->allocated = 0;
dsos->dsos = NULL;
diff --git a/tools/perf/util/dsos.h b/tools/perf/util/dsos.h
index 151efdba2aa4..d636e4c5cbaf 100644
--- a/tools/perf/util/dsos.h
+++ b/tools/perf/util/dsos.h
@@ -19,6 +19,7 @@ struct machine;
*/
struct dsos {
struct rw_semaphore lock;
+ struct machine *machine;
struct dso **dsos;
unsigned int cnt;
unsigned int allocated;
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 8d0c545ee544..3e0d68fd5efe 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -81,6 +81,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
memset(machine, 0, sizeof(*machine));
RB_CLEAR_NODE(&machine->rb_node);
dsos__init(&machine->dsos);
+ machine->dsos.machine = machine;
threads__init(&machine->threads);
machine->kmaps = maps__new(machine);
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 1d1f46a01a38..ab67cef67c80 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -164,6 +164,11 @@ static inline struct perf_session *machines__session(struct machines *machines)
return machines->session;
}
+static inline struct perf_session *machine__session(const struct machine *machine)
+{
+ return machine && machine->machines ? machine->machines->session : NULL;
+}
+
void machines__process_guests(struct machines *machines,
machine__process_t process, void *data);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 3f35c7affc29..3d4bc9c0063a 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -4274,3 +4274,73 @@ size_t perf_session__shrink(struct perf_session *session)
return machines__shrink(&session->machines);
}
+
+static __thread bool perf_session__in_shrink;
+
+static bool perf_session__try_shrink(struct perf_session *session)
+{
+ size_t freed;
+
+ if (!session || perf_session__in_shrink)
+ return false;
+
+ perf_session__in_shrink = true;
+ freed = perf_session__shrink(session);
+ perf_session__in_shrink = false;
+
+ return freed > 0;
+}
+
+void *perf_session__malloc(struct perf_session *session, size_t size)
+{
+ void *ptr = malloc(size);
+
+ if (unlikely(!ptr && size != 0) && perf_session__try_shrink(session))
+ ptr = malloc(size);
+
+ return ptr;
+}
+
+void *perf_session__zalloc(struct perf_session *session, size_t size)
+{
+ void *ptr = zalloc(size);
+
+ if (unlikely(!ptr && size != 0) && perf_session__try_shrink(session))
+ ptr = zalloc(size);
+
+ return ptr;
+}
+
+void *perf_session__calloc(struct perf_session *session, size_t nmemb, size_t size)
+{
+ void *ptr = calloc(nmemb, size);
+
+ if (unlikely(!ptr && nmemb != 0 && size != 0) && perf_session__try_shrink(session))
+ ptr = calloc(nmemb, size);
+
+ return ptr;
+}
+
+void *perf_session__realloc(struct perf_session *session, void *ptr, size_t size)
+{
+ void *new_ptr = realloc(ptr, size);
+
+ if (unlikely(!new_ptr && size != 0) && perf_session__try_shrink(session))
+ new_ptr = realloc(ptr, size);
+
+ return new_ptr;
+}
+
+char *perf_session__strdup(struct perf_session *session, const char *s)
+{
+ char *dup;
+
+ if (!s)
+ return NULL;
+
+ dup = strdup(s);
+ if (unlikely(!dup) && perf_session__try_shrink(session))
+ dup = strdup(s);
+
+ return dup;
+}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index fdec65fcfee6..90ae16a631b0 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -219,4 +219,10 @@ uint16_t perf_session__e_machine(struct perf_session *session, uint32_t *e_flags
size_t perf_session__shrink(struct perf_session *session);
+void *perf_session__malloc(struct perf_session *session, size_t size);
+void *perf_session__zalloc(struct perf_session *session, size_t size);
+void *perf_session__calloc(struct perf_session *session, size_t nmemb, size_t size);
+void *perf_session__realloc(struct perf_session *session, void *ptr, size_t size);
+char *perf_session__strdup(struct perf_session *session, const char *s);
+
#endif /* __PERF_SESSION_H */
--
2.56.0.313.g2479322e68-goog
next prev parent reply other threads:[~2026-10-27 23:15 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 7:52 [PATCH v1 0/7] perf symbol: Reference counting, flat array storage, and LRU shrinking Ian Rogers
2026-09-28 7:52 ` [PATCH v1 1/7] perf symbol: Add accessor functions for struct symbol fields Ian Rogers
2026-09-28 7:52 ` [PATCH v1 2/7] perf symbol: Remove symbol_conf.priv_size and negative-offset allocations Ian Rogers
2026-09-28 7:52 ` [PATCH v1 3/7] perf symbol: Switch backing storage from rbtree to struct symbols array Ian Rogers
2026-09-28 7:52 ` [PATCH v1 4/7] perf symbol: Add reference counting and DECLARE_RC_STRUCT(symbol) Ian Rogers
2026-09-28 7:52 ` [PATCH v1 5/7] perf symbol: Add LRU memory shrinking for symbols, DSOs, and machines Ian Rogers
2026-09-28 7:52 ` [PATCH v1 6/7] perf session: Periodically shrink symbols and DSOs during event processing Ian Rogers
2026-09-28 7:52 ` [PATCH v1 7/7] perf test symbols: Add tests for symbol and DSO LRU shrinking Ian Rogers
2026-09-28 15:37 ` [PATCH v1 0/7] perf symbol: Reference counting, flat array storage, and " Ian Rogers
2026-09-28 19:45 ` Alireza Haghdoost
2026-09-28 20:55 ` Ian Rogers
2026-09-28 21:51 ` Namhyung Kim
2026-09-28 22:04 ` Ian Rogers
2026-09-29 0:12 ` Alireza Haghdoost
2026-09-29 18:09 ` Namhyung Kim
2026-09-29 21:24 ` Alireza Haghdoost
2026-09-29 18:06 ` Namhyung Kim
2026-10-27 23:14 ` [PATCH v2 00/18] perf symbol: Reference counting, sorted arrays, and memory shrinking Ian Rogers
2026-10-27 23:14 ` [PATCH v2 01/18] perf bench internals: Add symbols and maps benchmarks Ian Rogers
2026-10-27 23:14 ` [PATCH v2 02/18] perf demangle: Add fast-path prefix checks for Rust and Java demanglers Ian Rogers
2026-10-27 23:14 ` [PATCH v2 03/18] perf symbol: Add accessor functions for struct symbol fields Ian Rogers
2026-10-27 23:14 ` [PATCH v2 04/18] perf map_browser: Compute symbol browser index on demand Ian Rogers
2026-10-27 23:14 ` [PATCH v2 05/18] perf db-export: Store symbol database IDs in a hashmap Ian Rogers
2026-10-27 23:15 ` [PATCH v2 06/18] perf annotate: Move struct annotation to a hashmap and remove symbol_conf.priv_size Ian Rogers
2026-10-27 23:15 ` [PATCH v2 07/18] perf symbol: Switch backing storage from rbtree to struct symbols array Ian Rogers
2026-10-27 23:15 ` [PATCH v2 08/18] perf symbol: Add reference counting and DECLARE_RC_STRUCT(symbol) Ian Rogers
2026-10-27 23:15 ` [PATCH v2 09/18] perf symbol: Optimize symbol sorting with natural-run merge sort and binary insertion Ian Rogers
2026-10-27 23:15 ` [PATCH v2 10/18] perf maps: Optimize tail insertion and small-append sorting Ian Rogers
2026-10-27 23:15 ` [PATCH v2 11/18] perf symbol-elf: Cache ELF program/section headers and defer symbol name lookup Ian Rogers
2026-10-27 23:15 ` [PATCH v2 12/18] perf rwsem: Add down_read_trylock() and down_write_trylock() Ian Rogers
2026-10-27 23:15 ` [PATCH v2 13/18] perf vdso: Constify dso parameter in dso__is_vdso() Ian Rogers
2026-10-27 23:15 ` [PATCH v2 14/18] perf machine: Protect machines->guests rbtree with a rw_semaphore Ian Rogers
2026-10-27 23:15 ` [PATCH v2 15/18] perf symbol: Add memory shrinking for symbols, DSOs, and machines Ian Rogers
2026-10-27 23:15 ` Ian Rogers [this message]
2026-10-27 23:15 ` [PATCH v2 17/18] perf symbol: Use session allocation wrappers in symbol, DSO, thread, and hist paths Ian Rogers
2026-10-27 23:15 ` [PATCH v2 18/18] perf test symbols: Add tests for symbol shrinking and session alloc wrappers Ian Rogers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261027231513.816148-17-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=haghdoost@uber.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®