@@ -147,6 +147,7 @@ typedef struct {
147147 int memfd ;
148148#endif
149149 page_cache_entry_t pages [MAX_PAGES ];
150+ int page_cache_count ;
150151 Py_ssize_t page_size ;
151152} proc_handle_t ;
152153
@@ -185,14 +186,16 @@ _Py_RemoteDebug_FreePageCache(proc_handle_t *handle)
185186 handle -> pages [i ].data = NULL ;
186187 handle -> pages [i ].valid = 0 ;
187188 }
189+ handle -> page_cache_count = 0 ;
188190}
189191
190192UNUSED static void
191193_Py_RemoteDebug_ClearCache (proc_handle_t * handle )
192194{
193- for (int i = 0 ; i < MAX_PAGES ; i ++ ) {
195+ for (int i = 0 ; i < handle -> page_cache_count ; i ++ ) {
194196 handle -> pages [i ].valid = 0 ;
195197 }
198+ handle -> page_cache_count = 0 ;
196199}
197200
198201#if defined(__APPLE__ ) && defined(TARGET_OS_OSX ) && TARGET_OS_OSX
@@ -222,6 +225,7 @@ _Py_RemoteDebug_InitProcHandle(proc_handle_t *handle, pid_t pid) {
222225 handle -> memfd = -1 ;
223226#endif
224227 handle -> page_size = get_page_size ();
228+ handle -> page_cache_count = 0 ;
225229 for (int i = 0 ; i < MAX_PAGES ; i ++ ) {
226230 handle -> pages [i ].data = NULL ;
227231 handle -> pages [i ].valid = 0 ;
@@ -1287,42 +1291,41 @@ _Py_RemoteDebug_PagedReadRemoteMemory(proc_handle_t *handle,
12871291 return _Py_RemoteDebug_ReadRemoteMemory (handle , addr , size , out );
12881292 }
12891293
1290- // Search for valid cached page
1291- for (int i = 0 ; i < MAX_PAGES ; i ++ ) {
1294+ // Search only the pages used since the last clear. The cache is cleared
1295+ // between profiler samples, so entries are packed at the front.
1296+ for (int i = 0 ; i < handle -> page_cache_count ; i ++ ) {
12921297 page_cache_entry_t * entry = & handle -> pages [i ];
12931298 if (entry -> valid && entry -> page_addr == page_base ) {
12941299 memcpy (out , entry -> data + offset_in_page , size );
12951300 return 0 ;
12961301 }
12971302 }
12981303
1299- // Find reusable slot
1300- for ( int i = 0 ; i < MAX_PAGES ; i ++ ) {
1301- page_cache_entry_t * entry = & handle -> pages [ i ];
1302- if (! entry -> valid ) {
1304+ if ( handle -> page_cache_count < MAX_PAGES ) {
1305+ page_cache_entry_t * entry = & handle -> pages [ handle -> page_cache_count ];
1306+ if ( entry -> data == NULL ) {
1307+ entry -> data = PyMem_RawMalloc ( page_size );
13031308 if (entry -> data == NULL ) {
1304- entry -> data = PyMem_RawMalloc (page_size );
1305- if (entry -> data == NULL ) {
1306- PyErr_NoMemory ();
1307- _set_debug_exception_cause (PyExc_MemoryError ,
1308- "Cannot allocate %zu bytes for page cache entry "
1309- "during read from PID %d at address 0x%lx" ,
1310- page_size , handle -> pid , addr );
1311- return -1 ;
1312- }
1313- }
1314-
1315- if (_Py_RemoteDebug_ReadRemoteMemory (handle , page_base , page_size , entry -> data ) < 0 ) {
1316- // Try to just copy the exact amount as a fallback
1317- PyErr_Clear ();
1318- goto fallback ;
1309+ PyErr_NoMemory ();
1310+ _set_debug_exception_cause (PyExc_MemoryError ,
1311+ "Cannot allocate %zu bytes for page cache entry "
1312+ "during read from PID %d at address 0x%lx" ,
1313+ page_size , handle -> pid , addr );
1314+ return -1 ;
13191315 }
1316+ }
13201317
1321- entry -> page_addr = page_base ;
1322- entry -> valid = 1 ;
1323- memcpy ( out , entry -> data + offset_in_page , size );
1324- return 0 ;
1318+ if ( _Py_RemoteDebug_ReadRemoteMemory ( handle , page_base , page_size , entry -> data ) < 0 ) {
1319+ // Try to just copy the exact amount as a fallback
1320+ PyErr_Clear ( );
1321+ goto fallback ;
13251322 }
1323+
1324+ entry -> page_addr = page_base ;
1325+ entry -> valid = 1 ;
1326+ handle -> page_cache_count ++ ;
1327+ memcpy (out , entry -> data + offset_in_page , size );
1328+ return 0 ;
13261329 }
13271330
13281331fallback :
0 commit comments