Modules increased build times

Hi,

I ported a big third-party header library to C++20 modules. I expected a decrease in compilation time, as it must only compile once per project and not per translation unit. Instead, the build times increased. -ftime-report reports that half of the time is spent in reading modules. I tried to profile it and most of the time is spent in clang::ASTReader::ReadDeclRecord(unsigned int).

Is there any possibility to reduce or speed up the declaration lookup?

Thanks!

1 Like

This seems to be related: https://github.com/llvm/llvm-project/issues/60996

Update: -ftime-trace reports that most of the time is spent in WriteAst and not in reading modules.

The issue looks not related to [Modules] Disappointing O(n^2) scaling of compile times with modules and optimizations · Issue #60996 · llvm/llvm-project · GitHub, which tells the modular build is slow within optimization. But the problem the thread talks is not related to the middle end.

According to [C++20] [Modules] Part of the time trace information may miss in one phase compilation · Issue #60555 · llvm/llvm-project · GitHub, the information recorded from -ftime-trace may miss in one-phase style (We can find the information about one phase style here: Standard C++ Modules — Clang 17.0.0git documentation), so the main time consuming part may be incorrect.

I think it would be helpful to send this to github issue with the reproducer.

Apparently, in my Cmake project, both time trace files are found in my build folder.

Here is my worst file:

First phase (precompile, generate pcm):

Second phase (build object file):

In the coming days, I will make a minimal example to reproduce this.

1 Like

Further information:

As a test I created a file in my project which looks like this:

module;

#include <iostream>


export module test;
import really_big_module;


export {
    void hello() {
        std::court << "hello\n";
    }
}

The following flame graph came out:

Note that <iostream> is only used, to inflate the AST.

Maybe it would be possible to cache parts of clang::ASTWriter::GenerateNameLookupTable and speed up the AST reading. I don’t know anything about clang internals, so I can’t say how to best fix this issue.

I also created an issue that focuses on the AST reader: https://github.com/llvm/llvm-project/issues/61064

Here the test file looks like this:

export module b;
import really_big_module;

export namespace b {
    int b() {
        return 1;
    }
}

And the resulting flame graph of this file:

As you can see a lot of time is spent in clang::ASTReader::VisitFunctionDecl, despite not using any function of really_big_module.

1 Like

Thanks! It should be pretty helpful for us to improve it.

@ChuanqiXu thank you for your time!

I tried the patch at: [C++20] [Modules] Don't load declaration eagerly for named modules · llvm/llvm-project@af86957 · GitHub. It significantly reduced the time spent in Module Load, however WriteAst still takes the same time. I was unable to create a minimal reproducer that highlights this specific issue.

As a test, I ran this file through callgrind with and without import really_big_module:

module;

#include <iostream>

export module test;
import really_big_module;


export {
    void hello() {
        std::cout << "hello\n";
    }
}

The number of calls to ASTWriter::WriteDecl, ASTDeclWriter::Visit, and DeclContext::lookup stayed nearly the same. The most significant difference is that ASTReader::FindExternalVisibleDeclsByName gets called often when using import. I noticed that the call chains while reading the AST are deep. I tried to print the Declaration it visits by modifying the AST reader, however, I only got crashes.

I created a repo that highlights this issue, note this is neither minimal nor beautiful and only a bad port to C++ Modules, but it could help to find the root cause of this issue. Please notify me if there are problems building this.

I can’t run it.

It tells me that:

./vulkan/vulkan_core.h:8186:10: fatal error: 'vk_video/vulkan_video_codec_h264std.h' file not found

It would be better if you can reduce it further.

I pushed a reduction, now it only depends on iostream.

Let’s track the issue in: [C++20] [Modules] Writing PCM will be unexpectedly slow with additional import. · Issue #61447 · llvm/llvm-project · GitHub

1 Like