Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: microsoft/perfview
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.2.4
Choose a base ref
...
head repository: microsoft/perfview
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v3.2.5
Choose a head ref
  • 7 commits
  • 19 files changed
  • 4 contributors

Commits on Jun 20, 2026

  1. Fix spurious BROKEN frames on musl-based Linux stacks

    On musl distros (e.g. Alpine) libc and the dynamic loader are combined
    into a single module named like ld-musl-x86_64.so.1, where threads start.
    Treat it as a valid top frame so musl stacks aren't marked BROKEN, mirroring
    the existing glibc libc handling. Add an in-memory nettrace unit test.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    brianrob and Copilot committed Jun 20, 2026
    Configuration menu
    Copy the full SHA
    4239169 View commit details
    Browse the repository at this point in the history

Commits on Jun 24, 2026

  1. Fix spurious BROKEN frames on musl-based Linux stacks (#2437)

    ## Why
    
    Traces captured with one-collect on musl-based Linux distros (e.g.
    Alpine) show a large fraction of stacks marked BROKEN when opened in
    PerfView or TraceEvent. On a real Alpine trace, about 18% of samples
    were broken. The root cause is that thread base frames on musl live in
    the combined libc + dynamic loader module, named like
    `ld-musl-x86_64.so.1`, which `ReasonableTopFrame` did not recognize as a
    legitimate thread-start module. We already special-case glibc's `libc`
    for the same reason; musl was simply missing.
    
    ## What
    
    - `TraceEventStacks.cs`: In `ReasonableTopFrame`, treat any module whose
    name starts with `ld-musl-` (case-insensitive, so it covers `x86_64`,
    `aarch64`, etc.) as a valid top frame, mirroring the existing glibc
    `libc` handling. When matched, a stack rooted there is no longer wrapped
    in a BROKEN frame.
    
    - Added `Universal/MuslBrokenStackTests.cs`: a unit test that
    synthesizes a tiny in-memory V6 nettrace (no large trace binary added to
    the repo) containing a musl loader module, an ordinary library, and two
    cpu samples: one rooted in the musl module and one rooted in the
    ordinary library. It asserts the musl-rooted stack is not BROKEN while
    the ordinary-library-rooted stack still is, parameterized over both
    `ld-musl-x86_64.so.1` and `ld-musl-aarch64.so.1`.
    
    ## Validation
    
    - A throwaway TraceEvent-based console app run against the real Alpine
    trace confirmed broken stacks dropped from 18.4% to 3.7% (eliminating
    ~6,100 musl-rooted frames). The scratch app was not committed.
    - Confirmed the new test fails without the fix (musl stack marked
    BROKEN) and passes with it.
    - Full TraceEvent suite is green: 2272 passing on net8.0 and 2289 on
    net462, no regressions.
    
    ## Notes for reviewers
    
    The negative-case assertion (ordinary library still BROKEN) is
    intentional to guard against the match being too broad. The test writer
    emits a non-zero `syncTimeQPC` so iterating relative timestamps does not
    trip a Debug.Assert in `QPCTimeToRelMSec`; this is a test-harness detail
    only.
    brianrob authored Jun 24, 2026
    Configuration menu
    Copy the full SHA
    226c25a View commit details
    Browse the repository at this point in the history

Commits on Jul 13, 2026

  1. Fix InMemoryCircularBuffer merge failure with large CircularMB (#2439)

    When collecting with /InMemoryCircularBuffer and /CircularMB:N where N is
    larger than ~256, PerfView collection succeeds but the subsequent
    KernelTraceControl merge fails (e.g. CreateMergedTraceFile returns
    0x80280012), and the requested memory grows quadratically.
    
    The buffering-mode branch of GetProperties overwrote properties->BufferSize
    with m_CircularBufferMB. BufferSize is a per-buffer size in KB, so a megabyte
    value was being written into a kilobyte field. This made each ETW buffer far
    larger than the OS maximum buffer size, which the relogger later chokes on
    during merge, and it contradicted the MinimumBuffers computation on the line
    above (which divides by the 64 KB quantum). It also corrupted the Attach
    round-trip that reconstructs buffer settings when stopping the session.
    
    Remove the erroneous assignment so BufferSize stays at the per-buffer
    quantum (m_BufferQuantumKB) set earlier, matching the file-based and
    real-time paths. MinimumBuffers alone now sizes the in-memory pool, so
    (MinimumBuffers * BufferSize) == m_CircularBufferMB megabytes as intended.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    cincuranet and Copilot authored Jul 13, 2026
    Configuration menu
    Copy the full SHA
    36d9a6a View commit details
    Browse the repository at this point in the history

Commits on Jul 15, 2026

  1. Fix GC dynamic ETLX replay (#2440)

    PerfView 3.2.4 can throw `ArgumentOutOfRangeException` when GC Stats or
    Heap Analyzer replays `GC/CommittedUsage` events from ETLX. During
    conversion, `FixupData()` classifies the raw dynamic event and the ETLX
    persists the synthetic event ID, but the original dynamic payload
    envelope remains unchanged. On replay, the typed template therefore
    still needs to parse that envelope.
    
    This change refreshes the payload layout in `EventPayload` only when
    processing a `TraceLog`. Raw ETW and EventPipe dispatch continue using
    the payload prepared by `FixupData()`, avoiding redundant parsing.
    Fixed-offset `CommittedUsage` fields also return safe defaults for
    truncated payloads.
    
    Regression coverage includes valid ETLX replay without `FixupData()`,
    reused replay templates with distinct payloads, and malformed payload
    access through properties, `PayloadValues`, and `ToXml`.
    
    Fixes #2438
    brianrob authored Jul 15, 2026
    Configuration menu
    Copy the full SHA
    4bd9156 View commit details
    Browse the repository at this point in the history

Commits on Jul 16, 2026

  1. Enable W4 and warnings as errors for C++ projects (#2441)

    * Enable W4 and warnings as errors for C++ projects
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: 5b148be3-5dce-425e-b025-94eb7b8de1d5
    
    * Remove stale sampling debug code
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    Copilot-Session: 5b148be3-5dce-425e-b025-94eb7b8de1d5
    
    ---------
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    brianrob and Copilot authored Jul 16, 2026
    Configuration menu
    Copy the full SHA
    fea55d6 View commit details
    Browse the repository at this point in the history
  2. Configuration menu
    Copy the full SHA
    0d1fc7d View commit details
    Browse the repository at this point in the history

Commits on Jul 17, 2026

  1. Support embedded portable PDBs for managed symbol resolution (#2434)

    * Support embedded portable PDBs for managed symbol resolution
    
    Managed assemblies built with <DebugType>embedded</DebugType> carry their
    portable PDB inside the PE image rather than in a standalone .pdb file.
    Previously SymbolReader could not read these, so source/line lookup failed
    for such modules.
    
    Add the ability to open an embedded portable PDB:
    
    - SymbolReader.OpenEmbeddedPortablePdb reads the EmbeddedPortablePdb
      debug-directory entry from a module and returns a PortableSymbolModule.
      Results are cached under a key suffixed so they cannot collide with
      standalone-PDB cache entries.
    - SymbolReader.OpenSymbolFileForModuleFile is a module-oriented entry point
      that prefers a standalone PDB and falls back to an embedded portable PDB.
    - PortableSymbolModule gains a constructor that takes a
      MetadataReaderProvider (which owns its own backing memory).
    - TraceLog.OpenPdbForModuleFile falls back to the module's embedded portable
      PDB when the on-disk module matches the trace and no standalone PDB exists.
    
    Tests: add an EmbeddedPdbTestApp fixture (built with embedded PDBs) and
    cover the happy path, caching, not-embedded/missing-file cases, the
    module-oriented entry point (embedded and standalone), and the end-to-end
    TraceLog fallback path. All run cross-platform on net462 and net8.0.
    
    * Build embedded-PDB test fixture unoptimized for stable source lines
    
    In Release the C# compiler optimizes EmbeddedTarget.Add, shifting its first sequence point from the 'int sum = a + b;' line to the 'return' line, so the source-line assertions failed in the Release CI leg. Pin Optimize=false on the fixture so its emitted sequence points are stable regardless of the build configuration.
    
    * Remove test-only OpenSymbolFileForModuleFile wrapper
    
    Per PR review: this wrapper was called only from tests, and TraceLog.OpenPdbForModuleFile already provides the standalone-then-embedded fallback for the trace path. Removed it and its three dedicated tests, keeping OpenEmbeddedPortablePdb (the building block TraceLog uses).
    JeremyKuhne authored Jul 17, 2026
    Configuration menu
    Copy the full SHA
    0759c07 View commit details
    Browse the repository at this point in the history
Loading