@@ -78,6 +78,13 @@ local breakpoints.
7878Things get a bit more involved in the JIT. See ` BeamAsm.md ` for more
7979details.
8080
81+ ### Trace sessions
82+
83+ Since OTP 27, isolated trace session can be dynamically created. Each trace
84+ session is represented by an instance of struct ` ErtsTraceSession ` . The old
85+ legacy session (kept for backward compatibility) is represented by the static
86+ instance ` erts_trace_session_0 ` .
87+
8188## Setting breakpoints
8289
8390### Introduction
@@ -88,29 +95,24 @@ was carried out in single threaded mode. Similar to code loading, this
8895can impose a severe problem for availability that grows with the
8996number of cores.
9097
91- In OTP R16, breakpoints are set in the code without blocking the VM.
98+ Since OTP R16, breakpoints are set in the code without blocking the VM.
9299Erlang processes may continue executing undisturbed in parallel during the
93100entire operation. The same base technique is used as for code loading. A
94101staging area of breakpoints is prepared and then made active with a single
95102atomic operation.
96103
97- ### Redesign of Breakpoint Wheel
104+ ### Breakpoints
98105
99- To make it easier to manage breakpoints without single threaded mode a
100- redesign of the breakpoint mechanism has been made. The old
101- "breakpoint wheel" data structure was a circular double-linked list of
102- breakpoints for each instrumented function. It was invented before the
103- SMP emulator. To support it in the SMP emulator, is was essentially
104- expanded to one breakpoint wheel per scheduler. As more breakpoint
105- types have been added, the implementation have become messy and hard
106- to understand and maintain .
106+ For call tracing, breakpoints are created and inserted in the ingress of each
107+ traced Erlang function. A pointer to the allocated struct ` GenericBp ` is
108+ inserted that holds all the data for all types of breakpoints. A bit-flag field
109+ is used to indicate what different type of break actions that are
110+ enabled. Struct ` GenericBp ` is session specific. If more than one trace session
111+ affects a function, one ` GenericBp ` instance is created for each session. They
112+ are linked together in a singly linked list that is traversed when the
113+ breakpoint is hit .
107114
108- In the new design the old wheel was dropped and instead replaced by
109- one struct (` GenericBp ` ) to hold the data for all types of breakpoints
110- for each instrumented function. A bit-flag field is used to indicate
111- what different type of break actions that are enabled.
112-
113- ### Same Same but Different
115+ ### Similar to Code Loading but Different
114116
115117Even though ` trace_pattern ` use the same technique as the non-blocking
116118code loading with replicated generations of data structures and an
@@ -290,6 +292,35 @@ tracing is that we insert the `op_i_generic_breakpoint` instruction
290292(with its pointer at offset -4) in the export entry rather than in the
291293code.
292294
295+ ### call_time and call_memory tracing
296+
297+ For profiling, ` call_time ` and/or ` call_memory ` tracing can be set for a function.
298+ This will measure the time/memory spent by a function. The measured
299+ time/memory is kept in individual counters for every call traced process
300+ calling that function. To ensure scalability, scheduler specific hash tables
301+ (` BpTimemTrace ` ) are used in the breakpoint to map the calling process pid to
302+ its time/memory counters.
303+
304+ Function ` trace:info ` is used to collect stats for ` call_time ` , ` call_memory `
305+ or both (` all ` ). It has to aggregate the counters from all those scheduler
306+ specific hash tables to build a list with one tuple with counters for each
307+ pid. This cannot be done safely while the hash tables may be concurrently
308+ updated by traced processes.
309+
310+ Since OTP 29, ` trace:info ` collects ` call_time ` and ` call_memory ` stats without
311+ blocking all schedulers from running. This is done by using the active and
312+ staging halves of the breakpoint. During normal operations both halves of the
313+ breakpoint refer to the same thread specific hash tables. To collect the stats
314+ safely, temporary hash tables are created to be used by traced calls happening
315+ during the call to ` trace:info ` . The temporary hash tables are being made active
316+ while the "real" hash tables are made inactive in the staging half. When the hash
317+ tables are inactive, they can be safely traversed. When done, the real
318+ tables are made active again. A final consolidation step is done to collect any
319+ stats from the temporary tables, delete them and make the two halves of the
320+ breakpoint identical again using the same real hash tables. Scheduling with
321+ thread progress is done between the switching to make sure the traversed hash
322+ tables are not being concurrently updated.
323+
293324### Future work
294325
295326We still go to single threaded mode when new code is loaded for a
0 commit comments