Fix missing weight due to JITted code#41
Conversation
There was a problem hiding this comment.
Pull request overview
This PR addresses missing CPU weight in the Functions pane when samples’ instruction pointers don’t resolve to any loaded module (common with JITted/unmapped code such as Java/Lua JIT or emulation scenarios). It introduces a synthetic module/function attribution path so those samples remain visible and navigable in the UI.
Changes:
- Add a synthetic
[Unknown Module]per profiled process and attribute unresolved stack frames to per-thread synthetic functions (named[JIT <ThreadName> (<ThreadId>) <StartModule>]). - Capture
Win32StartAddrfor threads from ETW so the synthetic function name can include the thread’s start module. - Keep
RawProfileData.imagesMap_alive after event processing so synthetic images can be added post-LoadingCompleted().
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/ProfileExplorerCore/Profile/ETW/ETWProfileDataProvider.cs |
Creates/uses synthetic unknown module state and attributes unresolved stack frames + PMC attribution to it. |
src/ProfileExplorerCore/Profile/ETW/ETWEventProcessor.cs |
Records Win32StartAddr on ProfileThread from ETW thread start events. |
src/ProfileExplorerCore/Profile/Data/RawProfileModel.cs |
Adds Win32StartAddr to ProfileThread protobuf model. |
src/ProfileExplorerCore/Profile/Data/RawProfileData.cs |
Stops clearing imagesMap_ during LoadingCompleted() to allow adding synthetic images after ETW processing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Pull request was converted to draft
c32b148 to
be58ecc
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
src/ProfileExplorerCore/Profile/ETW/ETWProfileDataProvider.cs:1545
- When a PMC event maps to the synthetic unknown module, this still calls
GetModuleBuilder(...), which can be relatively expensive and will always early-exit later due to missing debug info. For traces with lots of unmapped/JIT PMC samples, this becomes avoidable overhead. Consider short-circuiting whenframeImage.ModuleName == "[Unknown Module]"(orframeImage == unknownModuleImage_) so only module-level counters are recorded without creating a module builder.
if (frameImage != null) {
profileData_.AddModuleCounter(frameImage.ModuleName, counter.CounterId, 1);
var profileModuleBuilder = GetModuleBuilder(rawProfile, frameImage, context.ProcessId, symbolSettings);
if (profileModuleBuilder == null) {
continue;
}
if (!profileModuleBuilder.HasDebugInfo) {
continue;
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
previously when there was JITted code (either from e.g., Java, Lua, or from Prism emulation of x64 exe on arm64 device, the cpu time would be missing function pane, as discussed in profile-explorer/issues/31
Now, shows up as something like:

Tested on traces containing toy .EXEs with Java JIT, Lua JIT, and x64 .EXE running under emulation on an Arm64 device. The naming scheme is [JIT () ], where StartModule is the module containing the thread's entry point, and ThreadName is the OS-assigned name of the thread where unmapped samples were observed. These names reflect the host thread identity, not the names of individual JITted functions being executed.