@@ -250,6 +250,25 @@ def collect(self, stack_frames, timestamps_us=None):
250250 self .interval = (times [- 1 ] - self .last_sample_time ) / self .sample_count
251251 self .last_sample_time = times [- 1 ]
252252
253+ # Process async tasks
254+ if stack_frames and hasattr (stack_frames [0 ], "awaited_by" ):
255+ for frames , thread_id , _ in self ._iter_async_frames (stack_frames ):
256+ frames = filter_internal_frames (frames )
257+ if not frames :
258+ continue
259+
260+ if thread_id not in self .threads :
261+ self .threads [thread_id ] = self ._create_thread (
262+ thread_id , False
263+ )
264+
265+ self ._record_stack_sample (
266+ self .threads [thread_id ], frames , thread_id , times , first_time
267+ )
268+
269+ self .sample_count += len (times )
270+ return
271+
253272 # Process threads
254273 for interpreter_info in stack_frames :
255274 for thread_info in interpreter_info .threads :
@@ -333,37 +352,43 @@ def collect(self, stack_frames, timestamps_us=None):
333352 if not frames :
334353 continue
335354
336- # Process stack once to get stack_index
337- stack_index = self ._process_stack (thread_data , frames )
338-
339- # Add samples with timestamps
340- thread_spill = thread_data ["_spill" ]
341- for t in times :
342- thread_spill .append_sample (stack_index , t )
343-
344- # Handle opcodes
345- if self .opcodes_enabled and frames :
346- leaf_frame = frames [0 ]
347- filename , location , funcname , opcode = leaf_frame
348- if isinstance (location , tuple ):
349- lineno , _ , col_offset , _ = location
350- else :
351- lineno = location
352- col_offset = - 1
353-
354- current_state = (opcode , lineno , col_offset , funcname , filename )
355-
356- if tid not in self .opcode_state :
357- self .opcode_state [tid ] = (* current_state , first_time )
358- elif self .opcode_state [tid ][:5 ] != current_state :
359- prev_opcode , prev_lineno , prev_col , prev_funcname , prev_filename , prev_start = self .opcode_state [tid ]
360- self ._add_opcode_interval_marker (
361- tid , prev_opcode , prev_lineno , prev_col , prev_funcname , prev_start , first_time
362- )
363- self .opcode_state [tid ] = (* current_state , first_time )
355+ self ._record_stack_sample (
356+ thread_data , frames , tid , times , first_time
357+ )
364358
365359 self .sample_count += len (times )
366360
361+ def _record_stack_sample (self , thread_data , frames , tid , times , first_time ):
362+ stack_index = self ._process_stack (thread_data , frames )
363+
364+ thread_spill = thread_data ["_spill" ]
365+ for t in times :
366+ thread_spill .append_sample (stack_index , t )
367+
368+ if self .opcodes_enabled and frames :
369+ leaf_frame = frames [0 ]
370+ filename , location , funcname , opcode = leaf_frame
371+ if isinstance (location , tuple ):
372+ lineno , _ , col_offset , _ = location
373+ else :
374+ lineno = location
375+ col_offset = - 1
376+
377+ current_state = (opcode , lineno , col_offset , funcname , filename )
378+
379+ if tid not in self .opcode_state :
380+ self .opcode_state [tid ] = (* current_state , first_time )
381+ elif self .opcode_state [tid ][:5 ] != current_state :
382+ (
383+ prev_opcode , prev_lineno , prev_col , prev_funcname ,
384+ prev_filename , prev_start
385+ ) = self .opcode_state [tid ]
386+ self ._add_opcode_interval_marker (
387+ tid , prev_opcode , prev_lineno , prev_col , prev_funcname ,
388+ prev_start , first_time
389+ )
390+ self .opcode_state [tid ] = (* current_state , first_time )
391+
367392 def _create_thread (self , tid , is_main_thread ):
368393 """Create a new thread structure with processed profile format."""
369394 if self .spill_dir is None :
0 commit comments