File 1151-erts-Make-trace-info-S-MFA-Item-less-wasteful.patch of Package erlang
From a9d98805abda89f03bfa2558e9191b822e406e90 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Thu, 19 Jun 2025 17:33:19 +0200
Subject: [PATCH 1/7] erts: Make trace:info(S, MFA, Item) less wasteful
Don't spend time and heap memory on items not asked for.
---
erts/emulator/beam/erl_bif_trace.c | 134 ++++++++++++++++++-----------
1 file changed, 86 insertions(+), 48 deletions(-)
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 3ab153e2a6..ebb58a3007 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -1798,6 +1798,7 @@ trace_info_pid(Process* p, ErtsTraceSession* session, Eterm pid_spec, Eterm key)
static int function_is_traced(Process *p,
ErtsTraceSession *session,
const ErtsCodeMFA *mfa,
+ int want,
Binary **ms, /* out */
Binary **ms_meta, /* out */
ErtsTracer *tracer_pid_meta, /* out */
@@ -1806,43 +1807,52 @@ static int function_is_traced(Process *p,
Eterm *call_memory) /* out */
{
const ErtsCodeInfo *ci;
- const Export *ep;
- Export e;
/* First look for an export entry */
- e.info.mfa = *mfa;
- if ((ep = export_get(&e)) != NULL) {
- if (erts_is_export_trampoline_active(ep, erts_active_code_ix()) &&
- ! BeamIsOpCode(ep->trampoline.common.op, op_call_error_handler)) {
+ if (want & FUNC_TRACE_GLOBAL_TRACE) {
+ const Export *ep;
+ Export e;
- ASSERT(BeamIsOpCode(ep->trampoline.common.op, op_i_generic_breakpoint));
+ e.info.mfa = *mfa;
+ if ((ep = export_get(&e)) != NULL) {
+ if (erts_is_export_trampoline_active(ep, erts_active_code_ix()) &&
+ ! BeamIsOpCode(ep->trampoline.common.op, op_call_error_handler)) {
- if (erts_is_trace_break(session, &ep->info, ms, 0)) {
- return FUNC_TRACE_GLOBAL_TRACE;
- }
+ ASSERT(BeamIsOpCode(ep->trampoline.common.op, op_i_generic_breakpoint));
- ASSERT(!erts_is_trace_break(session, &ep->info, ms, 1));
- ASSERT(!erts_is_mtrace_break(session, &ep->info, ms_meta, tracer_pid_meta));
- ASSERT(!erts_is_call_break(p, session, 1, &ep->info, call_time));
- ASSERT(!erts_is_call_break(p, session, 0, &ep->info, call_memory));
- }
+ if (erts_is_trace_break(session, &ep->info, ms, 0)) {
+ return FUNC_TRACE_GLOBAL_TRACE;
+ }
+
+ ASSERT(!erts_is_trace_break(session, &ep->info, ms, 1));
+ ASSERT(!erts_is_mtrace_break(session, &ep->info, ms_meta, tracer_pid_meta));
+ ASSERT(!erts_is_call_break(p, session, 1, &ep->info, call_time));
+ ASSERT(!erts_is_call_break(p, session, 0, &ep->info, call_memory));
+ }
+ }
}
/* OK, now look for breakpoint tracing */
if ((ci = erts_find_local_func(mfa)) != NULL) {
- int r = 0;
- if (erts_is_trace_break(session, ci, ms, 1))
- r |= FUNC_TRACE_LOCAL_TRACE;
- if (erts_is_mtrace_break(session, ci, ms_meta, tracer_pid_meta))
- r |= FUNC_TRACE_META_TRACE;
- if (erts_is_count_break(session, ci, count))
- r |= FUNC_TRACE_COUNT_TRACE;
- if (erts_is_call_break(p, session, 1, ci, call_time))
- r |= FUNC_TRACE_TIME_TRACE;
- if (erts_is_call_break(p, session, 0, ci, call_memory))
- r |= FUNC_TRACE_MEMORY_TRACE;
+ int got = 0;
+
+ if ((want & FUNC_TRACE_LOCAL_TRACE) && erts_is_trace_break(session, ci, ms, 1)) {
+ got |= FUNC_TRACE_LOCAL_TRACE;
+ }
+ if ((want & FUNC_TRACE_META_TRACE) && erts_is_mtrace_break(session, ci, ms_meta, tracer_pid_meta)) {
+ got |= FUNC_TRACE_META_TRACE;
+ }
+ if ((want & FUNC_TRACE_COUNT_TRACE) && erts_is_count_break(session, ci, count)) {
+ got |= FUNC_TRACE_COUNT_TRACE;
+ }
+ if ((want & FUNC_TRACE_TIME_TRACE) && erts_is_call_break(p, session, 1, ci, call_time)) {
+ got |= FUNC_TRACE_TIME_TRACE;
+ }
+ if ((want & FUNC_TRACE_MEMORY_TRACE) && erts_is_call_break(p, session, 0, ci, call_memory)) {
+ got |= FUNC_TRACE_MEMORY_TRACE;
+ }
- return r ? r : FUNC_TRACE_UNTRACED;
+ return got ? got : FUNC_TRACE_UNTRACED;
}
return FUNC_TRACE_NOEXIST;
}
@@ -1912,14 +1922,14 @@ trace_info_func(Process* p, ErtsTraceSession* session,
Eterm* hp;
ErtsCodeMFA mfa;
Binary *ms = NULL, *ms_meta = NULL;
- Uint count = 0;
+ Uint call_count = 0;
Eterm traced = am_false;
Eterm match_spec = am_false;
Eterm retval = am_false;
ErtsTracer meta = erts_tracer_nil;
Eterm call_time = NIL;
Eterm call_memory = NIL;
- int r;
+ int want, got;
ASSERT(session);
@@ -1927,22 +1937,50 @@ trace_info_func(Process* p, ErtsTraceSession* session,
goto error;
}
- if (key == am_call_time || key == am_call_memory || key == am_all) {
+ switch (key) {
+ case am_traced:
+ case am_match_spec:
+ want = FUNC_TRACE_GLOBAL_TRACE | FUNC_TRACE_LOCAL_TRACE;
+ break;
+ case am_meta:
+ case am_meta_match_spec:
+ want = FUNC_TRACE_META_TRACE;
+ break;
+ case am_call_count:
+ want = FUNC_TRACE_COUNT_TRACE;
+ break;
+ case am_call_time:
+ want = FUNC_TRACE_TIME_TRACE;
+ break;
+ case am_call_memory:
+ want = FUNC_TRACE_MEMORY_TRACE;
+ break;
+ case am_all:
+ want = FUNC_TRACE_GLOBAL_TRACE | FUNC_TRACE_LOCAL_TRACE
+ | FUNC_TRACE_META_TRACE | FUNC_TRACE_COUNT_TRACE
+ | FUNC_TRACE_TIME_TRACE | FUNC_TRACE_MEMORY_TRACE;
+ break;
+ default:
+ goto error;
+ }
+
+
+ if (want & (FUNC_TRACE_TIME_TRACE | FUNC_TRACE_MEMORY_TRACE)) {
erts_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
erts_thr_progress_block();
erts_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
erts_mtx_lock(&erts_dirty_bp_ix_mtx);
- r = function_is_traced(p, session, &mfa, &ms, &ms_meta, &meta, &count,
- &call_time, &call_memory);
+ got = function_is_traced(p, session, &mfa, want, &ms, &ms_meta, &meta,
+ &call_count, &call_time, &call_memory);
erts_mtx_unlock(&erts_dirty_bp_ix_mtx);
- if ( (key == am_call_time) || (key == am_call_memory) || (key == am_all)) {
- erts_thr_progress_unblock();
+ if (want & (FUNC_TRACE_TIME_TRACE | FUNC_TRACE_MEMORY_TRACE)) {
+ erts_thr_progress_unblock();
}
- switch (r) {
+ switch (got) {
case FUNC_TRACE_NOEXIST:
hp = HAlloc(p, 3);
return TUPLE2(hp, key, am_undefined);
@@ -1954,7 +1992,7 @@ trace_info_func(Process* p, ErtsTraceSession* session,
match_spec = NIL; /* Fix up later if it's asked for*/
break;
default:
- if (r & FUNC_TRACE_LOCAL_TRACE) {
+ if (got & FUNC_TRACE_LOCAL_TRACE) {
traced = am_local;
match_spec = NIL; /* Fix up later if it's asked for*/
}
@@ -1979,7 +2017,7 @@ trace_info_func(Process* p, ErtsTraceSession* session,
retval = NIL;
break;
case am_meta_match_spec:
- if (r & FUNC_TRACE_META_TRACE) {
+ if (got & FUNC_TRACE_META_TRACE) {
if (ms_meta) {
retval = MatchSetGetSource(ms_meta);
retval = copy_object(retval, p);
@@ -1989,23 +2027,23 @@ trace_info_func(Process* p, ErtsTraceSession* session,
}
break;
case am_call_count:
- if (r & FUNC_TRACE_COUNT_TRACE) {
- retval = erts_make_integer(count, p);
+ if (got & FUNC_TRACE_COUNT_TRACE) {
+ retval = erts_make_integer(call_count, p);
}
break;
case am_call_time:
- if (r & FUNC_TRACE_TIME_TRACE) {
+ if (got & FUNC_TRACE_TIME_TRACE) {
retval = call_time;
}
break;
case am_call_memory:
- if (r & FUNC_TRACE_MEMORY_TRACE) {
+ if (got & FUNC_TRACE_MEMORY_TRACE) {
retval = call_memory;
}
break;
case am_all: {
Eterm match_spec_meta = am_false;
- Eterm call_count = am_false;
+ Eterm call_count_term = am_false;
Eterm t, m;
/* ToDo: Rewrite this to loop and reuse the above cases */
@@ -2014,20 +2052,20 @@ trace_info_func(Process* p, ErtsTraceSession* session,
match_spec = MatchSetGetSource(ms);
match_spec = copy_object(match_spec, p);
}
- if (r & FUNC_TRACE_META_TRACE) {
+ if (got & FUNC_TRACE_META_TRACE) {
if (ms_meta) {
match_spec_meta = MatchSetGetSource(ms_meta);
match_spec_meta = copy_object(match_spec_meta, p);
} else
match_spec_meta = NIL;
}
- if (r & FUNC_TRACE_COUNT_TRACE) {
- call_count = erts_make_integer(count, p);
+ if (got & FUNC_TRACE_COUNT_TRACE) {
+ call_count_term = erts_make_integer(call_count, p);
}
- if (!(r & FUNC_TRACE_TIME_TRACE)) {
+ if (!(got & FUNC_TRACE_TIME_TRACE)) {
call_time = am_false;
}
- if (!(r & FUNC_TRACE_MEMORY_TRACE)) {
+ if (!(got & FUNC_TRACE_MEMORY_TRACE)) {
call_memory = am_false;
}
@@ -2035,7 +2073,7 @@ trace_info_func(Process* p, ErtsTraceSession* session,
hp = HAlloc(p, (3+2)*7);
retval = NIL;
- t = TUPLE2(hp, am_call_count, call_count); hp += 3;
+ t = TUPLE2(hp, am_call_count, call_count_term); hp += 3;
retval = CONS(hp, t, retval); hp += 2;
t = TUPLE2(hp, am_call_time, call_time); hp += 3;
retval = CONS(hp, t, retval); hp += 2;
--
2.51.0