clang scan deps
play

clang-scan-deps Fast Dependency Scanning For Explicit Modules - PowerPoint PPT Presentation

clang-scan-deps Fast Dependency Scanning For Explicit Modules Alex Lorenz, Michael Spencer, Apple LLVM Developers Meeting, Brussels, Belgium, April 2019 1 Clang Modules Dependency Scanning Fast Dependency Scanning


  1. clang-scan-deps • • Fast Dependency Scanning For Explicit Modules Alex Lorenz, Michael Spencer, Apple LLVM Developers’ Meeting, Brussels, Belgium, April 2019 � 1

  2. • Clang Modules • Dependency Scanning • Fast Dependency Scanning • Dependency Extraction • Future Work � 2

  3. Clang Modules • Replace the textual preprocessor inclusions with an import of an AST • Widely used in SDKs shipped with Xcode • Implicit modules: Clang builds modules as they’re included • Users don’t have to specify modular dependencies • Requires a build system in the compiler 😬 � 3

  4. Compiler Discovered Build System Known Implicit Modules A.cpp B.cpp C.cpp D.cpp � 4

  5. Compiler Discovered Build System Known Implicit Modules Transforms A.cpp B.cpp C.cpp D.cpp � 5

  6. Implicit Modules Module Maps module LLVM_Transforms { requires cplusplus umbrella "Transforms" module * { export * } } � 6

  7. Compiler Discovered Build System Known Implicit Modules Transforms A.cpp B.cpp C.cpp D.cpp � 7

  8. Compiler Discovered Build System Known Implicit Modules Transforms A.cpp B.cpp C.cpp D.cpp � 8

  9. Compiler Discovered Build System Known Implicit Modules Analysis Analysis Transforms A.cpp B.cpp C.cpp D.cpp � 9

  10. Compiler Discovered Build System Known Implicit Modules Analysis Transforms A.cpp B.cpp C.cpp D.cpp � 10

  11. Compiler Discovered Build System Known Implicit Modules IR Analysis Transforms A.cpp B.cpp C.cpp D.cpp � 11

  12. Compiler Discovered Build System Known Implicit Modules IR Analysis Transforms A.cpp B.cpp C.cpp D.cpp � 12

  13. Compiler Discovered Build System Known Implicit Modules IR Analysis Transforms A.cpp B.cpp C.cpp D.cpp E.cpp -DFOO � 13

  14. Compiler Discovered Build System Known Implicit Modules IR Analysis Transforms Transforms A.cpp B.cpp C.cpp D.cpp E.cpp -DFOO � 14

  15. Compiler Discovered Build System Known Implicit Modules IR Analysis Analysis Transforms Transforms A.cpp B.cpp C.cpp D.cpp E.cpp -DFOO � 15

  16. Compiler Discovered Build System Known Implicit Modules ☹ IR IR Analysis Analysis Transforms Transforms A.cpp B.cpp C.cpp D.cpp E.cpp -DFOO � 16

  17. Compiler Discovered Build System Known Explicit Modules IR IR IR Analysis Analysis Transforms Transforms Transforms A.cpp B.cpp C.cpp D.cpp E.cpp -DFOO � 17

  18. Explicit Clang Modules • Better model: knowing modular dependencies before compiling • Allow more robust and reproducible builds • Faster builds 🏏 • Constraint: users shouldn’t have to specify modular dependencies • Problem: which modules are needed? • Solution: dependency discovery build phase for a build target � 18

  19. • Clang Modules • Dependency Scanning • Fast Dependency Scanning • Dependency Extraction • Future Work � 19

  20. Canonical Dependency Scanning Phase • Preprocess all translation units of a build target • Write out included files into a .d • clang -cc1 -Eonly -MT —dependency-file foo.d foo.c • How fast is the preprocessor? � 20

  21. Clang and LLVM sources: preprocessing time on an 18-Core iMac Pro 60 Preprocessing Time 45 Time (seconds) 30 15 0 6 12 18 24 30 36 Number Of Workers 21 �

  22. Clang and LLVM sources: the 12 workers scenario 60 Preprocessing Time 45 Time (seconds) 30 15 0 6 12 18 24 30 36 Number Of Workers � 22

  23. Clang and LLVM sources: the 12 workers scenario 60 Preprocessing Time 45 31 seconds to preprocess Time (seconds) 31 seconds to preprocess 31 seconds to preprocess 30 15 👏 Not fast enough for every build! 0 6 12 18 24 30 36 Number Of Workers � 23

  24. • Clang Modules • Dependency Scanning • Fast Dependency Scanning • Dependency Extraction • Future Work � 24

  25. What Does The Preprocessor Do? #ifndef HEADER_FILE #define HEADER_FILE Lex tokens… #include “Compiler.h” Evaluate #ifndef & #define // Clang is an awesome tool! Lex more tokens… class Clang: public Compiler { public: Include “Compiler.h” void buildAllCode(); #ifndef NDEBUG Lex more tokens… void dump(); Lex even more tokens 😬 #endif }; #endif � 25

  26. Reducing Preprocessor Workload #ifndef HEADER_FILE #define HEADER_FILE #include “Compiler.h” // Clang is an awesome tool! class Clang: public Compiler { Dependencies aren’t affected by these tokens 31 seconds to preprocess public: 31 seconds to preprocess void buildAllCode(); #ifndef NDEBUG void dump(); #endif }; #endif � 26

  27. Reducing Preprocessor Workload #ifndef HEADER_FILE #define HEADER_FILE #include “Compiler.h” // Clang is an awesome tool! class Clang: public Compiler { Dependencies aren’t affected by these tokens 31 seconds to preprocess public: 31 seconds to preprocess void buildAllCode(); #ifndefdNDEBUG void dump(); #endif }; #endif � 27

  28. Source Minimization #ifndef HEADER_FILE #define HEADER_FILE #include “Compiler.h” #endif � 28

  29. Source Minimization 💢 Keep directives that may affect dependency list #ifndef HEADER_FILE Strip everything else #define HEADER_FILE #include “Compiler.h” Context free: source reused in any compilation #endif � 29

  30. Clang and LLVM sources: 30% faster preprocessing 60 Preprocessing Time Minimized Source Preprocessing Time 45 Time (seconds) 30 15 0 6 12 18 24 30 36 Number Of Workers � 30

  31. Problem: Clang Invocations Preprocess Preprocess Parallel invocations do redundant work #include “Test.h” Read the same file twice #include “Test.h” Minimize Source Minimize the same file twice Minimize Source Preprocess Preprocess � 31

  32. Introducing clang-scan-deps • Library and command line tool for dependency scanning • Tool currently accepts compilation database and emits dependencies • Runs preprocessor invocations in parallel • Efficient: Reads and minimizes a source file only once • one shared FileSystem with shared minimized file cache • one shared FileManager � 32

  33. Minimized File Cache • Maps from file name to cache entry • Shared by worker threads: lock required access the StringMap • High lock contention for many threads 5 One StringMap Time (seconds) 3.75 2.5 1.25 0 18 24 30 36 Number Of Workers 33 �

  34. Optimizing Minimized File Cache • Solution: Array of StringMap addressed by hash of file name 5 One StringMap Time (seconds) Nine StringMaps 3.75 2.5 1.25 0 18 24 30 36 Number Of Workers 34 �

  35. Preprocessor Block Skipping When this #ifdef is not taken… #ifdef NOT_TAKEN // Important comment The tokens inside it are lexed… #include “LexMeNot.h” Until the #elif is found #elif Took up to 10-15% of time in our profiles #include “IAmLexed.h” #endif � 35

  36. Optimizing Preprocessor Block Skipping When this #ifdef is not taken… #ifdef NOT_TAKEN // Important comment #include “LexMeNot.h” Skip to #elif : add offset to Lexer’s pointer #elif Offset computed when minimizing file #include “IAmLexed.h” #endif � 36

  37. Clang and LLVM sources: 5-10x faster dependency scanning 40 Preprocessing Time scan-deps Time 30 Time (seconds) 20 10 0 6 12 18 24 30 36 Number Of Workers � 37

  38. Things We Aren’t Going To Support #define AT_IMPORT @import AT_IMPORT Foundation; #define WHY(X) _##X ("clang module import X") WHY(Pragma); ➡ We want to disallow this behavior in Clang � 38

  39. Modular Dependencies • clang-scan-deps builds implicit modules with minimized files • For now still uses old implicit module build machinery • Dependencies are extracted from the fast implicit build � 39

  40. • Clang Modules • Dependency Scanning • Fast Dependency Scanning • Dependency Extraction • Future Work � 40

  41. Dependency Extraction IR.min Analysis.min Transforms.min A.cpp.min B.cpp.min C.cpp.min D.cpp.min � 41

  42. Dependency Extraction IR.min Analysis.min Transforms.min A.cpp.min B.cpp.min C.cpp.min D.cpp.min � 42

  43. Dependency Extraction IR.min Analysis.min Transforms.min A.cpp.min B.cpp.min C.cpp.min D.cpp.min � 43

  44. Dependency Extraction build LLVM_Transforms.pcm: cxx_explicit_module llvm/include/llvm/module.modulemap | LLVM_IR.pcm LLVM_Analysis.pcm std.pcm module_id = LLVM_Transforms moduledeps = -fmodule-file=LLVM_Config_Config.pcm -fmodule-file=std.pcm -fmodule-file=LLVM_IR.pcm -fmodule-file=LLVM_Analysis.pcm args = builds/release/bin/clang++ -cc1 -fmodules ...

  45. Initial Results - Scanning • Faster than modules -Eonly and -Eonly, but slower than scan-deps • Building modules takes time ☹ Modules -Eonly -Eonly 200 Modules scan-deps scan-deps Scan Time (seconds) 150 100 50 0 6 12 18 24 30 36 Number Of Workers � 45

  46. Initial Results - Scanning • Faster than modules -Eonly and -Eonly, but slower than scan-deps Modules -Eonly -Eonly 60 Modules scan-deps scan-deps Scan Time (seconds) 45 30 15 0 6 12 18 24 30 36 Number Of Workers � 46

  47. Initial Results - Scanning Modules -Eonly -Eonly 22 Modules scan-deps The cost of building modules during scanning scan-deps Scan Time (seconds) 16.5 11 5.5 0 6 12 18 24 30 36 Number Of Workers � 47

Recommend


More recommend