Skip to content

llvm-cov export spends most of its time in skipOtherFiles #62079

Closed
@jonhoo

Description

@jonhoo

As part of digging into a performance issue in a tool built on top of llvm-cov (specifically, it calls llvm-cov export), I realized that llvm-cov export was taking upwards of 4s to run on a modestly-sized input. That is, it takes 4s to complete this invocation:

llvm-cov export some-binary --instr-profile some.profdata --format lcov > /dev/null

where some-binary is a Rust binary of about 370M and some.profdata is 4M. And, during this time, llvm-cov appears to be saturating a single core on my multi-core host.

I built llvm-cov from the source in main and ran it through perf and Valgrind, and an interesting picture emerged (Firefox profiler visualization). llvm-cov appears to be spending a majority of its time in

void FunctionRecordIterator::skipOtherFiles() {
while (Current != Records.end() && !Filename.empty() &&
Filename != Current->Filenames[0])
++Current;
if (Current == Records.end())
*this = FunctionRecordIterator();
}

The calls to that function appear to stem from this call in renderFile:

if (!ExportSummaryOnly && !SkipFunctions) {
renderFunctions(OS, Coverage.getCoveredFunctions(Filename));
}

Which is ultimately called from CoverageExporterLcov::renderRoot via renderFiles.

Valgrind appears to struggle to follow the full call-graph, but from what I can see, it appears that skipOtherFiles is called upwards of 650k times. It also appears to be the case that renderRoot is itself called 300k times (possibly by itself — the call graph is unclear). In other words, it's not clear that skipOtherFiles itself is the problem (although it is doing a linear search as part of an iterator if I read it correctly?); the problem may be in the number of times it gets called. Perhaps some caching of its results are warranted?

My lack of LLVM knowledge is preventing me from digging much further into this, but I'd be happy to run additional commands/instrument llvm-cov in whatever ways may be helpful to surface more information to track down the underlying issue.

In case it matters, I'm running on an AArch64 host.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions