fixed memory leak PCLStatsShutdown event · GameTechDev/PresentMon@8e303cc (original) (raw)
`@@ -2365,8 +2365,8 @@ void PMTraceConsumer::CompletePresent(std::shared_ptr const& p)
`
2365
2365
`static_cast(appFrameId - it->second.FrameId) >= 10) {
`
2366
2366
`// Remove the app frame data if the app frame id is too old
`
2367
2367
` it = mAppTimingDataByAppFrameId.erase(it); // Erase and move to the next element
`
2368
``
`-
} else if (appFrameId == 0 && it->second.ProcessId == processId &&
`
2369
``
`-
it->second.AssignedToPresent == false && it->second.AppPresentStartTime != 0 &&
`
``
2368
`+
} else if (appFrameId == 0 && it->second.ProcessId == processId &&
`
``
2369
`+
it->second.AssignedToPresent == false && it->second.AppPresentStartTime != 0 &&
`
2370
2370
` presentStartTime >= it->second.AppPresentStartTime &&
`
2371
2371
` presentStartTime - it->second.AppPresentStartTime >= mDeferralTimeLimit) {
`
2372
2372
`// Remove app frame data if the app present start time is too old
`
`@@ -2376,6 +2376,47 @@ void PMTraceConsumer::CompletePresent(std::shared_ptr const& p)
`
2376
2376
` ++it; // Move to the next element
`
2377
2377
` }
`
2378
2378
` }
`
``
2379
+
``
2380
`+
// Prune out old PC Latency timing data to prevent memory leaks.
`
``
2381
`+
// This is critical because PCL data accumulates for every frame and the
`
``
2382
`+
// PCLStatsShutdown event (the only other cleanup mechanism) is app-controlled.
`
``
2383
`+
if (mTrackPcLatency) {
`
``
2384
`+
auto pclFrameId = present->PclFrameId;
`
``
2385
`+
for (auto it = mPclTimingDataByPclFrameId.begin(); it != mPclTimingDataByPclFrameId.end();) {
`
``
2386
`+
if (it->first.second == processId) {
`
``
2387
`+
// For entries from this process:
`
``
2388
`+
// 1. Remove if assigned and frame ID is too old (10+ frames behind)
`
``
2389
`+
// 2. Remove if timestamp is too old (stale data - assigned or not)
`
``
2390
`+
bool shouldRemove = false;
`
``
2391
+
``
2392
`+
// Get the best available timestamp for this entry
`
``
2393
`+
uint64_t timingValue = mUsingOutOfBoundPresentStart
`
``
2394
`+
? it->second.PclOutOfBandPresentStartTime
`
``
2395
`+
: it->second.PclPresentStartTime;
`
``
2396
`+
if (timingValue == 0) {
`
``
2397
`+
timingValue = it->second.PclSimStartTime;
`
``
2398
`+
}
`
``
2399
+
``
2400
`+
if (pclFrameId != 0 && it->second.AssignedToPresent &&
`
``
2401
`+
static_cast(pclFrameId - it->second.FrameId) >= 10) {
`
``
2402
`+
// Remove assigned PCL data if frame id is too old
`
``
2403
`+
shouldRemove = true;
`
``
2404
`+
} else if (timingValue != 0 && presentStartTime >= timingValue &&
`
``
2405
`+
presentStartTime - timingValue >= mDeferralTimeLimit) {
`
``
2406
`+
// Remove PCL data (assigned or not) if timestamp is too old
`
``
2407
`+
shouldRemove = true;
`
``
2408
`+
}
`
``
2409
+
``
2410
`+
if (shouldRemove) {
`
``
2411
`+
it = mPclTimingDataByPclFrameId.erase(it);
`
``
2412
`+
} else {
`
``
2413
`+
++it;
`
``
2414
`+
}
`
``
2415
`+
} else {
`
``
2416
`+
++it;
`
``
2417
`+
}
`
``
2418
`+
}
`
``
2419
`+
}
`
2379
2420
`}
`
2380
2421
``
2381
2422
`void PMTraceConsumer::UpdateReadyCount(bool useLock)
`
`@@ -2708,6 +2749,16 @@ void PMTraceConsumer::HandleProcessEvent(EVENT_RECORD* pEventRecord)
`
2708
2749
` event.ProcessId = desc[0].GetData();
`
2709
2750
` event.IsStartEvent = false;
`
2710
2751
``
``
2752
`+
// Clean up PC Latency tracking data for this process to prevent memory leaks.
`
``
2753
`+
// This is necessary because PCLStatsShutdown events are application-controlled
`
``
2754
`+
// and may not be sent if the app crashes or terminates abnormally.
`
``
2755
`+
if (mTrackPcLatency) {
`
``
2756
`+
std::erase_if(mPclTimingDataByPclFrameId, [&event](const auto& p) {
`
``
2757
`+
return p.first.second == event.ProcessId;
`
``
2758
`+
});
`
``
2759
`+
mLatestPingTimestampByProcessId.erase(event.ProcessId);
`
``
2760
`+
}
`
``
2761
+
2711
2762
`break;
`
2712
2763
` }
`
2713
2764
`default:
`
`@@ -2734,6 +2785,14 @@ void PMTraceConsumer::HandleProcessEvent(EVENT_RECORD* pEventRecord)
`
2734
2785
`mMetadata.GetEventData(pEventRecord, desc, _countof(desc));
`
2735
2786
` event.ProcessId = desc[0].GetData();
`
2736
2787
` event.IsStartEvent = false;
`
``
2788
+
``
2789
`+
// Clean up PC Latency tracking data for this process to prevent memory leaks.
`
``
2790
`+
if (mTrackPcLatency) {
`
``
2791
`+
std::erase_if(mPclTimingDataByPclFrameId, [&event](const auto& p) {
`
``
2792
`+
return p.first.second == event.ProcessId;
`
``
2793
`+
});
`
``
2794
`+
mLatestPingTimestampByProcessId.erase(event.ProcessId);
`
``
2795
`+
}
`
2737
2796
` } else {
`
2738
2797
`return;
`
2739
2798
` }
`