Skip to content

[PROF-14955] Skip expensive SymFromAddr for modules without PDB symbols#58

Draft
r1viollet wants to merge 1 commit into
mainfrom
r1viollet/cache-symbol-load-failures
Draft

[PROF-14955] Skip expensive SymFromAddr for modules without PDB symbols#58
r1viollet wants to merge 1 commit into
mainfrom
r1viollet/cache-symbol-load-failures

Conversation

@r1viollet

@r1viollet r1viollet commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

Description

Skip repeated expensive DbgHelp calls for modules without PDB symbols.

Motivation

CPU profile of the profiler showed SymFromAddr burning ~27% of CPU via:

SymFromAddr -> SymLoadModuleExW -> SymFindFileInPath -> GetSymLoadError (138ms flat)

SymFromAddr succeeds (returning export symbols for ntdll, kernel32, etc.) but internally re-attempts PDB loading on every call. With SYMOPT_DEFERRED_LOADS, DbgHelp loads and unloads module symbols on each invocation.

Changes

  1. Remove SYMOPT_DEFERRED_LOADS — symbols load once at SymInitialize instead of triggering expensive deferred loads on every SymFromAddr.
  2. Track per-module whether full symbols (PDB/DIA) are available. After the first SymFromAddr for a module, check SymType. If only exports, skip SymFromAddr for subsequent addresses in that module.
  3. Print dd-win-prof.dll timestamp in capture-pprof.ps1.
  4. Fix pre-existing ThreadList test crash (fake handles passed to ScopedHandleCloseHandle on garbage).

Testing

  • Built successfully on Windows
  • Existing tests pass
  • New test added: TestModuleLevelFailureCaching
  • Manually tested with capture-pprof

Checklist

  • Code follows existing style
  • Documentation updated (if needed)
  • No breaking changes (or clearly documented)

@datadog-prod-us1-4

This comment has been minimized.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a4922f08dd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/dd-win-prof/Symbolication.cpp Outdated
Comment on lines +168 to +172
// SymFromAddr failed - mark module as having failed symbol load to avoid expensive retries
if (moduleCacheKey != 0) {
auto it = _moduleCache.find(moduleCacheKey);
if (it != _moduleCache.end()) {
it->second.symbolLoadFailed = true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Cache only confirmed module-load failures

This marks the whole module as failed after any SymFromAddr miss, but a miss can be address-specific (for example an address in a gap/header region or otherwise outside any loaded symbol) while other addresses in the same module still resolve. Once this flag is set, the early return above skips SymFromAddr for every subsequent address in that module until RefreshModules, so one unsymbolizable frame can turn valid symbols for the rest of the module into empty function names. Please gate the cache on a confirmed module symbol-load failure (e.g. module state/GetLastError) rather than every lookup failure.

Useful? React with 👍 / 👎.

@r1viollet r1viollet changed the title [PROF-????] Cache module-level symbol load failures to avoid expensive retries [PROF-14955] Skip expensive SymFromAddr for modules without PDB symbols Jun 16, 2026
@r1viollet
r1viollet force-pushed the r1viollet/cache-symbol-load-failures branch 3 times, most recently from bb0e902 to 2ca0ad9 Compare June 17, 2026 09:27
CPU profile showed SymFromAddr burning ~27% of CPU time via:
  SymFromAddr -> SymLoadModuleExW -> SymFindFileInPath -> GetSymLoadError

SymFromAddr succeeds (returning export symbols for ntdll, kernel32,
etc.) but internally re-attempts PDB loading on every call.

Two fixes:
1. Remove SYMOPT_DEFERRED_LOADS so symbols load upfront at
   SymInitialize instead of triggering expensive deferred loads on
   every SymFromAddr.
2. Track per-module whether full symbols (PDB/DIA) are available.
   After the first successful SymFromAddr for a module, check SymType.
   If only exports, skip SymFromAddr for subsequent addresses.

The module-level flag is only set on SymFromAddr success (where
SymType is reliable). A per-address failure (gap/header region) does
not poison the module cache.
@r1viollet
r1viollet force-pushed the r1viollet/cache-symbol-load-failures branch from 2ca0ad9 to 3b7b7c9 Compare June 17, 2026 09:28
@r1viollet

Copy link
Copy Markdown
Collaborator Author

not a huge priority for now (as symbolication is not expected to be triggered on profiler side in many use cases)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant