[PATCH] D69575: Improve module.pcm lock file performance on machines with high core counts

Ladd Van Tol via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 29 11:04:37 PDT 2019


Ladd created this revision.
Ladd added reviewers: doug.gregor, benlangmuir.
Ladd added a project: LLVM.
Herald added subscribers: llvm-commits, kristina, dexonsmith, hiraditya.
Ladd edited the summary of this revision.

When building a large Xcode project with multiple module dependencies, and mixed Objective-C & Swift, I observed a large number of clang processes stalling at zero CPU for 30+ seconds throughout the build. This was especially prevalent on my 18-core iMac Pro.

After some sampling, the major cause appears to be the lock file implementation for precompiled modules in the module cache. When the lock is heavily contended by multiple clang processes, the exponential backoff runs in lockstep, with some of the processes sleeping for 30+ seconds in order to acquire the file lock.

In the attached patch, I implemented a more aggressive polling mechanism that limits the sleep interval to a max of 500ms, and randomizes the wait time. I preserved a limited form of exponential backoff. I also updated the code to use cross-platform timing, thread sleep sleep, and random number capabilities available in C++11.

Additionally, for macOS, I implemented kevent support that skips the sleep-based polling of the lock file.

These two implementations perform similarly for my Xcode project (1M+ lines).

On iMac Pro (2.3 GHz Intel Xeon W, 18 core):

Xcode 11.1 bundled clang:

502.2 seconds (average of 5 runs)

Custom clang build with LockFileManager patch applied:

276.6 seconds (average of 5 runs)

This is a 1.82x speedup for this use case.

On MacBook Pro (4 core 3.1GHz Intel i7):

Xcode 11.1 bundled clang:

539.4 seconds (average of 2 runs)

Custom clang build with LockFileManager patch applied:

509.5 seconds (average of 2 runs)

As expected, machines with fewer cores benefit less from this change.

  Call graph:
      2992 Thread_393602   DispatchQueue_1: com.apple.main-thread  (serial)
        2992 start  (in libdyld.dylib) + 1  [0x7fff6a1683d5]
          2992 main  (in clang) + 297  [0x1097a1059]
            2992 driver_main(int, char const**)  (in clang) + 2803  [0x1097a5513]
              2992 cc1_main(llvm::ArrayRef<char const*>, char const*, void*)  (in clang) + 1608  [0x1097a7cc8]
                2992 clang::ExecuteCompilerInvocation(clang::CompilerInstance*)  (in clang) + 3299  [0x1097dace3]
                  2992 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&)  (in clang) + 509  [0x1097dcc1d]
                    2992 clang::FrontendAction::Execute()  (in clang) + 42  [0x109818b3a]
                      2992 clang::ParseAST(clang::Sema&, bool, bool)  (in clang) + 185  [0x10981b369]
                        2992 clang::Parser::ParseFirstTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&)  (in clang) + 37  [0x10983e9b5]
                          2992 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&)  (in clang) + 141  [0x10983ecfd]
                            2992 clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*)  (in clang) + 695  [0x10983f3b7]
                              2992 clang::Parser::ParseObjCAtDirectives(clang::Parser::ParsedAttributesWithRange&)  (in clang) + 637  [0x10a9be9bd]
                                2992 clang::Parser::ParseModuleImport(clang::SourceLocation)  (in clang) + 170  [0x10c4841ba]
                                  2992 clang::Parser::ParseModuleName(clang::SourceLocation, llvm::SmallVectorImpl<std::__1::pair<clang::IdentifierInfo*, clang::SourceLocation> >&, bool)  (in clang) + 503  [0x10c485267]
                                    2992 clang::Preprocessor::Lex(clang::Token&)  (in clang) + 316  [0x1098285cc]
                                      2992 clang::Preprocessor::LexAfterModuleImport(clang::Token&)  (in clang) + 690  [0x10cc7af62]
                                        2992 clang::CompilerInstance::loadModule(clang::SourceLocation, llvm::ArrayRef<std::__1::pair<clang::IdentifierInfo*, clang::SourceLocation> >, clang::Module::NameVisibilityKind, bool)  (in clang) + 7989  [0x10bba6535]
                                          2992 compileAndLoadModule(clang::CompilerInstance&, clang::SourceLocation, clang::SourceLocation, clang::Module*, llvm::StringRef)  (in clang) + 296  [0x10bba8318]
                                            2992 llvm::LockFileManager::waitForUnlock()  (in clang) + 91  [0x10b6953ab]
                                              2992 nanosleep  (in libsystem_c.dylib) + 199  [0x7fff6a22c914]
                                                2992 __semwait_signal  (in libsystem_kernel.dylib) + 10  [0x7fff6a2a0f32]




Repository:
  rL LLVM

https://reviews.llvm.org/D69575

Files:
  llvm/lib/Support/LockFileManager.cpp

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D69575.226935.patch
Type: text/x-patch
Size: 4881 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191029/e01b5ddd/attachment.bin>


More information about the llvm-commits mailing list