File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -69,6 +69,41 @@ async def a(n):
6969 stats = yappi .get_func_stats ()
7070 self .assert_traces_almost_equal (r1 , stats )
7171
72+ def test_mem_leak (self ):
73+ import gc
74+ import types
75+
76+ async def noop ():
77+ return
78+
79+ async def run_batch (n ):
80+ await asyncio .gather (* (noop () for _ in range (n )))
81+
82+ def exhausted_coroutines ():
83+ gc .collect ()
84+ return sum (
85+ 1
86+ for o in gc .get_objects ()
87+ if isinstance (o , types .CoroutineType ) and o .cr_frame is None
88+ )
89+
90+ batch_size = 1000
91+
92+ yappi .set_clock_type ("cpu" )
93+ yappi .start ()
94+ asyncio .get_event_loop ().run_until_complete (run_batch (batch_size ))
95+ yappi .stop ()
96+ yappi .clear_stats ()
97+ baseline = exhausted_coroutines ()
98+
99+ yappi .start ()
100+ asyncio .get_event_loop ().run_until_complete (run_batch (batch_size ))
101+ yappi .stop ()
102+ yappi .clear_stats ()
103+ after = exhausted_coroutines ()
104+
105+ self .assertLess (after - baseline , batch_size // 3 )
106+
72107 def test_basic_old_style (self ):
73108
74109 async def a ():
Original file line number Diff line number Diff line change @@ -225,17 +225,20 @@ int
225225IS_SUSPENDED (PyFrameObject * frame ) {
226226#if PY_VERSION_HEX >= 0x030B0000 // Python 3.11+
227227 PyGenObject * gen = (PyGenObject * )PyFrame_GetGenerator (frame );
228+ int suspended ;
228229 if (gen == NULL ) {
229230 return 0 ;
230231 }
231232#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION == 14
232233 unsigned char curr_op_code = (* frame -> f_frame -> instr_ptr ).op .code ;
233- return curr_op_code == YIELD_VALUE || curr_op_code == INSTRUMENTED_YIELD_VALUE ;
234+ suspended = curr_op_code == YIELD_VALUE || curr_op_code == INSTRUMENTED_YIELD_VALUE ;
234235#elif PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION == 13
235- return FRAME_STATE_SUSPENDED (gen -> gi_frame_state );
236+ suspended = FRAME_STATE_SUSPENDED (gen -> gi_frame_state );
236237#else
237- return gen -> gi_frame_state == FRAME_SUSPENDED ;
238+ suspended = gen -> gi_frame_state == FRAME_SUSPENDED ;
238239#endif
240+ Py_DECREF (gen );
241+ return suspended ;
239242#elif PY_VERSION_HEX >= 0x030A0000 // Python 3.10+
240243 return (frame -> f_state == FRAME_SUSPENDED );
241244#else
You can’t perform that action at this time.
0 commit comments