RFR: 8334866: Improve Speed of ElfDecoder source search [v6]

Christian Hagedorn chagedorn at openjdk.org
Mon Oct 27 10:07:27 UTC 2025


On Fri, 24 Oct 2025 17:38:35 GMT, Kerem Kat <krk at openjdk.org> wrote:

>> Right now, looking up source file and line number info is slow because we do a full linear scan of the `.debug_aranges` section for every single call. This can be a major bottleneck on large binaries, especially during frequent native stack walking, e.g. while writing an hs_err.
>> 
>> This change fixes that by caching the address ranges on the first lookup, and keeping it in memory for the lifetime of the `DwarfFile` object.
>> 
>> All subsequent lookups on that object now use a binary search instead of the slow linear scan. If caching fails for any reason, it just falls back to the old method.
>
> Kerem Kat has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Fix comments, delete copy ctor

Thanks for the updates and sharing some numbers! 

> Benchmark of PrintAssembly before/after PR, on a noisy intel laptop:

Can you show me where we are calling the DWARF parser when running with `-XX:+PrintAssembly`? Running without `-Xbatch` means that we sometimes compile more and sometimes less which will produce different sized outputs and thus quite some variance.

> Benchmarking an arbitrary test from TestDwarf.java, on a noisy laptop
[...]
    1.02 ± 0.03 times faster than <fastdebug-no-cache>
The test finishes ~35 ms faster with cache.

I hoped for some bigger improvement but still counts even when it's small.

I have some more comments and suggestions.

src/hotspot/share/utilities/elfFile.cpp line 761:

> 759:     }
> 760: 
> 761:     // Read all address descriptors for this set

Suggestion:

    // Read all address descriptors for this set into the cache.

src/hotspot/share/utilities/elfFile.cpp line 785:

> 783:           set_header._debug_info_offset
> 784:         );
> 785:         _cache._count++;

You do a lot of delegation to `_cache`. This suggests that it could be part of the cache class itself. How about having `add_entry()` with a `grow()` method there?

src/hotspot/share/utilities/elfFile.cpp line 801:

> 799:       _cache._capacity = _cache._count;
> 800:     }
> 801:   }

Why do we need this? Can you add a comment?

src/hotspot/share/utilities/elfFile.cpp line 803:

> 801:   }
> 802:   _cache._initialized = true;
> 803:   DWARF_LOG_INFO("Built aranges cache for '%s' with %zu entries", this->_dwarf_file->filepath(), _cache._count);

Suggestion:

  DWARF_LOG_INFO("Built .debug_aranges cache for '%s' with %zu entries", this->_dwarf_file->filepath(), _cache._count);

src/hotspot/share/utilities/elfFile.cpp line 812:

> 810: // This process is described in section 6.1.2 of the DWARF 4 spec.
> 811: bool DwarfFile::DebugAranges::find_compilation_unit_offset(const uint32_t offset_in_library, uint32_t* compilation_unit_offset) {
> 812:   switch(ensure_cached()) {

Suggestion:

  switch (ensure_cached()) {

src/hotspot/share/utilities/elfFile.hpp line 207:

> 205: #ifdef ASSERT
> 206:   const char* filepath() const { return _filepath; }
> 207: #endif

For one-liners, you could use `DEBUG_ONLY()`:

Suggestion:

  DEBUG_ONLY(const char* filepath() const { return _filepath; })

src/hotspot/share/utilities/elfFile.hpp line 442:

> 440:   };
> 441: 
> 442:   struct ArangesEntry {

You could add a comment here that this is an entry in the `ArangesCache`.

src/hotspot/share/utilities/elfFile.hpp line 452:

> 450:   };
> 451: 
> 452:   class DebugAranges;

Can you move this forward declaration to the top of the file where we already have some other forward declarations?

src/hotspot/share/utilities/elfFile.hpp line 456:

> 454:   // Cache for .debug_aranges to enable binary search for address lookup.
> 455:   // DebugAranges uses this cache to resolve the compilation_unit_offset, rather than doing a linear scan on the files
> 456:   // in each invocation of DebugAranges::find_compilation_unit_offset

Suggestion:

  // in each invocation of DebugAranges::find_compilation_unit_offset.

src/hotspot/share/utilities/elfFile.hpp line 466:

> 464:     bool _failed;
> 465: 
> 466:    public:

`public` is already implied here.

Suggestion:

src/hotspot/share/utilities/elfFile.hpp line 547:

> 545:       VALID,
> 546: 
> 547:       // Cache is unusable, fallback to linear scan.

Can you either add a comment here when a cache becomes unusable or add a reference where this is explained further?
Suggestion:

      // Cache is unusable, fall back to linear scan.

src/hotspot/share/utilities/elfFile.hpp line 568:

> 566:                               const AddressDescriptor& descriptor);
> 567:    public:
> 568:     DebugAranges(DwarfFile* dwarf_file) : _dwarf_file(dwarf_file), _cache(), _reader(dwarf_file->fd()),

Is `_cache()` really needed and not done implicitly?

src/hotspot/share/utilities/elfFile.hpp line 572:

> 570:     bool find_compilation_unit_offset(uint32_t offset_in_library, uint32_t* compilation_unit_offset);
> 571: 
> 572:     // Build cache of all address ranges for binary search in a single pass

For consistency with other method comments for the DWARF processing, I suggest to move the comment to the definition in the source file.

-------------

PR Review: https://git.openjdk.org/jdk/pull/27337#pullrequestreview-3382306631
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464932415
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464953428
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464901313
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464900663
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464824414
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464927421
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464804216
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464801391
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464802820
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464805799
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464811428
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464815856
PR Review Comment: https://git.openjdk.org/jdk/pull/27337#discussion_r2464818635


More information about the hotspot-dev mailing list