From: Ian Rogers <irogers@google.com>
To: irogers@google.com, acme@kernel.org, haghdoost@uber.com,
namhyung@kernel.org
Cc: adrian.hunter@intel.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 v3 06/20] perf call-path: Use struct dso_symbol to retain symbol DSO lifetimes
Date: Tue, 10 Nov 2026 14:07:49 -0800 [thread overview]
Message-ID: <20261110220803.2503416-7-irogers@google.com> (raw)
In-Reply-To: <20261110220803.2503416-1-irogers@google.com>
struct call_path stores resolved function symbols for the lifetime of a
call_path_root (in thread-stack call/return processing and db-export)
without holding a map reference. Similarly, Python callchain frames and
nodes store resolved symbols across Python object lifetimes.
Replace bare struct symbol * fields in struct call_path,
struct pyrf_callchain_frame, and struct pyrf_callchain_node with
struct dso_symbol so that each retained symbol pins its owning
struct dso until call_path_root__free() or Python deallocation. In
python.c, this also avoids duplicating symbol names for call_path frames
and allows pyrf_callchain_node__get_dso() to report the DSO of resolved
call_path symbols whose ip was zeroed.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/call-path.c | 42 ++++++++++++++++++++-------
tools/perf/util/call-path.h | 10 ++++---
tools/perf/util/db-export.c | 12 ++++++--
tools/perf/util/python.c | 53 +++++++++++++++-------------------
tools/perf/util/thread-stack.c | 40 +++++++++++++------------
5 files changed, 93 insertions(+), 64 deletions(-)
diff --git a/tools/perf/util/call-path.c b/tools/perf/util/call-path.c
index 5c60b8be1cf6..eac52a902d6b 100644
--- a/tools/perf/util/call-path.c
+++ b/tools/perf/util/call-path.c
@@ -10,13 +10,21 @@
#include <stdlib.h>
#include "call-path.h"
+#include "dso.h"
static void call_path__init(struct call_path *cp, struct call_path *parent,
- struct symbol *sym, u64 ip, bool in_kernel)
+ const struct dso_symbol *ds, u64 ip, bool in_kernel)
{
+ struct symbol *sym = ds ? ds->sym : NULL;
+
cp->parent = parent;
- cp->sym = sym;
- cp->ip = sym ? 0 : ip;
+ if (sym) {
+ dso_symbol__copy(&cp->ds, ds);
+ cp->ip = 0;
+ } else {
+ cp->ds = (struct dso_symbol){};
+ cp->ip = ip;
+ }
cp->db_id = 0;
cp->in_kernel = in_kernel;
RB_CLEAR_NODE(&cp->rb_node);
@@ -39,7 +47,13 @@ void call_path_root__free(struct call_path_root *cpr)
{
struct call_path_block *pos, *n;
+ if (!cpr)
+ return;
+
+ dso_symbol__exit(&cpr->call_path.ds);
list_for_each_entry_safe(pos, n, &cpr->blocks, node) {
+ for (size_t i = 0; i < CALL_PATH_BLOCK_SIZE; i++)
+ dso_symbol__exit(&pos->cp[i].ds);
list_del_init(&pos->node);
free(pos);
}
@@ -48,7 +62,7 @@ void call_path_root__free(struct call_path_root *cpr)
static struct call_path *call_path__new(struct call_path_root *cpr,
struct call_path *parent,
- struct symbol *sym, u64 ip,
+ const struct dso_symbol *ds, u64 ip,
bool in_kernel)
{
struct call_path_block *cpb;
@@ -69,17 +83,20 @@ static struct call_path *call_path__new(struct call_path_root *cpr,
n = cpr->next++ & CALL_PATH_BLOCK_MASK;
cp = &cpb->cp[n];
- call_path__init(cp, parent, sym, ip, in_kernel);
+ call_path__init(cp, parent, ds, ip, in_kernel);
return cp;
}
struct call_path *call_path__findnew(struct call_path_root *cpr,
struct call_path *parent,
- struct symbol *sym, u64 ip, u64 ks)
+ const struct dso_symbol *ds,
+ u64 ip, u64 ks)
{
struct rb_node **p;
struct rb_node *node_parent = NULL;
+ struct symbol *sym = ds ? ds->sym : NULL;
+ const void *dso_ptr = (sym && ds->dso) ? RC_CHK_ACCESS(ds->dso) : NULL;
struct call_path *cp;
bool in_kernel = ip >= ks;
@@ -87,23 +104,28 @@ struct call_path *call_path__findnew(struct call_path_root *cpr,
ip = 0;
if (!parent)
- return call_path__new(cpr, parent, sym, ip, in_kernel);
+ return call_path__new(cpr, parent, ds, ip, in_kernel);
p = &parent->children.rb_node;
while (*p != NULL) {
+ const void *cp_dso_ptr;
+
node_parent = *p;
cp = rb_entry(node_parent, struct call_path, rb_node);
+ cp_dso_ptr = cp->ds.dso ? RC_CHK_ACCESS(cp->ds.dso) : NULL;
- if (cp->sym == sym && cp->ip == ip)
+ if (cp->ds.sym == sym && cp_dso_ptr == dso_ptr && cp->ip == ip)
return cp;
- if (sym < cp->sym || (sym == cp->sym && ip < cp->ip))
+ if (sym < cp->ds.sym ||
+ (sym == cp->ds.sym && dso_ptr < cp_dso_ptr) ||
+ (sym == cp->ds.sym && dso_ptr == cp_dso_ptr && ip < cp->ip))
p = &(*p)->rb_left;
else
p = &(*p)->rb_right;
}
- cp = call_path__new(cpr, parent, sym, ip, in_kernel);
+ cp = call_path__new(cpr, parent, ds, ip, in_kernel);
if (!cp)
return NULL;
diff --git a/tools/perf/util/call-path.h b/tools/perf/util/call-path.h
index 5875cfc8106e..e43aa7513633 100644
--- a/tools/perf/util/call-path.h
+++ b/tools/perf/util/call-path.h
@@ -11,12 +11,13 @@
#include <linux/types.h>
#include <linux/rbtree.h>
+#include "map_symbol.h"
/**
* struct call_path - node in list of calls leading to a function call.
* @parent: call path to the parent function call
- * @sym: symbol of function called
- * @ip: only if sym is null, the ip of the function
+ * @ds: DSO and symbol of function called
+ * @ip: only if ds.sym is null, the ip of the function
* @db_id: id used for db-export
* @in_kernel: whether function is a in the kernel
* @rb_node: node in parent's tree of called functions
@@ -27,7 +28,7 @@
*/
struct call_path {
struct call_path *parent;
- struct symbol *sym;
+ struct dso_symbol ds;
u64 ip;
u64 db_id;
bool in_kernel;
@@ -63,6 +64,7 @@ void call_path_root__free(struct call_path_root *cpr);
struct call_path *call_path__findnew(struct call_path_root *cpr,
struct call_path *parent,
- struct symbol *sym, u64 ip, u64 ks);
+ const struct dso_symbol *ds,
+ u64 ip, u64 ks);
#endif
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index ba54b1119ee6..6a5db62cd58b 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -261,12 +261,18 @@ static struct call_path *call_path_from_sample(struct db_export *dbe,
db_ids_from_al(dbe, &al, &dso_db_id, &sym_db_id, &offset);
/* add node to the call path tree if it doesn't exist */
- current = call_path__findnew(dbe->cpr, current,
- al.sym, node->ip,
- kernel_start);
+ {
+ struct dso_symbol ds = dso_symbol__from_al(&al);
+
+ current = call_path__findnew(dbe->cpr, current,
+ &ds, node->ip,
+ kernel_start);
+ }
callchain_cursor_advance(cursor);
addr_location__exit(&al);
+ if (!current)
+ break;
}
/* Reset the callchain order to its prior value. */
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 42c587cd54a5..2fcbab8e69ec 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -937,14 +937,13 @@ struct pyrf_callchain_node {
PyObject_HEAD
u64 ip;
struct map *map;
- struct symbol *sym;
- char *sym_name;
+ struct dso_symbol ds;
};
static void pyrf_callchain_node__delete(struct pyrf_callchain_node *pnode)
{
map__put(pnode->map);
- free(pnode->sym_name);
+ dso_symbol__exit(&pnode->ds);
Py_TYPE(pnode)->tp_free((PyObject *)pnode);
}
@@ -957,27 +956,22 @@ static PyObject *pyrf_callchain_node__get_ip(struct pyrf_callchain_node *pnode,
static PyObject *pyrf_callchain_node__get_symbol(struct pyrf_callchain_node *pnode,
void *closure __maybe_unused)
{
- if (pnode->sym_name)
- return PyUnicode_FromString(pnode->sym_name);
- if (pnode->sym)
- return PyUnicode_FromString(pnode->sym->name);
+ if (pnode->ds.sym)
+ return PyUnicode_FromString(pnode->ds.sym->name);
return PyUnicode_FromString("[unknown]");
}
static PyObject *pyrf_callchain_node__get_dso(struct pyrf_callchain_node *pnode,
void *closure __maybe_unused)
{
+ struct dso *dso = pnode->ds.dso ?: (pnode->map ? map__dso(pnode->map) : NULL);
const char *dsoname = "[unknown]";
- if (pnode->map) {
- struct dso *dso = map__dso(pnode->map);
-
- if (dso) {
- if (symbol_conf.show_kernel_path && dso__long_name(dso))
- dsoname = dso__long_name(dso);
- else
- dsoname = dso__name(dso);
- }
+ if (dso) {
+ if (symbol_conf.show_kernel_path && dso__long_name(dso))
+ dsoname = dso__long_name(dso);
+ else
+ dsoname = dso__name(dso);
}
return PyUnicode_FromString(dsoname);
}
@@ -987,11 +981,11 @@ static PyObject *pyrf_callchain_node__get_sym_offset(struct pyrf_callchain_node
{
u64 addr;
- if (!pnode->sym)
+ if (!pnode->ds.sym || (!pnode->map && !pnode->ip))
Py_RETURN_NONE;
addr = pnode->map ? map__map_ip(pnode->map, pnode->ip) : pnode->ip;
- return PyLong_FromUnsignedLongLong(addr - pnode->sym->start);
+ return PyLong_FromUnsignedLongLong(addr - pnode->ds.sym->start);
}
static PyGetSetDef pyrf_callchain_node__getset[] = {
@@ -1015,8 +1009,7 @@ static PyTypeObject pyrf_callchain_node__type = {
struct pyrf_callchain_frame {
u64 ip;
struct map *map;
- struct symbol *sym;
- char *sym_name;
+ struct dso_symbol ds;
};
struct pyrf_callchain {
@@ -1030,7 +1023,7 @@ static void pyrf_callchain__delete(struct pyrf_callchain *pchain)
if (pchain->frames) {
for (u64 i = 0; i < pchain->nr_frames; i++) {
map__put(pchain->frames[i].map);
- free(pchain->frames[i].sym_name);
+ dso_symbol__exit(&pchain->frames[i].ds);
}
free(pchain->frames);
}
@@ -1060,8 +1053,7 @@ static PyObject *pyrf_callchain__item(PyObject *obj, Py_ssize_t i)
pnode->ip = pchain->frames[i].ip;
pnode->map = map__get(pchain->frames[i].map);
- pnode->sym = pchain->frames[i].sym;
- pnode->sym_name = pchain->frames[i].sym_name ? strdup(pchain->frames[i].sym_name) : NULL;
+ dso_symbol__copy(&pnode->ds, &pchain->frames[i].ds);
return (PyObject *)pnode;
}
@@ -1111,10 +1103,16 @@ static int pyrf_sample_event__resolve_callchain(struct pyrf_event *pevent)
return -ENOMEM;
}
for (u64 i = 0; i < pchain->nr_frames; i++) {
+ struct dso_symbol ds;
+
node = callchain_cursor_current(cursor);
+ ds = (struct dso_symbol){
+ .dso = (node->ms.sym && node->ms.map) ? map__dso(node->ms.map) : NULL,
+ .sym = node->ms.sym,
+ };
pchain->frames[i].ip = node->ip;
pchain->frames[i].map = map__get(node->ms.map);
- pchain->frames[i].sym = node->ms.sym;
+ dso_symbol__copy(&pchain->frames[i].ds, &ds);
callchain_cursor_advance(cursor);
}
pevent->callchain = (PyObject *)pchain;
@@ -4504,10 +4502,9 @@ static PyObject *pyrf_call_path__to_callchain(const struct call_path *cp,
struct pyrf_callchain_frame *frame = &pchain->frames[--nr_frames];
frame->ip = pos->ip;
- frame->sym = NULL;
- frame->sym_name = pos->sym ? strdup(pos->sym->name) : NULL;
+ dso_symbol__copy(&frame->ds, &pos->ds);
frame->map = NULL;
- if (thread) {
+ if (thread && !pos->ds.sym) {
struct addr_location al;
u8 cpumode = pos->in_kernel ? PERF_RECORD_MISC_KERNEL
: PERF_RECORD_MISC_USER;
@@ -4515,8 +4512,6 @@ static PyObject *pyrf_call_path__to_callchain(const struct call_path *cp,
addr_location__init(&al);
thread__find_map(thread, cpumode, pos->ip, &al);
frame->map = map__get(al.map);
- if (frame->map)
- frame->sym = pos->sym;
addr_location__exit(&al);
}
}
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index d452d1a7eabb..aa05acb0467c 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -11,6 +11,7 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include "addr_location.h"
#include "thread.h"
#include "event.h"
#include "machine.h"
@@ -823,7 +824,7 @@ static int thread_stack__pop_cp(struct thread *thread, struct thread_stack *ts,
if (ts->cnt == 1) {
struct thread_stack_entry *tse = &ts->stack[0];
- if (tse->cp->sym == sym)
+ if (tse->cp->ds.sym == sym)
return thread_stack__call_return(thread, ts, --ts->cnt,
timestamp, ref, false);
}
@@ -862,21 +863,21 @@ static int thread_stack__bottom(struct thread_stack *ts,
struct addr_location *to_al, u64 ref)
{
struct call_path_root *cpr = ts->crp->cpr;
+ struct dso_symbol ds;
struct call_path *cp;
- struct symbol *sym;
u64 ip;
if (sample->ip) {
ip = sample->ip;
- sym = from_al->sym;
+ ds = dso_symbol__from_al(from_al);
} else if (sample->addr) {
ip = sample->addr;
- sym = to_al->sym;
+ ds = dso_symbol__from_al(to_al);
} else {
return 0;
}
- cp = call_path__findnew(cpr, &cpr->call_path, sym, ip,
+ cp = call_path__findnew(cpr, &cpr->call_path, &ds, ip,
ts->kernel_start);
return thread_stack__push_cp(ts, ip, sample->time, ref, cp,
@@ -908,8 +909,8 @@ static int thread_stack__no_call_return(struct thread *thread,
{
struct call_path_root *cpr = ts->crp->cpr;
struct call_path *root = &cpr->call_path;
- struct symbol *fsym = from_al->sym;
- struct symbol *tsym = to_al->sym;
+ struct dso_symbol fds = dso_symbol__from_al(from_al);
+ struct dso_symbol tds = dso_symbol__from_al(to_al);
struct call_path *cp, *parent;
u64 ks = ts->kernel_start;
u64 addr = sample->addr;
@@ -925,7 +926,7 @@ static int thread_stack__no_call_return(struct thread *thread,
/* If the stack is empty, push the userspace address */
if (!ts->cnt) {
- cp = call_path__findnew(cpr, root, tsym, addr, ks);
+ cp = call_path__findnew(cpr, root, &tds, addr, ks);
return thread_stack__push_cp(ts, 0, tm, ref, cp, true,
false);
}
@@ -941,7 +942,7 @@ static int thread_stack__no_call_return(struct thread *thread,
else
parent = root;
- if (parent->sym == from_al->sym) {
+ if (parent->ds.sym == from_al->sym) {
/*
* At the bottom of the stack, assume the missing 'call' was
* before the trace started. So, pop the current symbol and push
@@ -955,7 +956,7 @@ static int thread_stack__no_call_return(struct thread *thread,
}
if (!ts->cnt) {
- cp = call_path__findnew(cpr, root, tsym, addr, ks);
+ cp = call_path__findnew(cpr, root, &tds, addr, ks);
return thread_stack__push_cp(ts, addr, tm, ref, cp,
true, false);
@@ -965,7 +966,7 @@ static int thread_stack__no_call_return(struct thread *thread,
* Otherwise assume the 'return' is being used as a jump (e.g.
* retpoline) and just push the 'to' symbol.
*/
- cp = call_path__findnew(cpr, parent, tsym, addr, ks);
+ cp = call_path__findnew(cpr, parent, &tds, addr, ks);
err = thread_stack__push_cp(ts, 0, tm, ref, cp, true, false);
if (!err)
@@ -979,13 +980,13 @@ static int thread_stack__no_call_return(struct thread *thread,
* pop 'from'.
*/
- cp = call_path__findnew(cpr, parent, tsym, addr, ks);
+ cp = call_path__findnew(cpr, parent, &tds, addr, ks);
err = thread_stack__push_cp(ts, addr, tm, ref, cp, true, false);
if (err)
return err;
- cp = call_path__findnew(cpr, cp, fsym, ip, ks);
+ cp = call_path__findnew(cpr, cp, &fds, ip, ks);
err = thread_stack__push_cp(ts, ip, tm, ref, cp, true, false);
if (err)
@@ -1052,7 +1053,8 @@ static int thread_stack__x86_retpoline(struct thread_stack *ts,
{
struct thread_stack_entry *tse = &ts->stack[ts->cnt - 1];
struct call_path_root *cpr = ts->crp->cpr;
- struct symbol *sym = tse->cp->sym;
+ struct symbol *sym = tse->cp->ds.sym;
+ struct dso_symbol tds = dso_symbol__from_al(to_al);
struct symbol *tsym = to_al->sym;
struct call_path *cp;
@@ -1068,7 +1070,7 @@ static int thread_stack__x86_retpoline(struct thread_stack *ts,
* graph, since all the original branches are left unchanged.
*/
ts->cnt -= 1;
- sym = ts->stack[ts->cnt - 2].cp->sym;
+ sym = ts->stack[ts->cnt - 2].cp->ds.sym;
if (sym && sym == tsym && to_al->addr != tsym->start) {
/*
* Target is back to the middle of the symbol we came
@@ -1087,7 +1089,7 @@ static int thread_stack__x86_retpoline(struct thread_stack *ts,
return 0;
}
- cp = call_path__findnew(cpr, ts->stack[ts->cnt - 2].cp, tsym,
+ cp = call_path__findnew(cpr, ts->stack[ts->cnt - 2].cp, &tds,
sample->addr, ts->kernel_start);
if (!cp)
return -ENOMEM;
@@ -1147,6 +1149,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
if (sample->flags & PERF_IP_FLAG_CALL) {
bool trace_end = sample->flags & PERF_IP_FLAG_TRACE_END;
+ struct dso_symbol tds = dso_symbol__from_al(to_al);
struct call_path_root *cpr = ts->crp->cpr;
struct call_path *cp;
u64 ret_addr;
@@ -1160,7 +1163,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
return 0; /* Zero-length calls are excluded */
cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp,
- to_al->sym, sample->addr,
+ &tds, sample->addr,
ts->kernel_start);
err = thread_stack__push_cp(ts, ret_addr, sample->time, ref,
cp, false, trace_end);
@@ -1209,6 +1212,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
} else if (sample->flags & PERF_IP_FLAG_BRANCH &&
from_al->sym != to_al->sym && to_al->sym &&
to_al->addr == to_al->sym->start) {
+ struct dso_symbol tds = dso_symbol__from_al(to_al);
struct call_path_root *cpr = ts->crp->cpr;
struct call_path *cp;
@@ -1219,7 +1223,7 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
* when a ret pops the stack, all jmps must be popped off first.
*/
cp = call_path__findnew(cpr, ts->stack[ts->cnt - 1].cp,
- to_al->sym, sample->addr,
+ &tds, sample->addr,
ts->kernel_start);
err = thread_stack__push_cp(ts, 0, sample->time, ref, cp, false,
false);
--
2.56.0.542.g3ef89b7020-goog
next prev parent reply other threads:[~2026-11-10 22:08 UTC|newest]
Thread overview: 73+ 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-29 19:46 ` Alireza Haghdoost
2026-11-01 2:48 ` Namhyung Kim
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-30 4:08 ` Alireza Haghdoost
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-30 12:51 ` Alireza Haghdoost
2026-10-27 23:15 ` [PATCH v2 07/18] perf symbol: Switch backing storage from rbtree to struct symbols array Ian Rogers
2026-10-30 13:12 ` Alireza Haghdoost
2026-10-27 23:15 ` [PATCH v2 08/18] perf symbol: Add reference counting and DECLARE_RC_STRUCT(symbol) Ian Rogers
2026-10-30 13:22 ` Alireza Haghdoost
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-30 13:27 ` Alireza Haghdoost
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-30 13:32 ` Alireza Haghdoost
2026-10-27 23:15 ` [PATCH v2 12/18] perf rwsem: Add down_read_trylock() and down_write_trylock() Ian Rogers
2026-10-30 13:39 ` Alireza Haghdoost
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-30 13:53 ` Alireza Haghdoost
2026-10-27 23:15 ` [PATCH v2 16/18] perf session: Add dso__session() and session-scoped allocation wrappers Ian Rogers
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
2026-10-30 13:55 ` Alireza Haghdoost
2026-10-28 20:29 ` [PATCH v2 00/18] perf symbol: Reference counting, sorted arrays, and memory shrinking Ian Rogers
2026-10-30 14:02 ` Alireza Haghdoost
2026-10-30 16:10 ` Ian Rogers
2026-10-30 17:57 ` Ian Rogers
2026-10-31 17:22 ` David Laight
2026-11-10 22:07 ` [PATCH v3 00/20] perf symbol: Sorted arrays, DSO-owned lifetimes, " Ian Rogers
2026-11-10 22:07 ` [PATCH v3 01/20] perf map_browser: Fix browser index heap corruption by computing on demand Ian Rogers
2026-11-10 22:07 ` [PATCH v3 02/20] perf machine: Protect machines->guests rbtree with a rw_semaphore Ian Rogers
2026-11-10 22:07 ` [PATCH v3 03/20] perf vdso: Constify dso parameter in dso__is_vdso() Ian Rogers
2026-11-10 22:07 ` [PATCH v3 04/20] perf rwsem: Add down_read_trylock() and down_write_trylock() Ian Rogers
2026-11-10 22:07 ` [PATCH v3 05/20] perf map_symbol: Add struct dso_symbol and use for parent symbols Ian Rogers
2026-11-10 22:07 ` Ian Rogers [this message]
2026-11-10 22:07 ` [PATCH v3 07/20] perf db-export: Store symbol database IDs in a hashmap Ian Rogers
2026-11-10 22:07 ` [PATCH v3 08/20] perf annotate: Move struct annotation to a hashmap and remove symbol_conf.priv_size Ian Rogers
2026-11-10 22:07 ` [PATCH v3 09/20] perf bench internals: Add symbols benchmark Ian Rogers
2026-11-10 22:07 ` [PATCH v3 10/20] perf bench internals: Add maps benchmark Ian Rogers
2026-11-10 22:07 ` [PATCH v3 11/20] perf demangle: Add fast-path prefix checks for Rust and Java demanglers Ian Rogers
2026-11-10 22:07 ` [PATCH v3 12/20] perf symbol-elf: Cache ELF program/section headers and defer symbol name lookup Ian Rogers
2026-11-10 22:07 ` [PATCH v3 13/20] perf maps: Optimize tail insertion and small-append sorting Ian Rogers
2026-11-10 22:07 ` [PATCH v3 14/20] perf symbol: Add accessor functions for struct symbol fields Ian Rogers
2026-11-10 22:07 ` [PATCH v3 15/20] perf symbol: Switch backing storage from rbtree to struct symbols array Ian Rogers
2026-11-10 22:07 ` [PATCH v3 16/20] perf symbol: Optimize symbol sorting with natural-run merge sort and binary insertion Ian Rogers
2026-11-10 22:08 ` [PATCH v3 17/20] perf symbol: Add memory shrinking for symbols, DSOs, and machines Ian Rogers
2026-11-10 22:08 ` [PATCH v3 18/20] perf session: Add dso__session() and session-scoped allocation wrappers Ian Rogers
2026-11-10 22:08 ` [PATCH v3 19/20] perf symbol: Use session allocation wrappers in symbol, DSO, thread, and hist paths Ian Rogers
2026-11-10 22:08 ` [PATCH v3 20/20] 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=20261110220803.2503416-7-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®