Ted Kremenek | 797a247 | 2009-04-08 05:07:30 +0000 | [diff] [blame] | 1 | <html> |
| 2 | <head> |
| 3 | <title>Pretokenized Headers (PTH)</title> |
| 4 | <link type="text/css" rel="stylesheet" href="../menu.css" /> |
| 5 | <link type="text/css" rel="stylesheet" href="../content.css" /> |
| 6 | <style type="text/css"> |
| 7 | td { |
| 8 | vertical-align: top; |
| 9 | } |
| 10 | </style> |
| 11 | </head> |
| 12 | <body> |
| 13 | |
| 14 | <!--#include virtual="../menu.html.incl"--> |
| 15 | |
| 16 | <div id="content"> |
| 17 | <h1>Pretokenized Headers</h1> |
| 18 | |
| 19 | <p> <a href="http://en.wikipedia.org/wiki/Precompiled_header">Precompiled |
Chris Lattner | cdf59da | 2009-04-08 05:50:25 +0000 | [diff] [blame] | 20 | headers</a> are a general approach employed by many compilers to reduce |
| 21 | compilation time. The underlying motivation of the approach is that it is |
| 22 | common for the same (and often large) header files to be included by |
Ted Kremenek | 797a247 | 2009-04-08 05:07:30 +0000 | [diff] [blame] | 23 | multiple source files. Consequently, compile times can often be greatly improved |
| 24 | by caching some of the (redundant) work done by a compiler to process headers. |
Chris Lattner | cdf59da | 2009-04-08 05:50:25 +0000 | [diff] [blame] | 25 | Precompiled header files, which represent one of many ways to implement |
Ted Kremenek | 797a247 | 2009-04-08 05:07:30 +0000 | [diff] [blame] | 26 | this optimization, are literally files that represent an on-disk cache that |
| 27 | contains the vital information necessary to reduce some (or all) of the work |
| 28 | needed to process a corresponding header file. While details of precompiled |
| 29 | headers vary between compilers, precompiled headers have been shown to be a |
| 30 | highly effective at speeding up program compilation on systems with very large |
Chris Lattner | cdf59da | 2009-04-08 05:50:25 +0000 | [diff] [blame] | 31 | system headers (e.g., Mac OS/X).</p> |
Ted Kremenek | 797a247 | 2009-04-08 05:07:30 +0000 | [diff] [blame] | 32 | |
| 33 | <p>Clang supports an implementation of precompiled headers known as |
| 34 | <em>pre-tokenized headers</em> (PTH). Clang's pre-tokenized headers support most |
| 35 | of same interfaces as GCC's pre-compiled headers (as well as others) but are |
Chris Lattner | cdf59da | 2009-04-08 05:50:25 +0000 | [diff] [blame] | 36 | completely different in their implementation. This first describes the |
Ted Kremenek | 797a247 | 2009-04-08 05:07:30 +0000 | [diff] [blame] | 37 | interface for using PTH and then briefly elaborates on their design and |
| 38 | implementation.</p> |
| 39 | |
| 40 | |
| 41 | <h2>Using Pretokenized Headers (High-level Interface)</h2> |
| 42 | |
| 43 | <p>The high-level interface to generate a PTH file is the same as GCC's:</p> |
| 44 | |
| 45 | <pre> |
| 46 | $ gcc -x c-header test.h -o test.h.gch |
| 47 | $ clang -x c-header test.h -o test.h.pth |
| 48 | </pre> |
| 49 | |
| 50 | <p>A PTH file can then be used as a prefix header when a <tt>-include</tt> |
| 51 | option is passed to <tt>clang</tt>:</p> |
| 52 | |
| 53 | <pre> |
| 54 | $ clang -include test.h test.c -o test |
| 55 | </pre> |
| 56 | |
| 57 | <p>The <tt>clang</tt> driver will first check if a PTH file for <tt>test.h</tt> |
| 58 | is available; if so, the contents of <tt>test.h</tt> (and the files it includes) |
| 59 | will be processed from the PTH file. Otherwise, <tt>clang</tt> falls back to |
| 60 | directly processing the content of <tt>test.h</tt>. This mirrors the behavior of |
| 61 | GCC.</p> |
| 62 | |
| 63 | <p><b>NOTE:</b> <tt>clang</tt> does <em>not</em> automatically used PTH files |
| 64 | for headers that are directly included within a source file. For example:</p> |
| 65 | |
| 66 | <pre> |
| 67 | $ clang -x c-header test.h -o test.h.pth |
| 68 | $ cat test.c |
| 69 | #include "test.h" |
| 70 | $ clang test.c -o test |
| 71 | </pre> |
| 72 | |
| 73 | <p>In this example, <tt>clang</tt> will not automatically use the PTH file for |
| 74 | <tt>test.h</tt> since <tt>test.h</tt> was included directly in the source file |
| 75 | and not specified on the command line using <tt>-include</tt>.</p> |
| 76 | |
| 77 | <h2>Using Pretokenized Headers (Low-level Interface)</h2> |
| 78 | |
Chris Lattner | cdf59da | 2009-04-08 05:50:25 +0000 | [diff] [blame] | 79 | <p>The low-level Clang compiler tool, <tt>clang-cc</tt>, supports three command |
| 80 | line options for generating and using PTH files.<p> |
Ted Kremenek | 797a247 | 2009-04-08 05:07:30 +0000 | [diff] [blame] | 81 | |
| 82 | <p>To generate PTH files using <tt>clang-cc</tt>, use the option <tt>-emit-pth</tt>: |
| 83 | |
| 84 | <pre> |
| 85 | $ clang-cc test.h -emit-pth -o test.h.pth |
| 86 | </pre> |
| 87 | |
| 88 | <p>This option is transparently used by <tt>clang</tt> when generating PTH |
| 89 | files. Similarly, PTH files can be used as prefix headers using the <tt>-include-pth</tt> option:</p> |
| 90 | |
| 91 | <pre> |
| 92 | $ clang-cc -include-pth test.h.pth test.c -o test.s |
| 93 | </pre> |
| 94 | |
| 95 | <p>Alternatively, Clang's PTH files can be used as a raw "token-cache" |
| 96 | (or "content" cache) of the source included by the original header |
| 97 | file. This means that the contents of the PTH file are searched as substitutes |
| 98 | for <em>any</em> source files that are used by <tt>clang-cc</tt> to process a |
| 99 | source file. This is done by specifying the <tt>-token-cache</tt> option:</p> |
| 100 | |
| 101 | <pre> |
| 102 | $ cat test.h |
Chris Lattner | 0a06999 | 2009-04-08 06:00:32 +0000 | [diff] [blame] | 103 | #include <stdio.h> |
Ted Kremenek | 797a247 | 2009-04-08 05:07:30 +0000 | [diff] [blame] | 104 | $ clang-cc -emit-pth test.h -o test.h.pth |
| 105 | $ cat test.c |
| 106 | #include "test.h" |
| 107 | $ clang-cc test.c -o test -token-cache test.h.pth |
| 108 | </pre> |
| 109 | |
| 110 | <p>In this example the contents of <tt>stdio.h</tt> (and the files it includes) |
| 111 | will be retrieved from <tt>test.h.pth</tt>, as the PTH file is being used in |
| 112 | this case as a raw cache of the contents of <tt>test.h</tt>. This is a low-level |
| 113 | interface used to both implement the high-level PTH interface as well as to |
| 114 | provide alternative means to use PTH-style caching.</p> |
| 115 | |
| 116 | <h2>PTH Design and Implementation</h2> |
| 117 | |
| 118 | <p>Unlike GCC's precompiled headers, which cache the full ASTs and preprocessor |
| 119 | state of a header file, Clang's pretokenized header files mainly cache the raw |
| 120 | lexer <em>tokens</em> that are needed to segment the stream of characters in a |
| 121 | source file into keywords, identifiers, and operators. Consequently, PTH serves |
| 122 | to mainly directly speed up the lexing and preprocessing of a source file, while |
| 123 | parsing and type-checking must be completely redone every time a PTH file is |
| 124 | used.</p> |
| 125 | |
| 126 | <h3>Basic Design Tradeoffs</h3> |
| 127 | |
| 128 | <p>In the long term there are plans to provide an alternate PCH implementation |
| 129 | for Clang that also caches the work for parsing and type checking the contents |
| 130 | of header files. The current implementation of PCH in Clang as pretokenized |
| 131 | header files was motivated by the following factors:<p> |
| 132 | |
| 133 | <ul> |
Ted Kremenek | 07f08d2 | 2009-04-09 18:03:21 +0000 | [diff] [blame^] | 134 | |
| 135 | <li><p><em>Language independence</em>: PTH files work with any language that |
| 136 | Clang's lexer can handle, including C, Objective-C, and (in the early stages) |
| 137 | C++. This means development on language features at the parsing level or above |
| 138 | (which is basically almost all interesting pieces) does not require PTH to be |
| 139 | modified.</p></li> |
Ted Kremenek | 797a247 | 2009-04-08 05:07:30 +0000 | [diff] [blame] | 140 | |
| 141 | <li><em>Simple design</em>: Relatively speaking, PTH has a simple design and |
| 142 | implementation, making it easy to test. Further, because the machinery for PTH |
| 143 | resides at the lower-levels of the Clang library stack it is fairly |
| 144 | straightforward to profile and optimize.</li> |
| 145 | </ul> |
| 146 | |
| 147 | <p>Further, compared to GCC's PCH implementation (which is the dominate |
| 148 | precompiled header file implementation that Clang can be directly compared |
| 149 | against) the PTH design in Clang yields several attractive features:</p> |
| 150 | |
| 151 | <ul> |
| 152 | |
| 153 | <li><p><em>Architecture independence</em>: In contrast to GCC's PCH files (and |
| 154 | those of several other compilers), Clang's PTH files are architecture |
| 155 | independent, requiring only a single PTH file when building an program for |
| 156 | multiple architectures.</p> |
| 157 | |
| 158 | <p>For example, on Mac OS X one may wish to |
| 159 | compile a "universal binary" that runs on PowerPC, 32-bit Intel |
| 160 | (i386), and 64-bit Intel architectures. In contrast, GCC requires a PCH file for |
| 161 | each architecture, as the definitions of types in the AST are |
| 162 | architecture-specific. Since a Clang PTH file essentially represents a lexical |
| 163 | cache of header files, a single PTH file can be safely used when compiling for |
| 164 | multiple architectures. This can also reduce compile times because only a single |
| 165 | PTH file needs to be generated during a build instead of several.</p></li> |
| 166 | |
| 167 | <li><p><em>Reduced memory pressure</em>: Similar to GCC, |
| 168 | Clang reads PTH files via the use of memory mapping (i.e., <tt>mmap</tt>). |
| 169 | Clang, however, memory maps PTH files as read-only, meaning that multiple |
| 170 | invocations of <tt>clang-cc</tt> can share the same pages in memory from a |
| 171 | memory-mapped PTH file. In comparison, GCC also memory maps its PCH files but |
| 172 | also modifies those pages in memory, incurring the copy-on-write costs. The |
| 173 | read-only nature of PTH can greatly reduce memory pressure for builds involving |
| 174 | multiple cores, thus improving overall scalability.</p></li> |
| 175 | |
Ted Kremenek | 07f08d2 | 2009-04-09 18:03:21 +0000 | [diff] [blame^] | 176 | <li><p><em>Fast generation<em>: PTH files can be generated in a small fraction |
| 177 | of the time needed to generate GCC's PCH files. Since PTH/PCH generation is a |
| 178 | serial operation that typically blocks progress during a build, faster |
| 179 | generation time leads to improved processor utilization with parallel builds on |
| 180 | multicore machines.</p></li> |
| 181 | |
Ted Kremenek | 797a247 | 2009-04-08 05:07:30 +0000 | [diff] [blame] | 182 | </ul> |
| 183 | |
| 184 | <p>Despite these strengths, PTH's simple design suffers some algorithmic |
| 185 | handicaps compared to other PCH strategies such as those used by GCC. While PTH |
| 186 | can greatly speed up the processing time of a header file, the amount of work |
| 187 | required to process a header file is still roughly linear in the size of the |
| 188 | header file. In contrast, the amount of work done by GCC to process a |
| 189 | precompiled header is (theoretically) constant (the ASTs for the header are |
| 190 | literally memory mapped into the compiler). This means that only the pieces of |
| 191 | the header file that are referenced by the source file including the header are |
| 192 | the only ones the compiler needs to process during actual compilation. While |
| 193 | GCC's particular implementation of PCH mitigates some of these algorithmic |
| 194 | strengths via the use of copy-on-write pages, the approach itself can |
| 195 | fundamentally dominate at an algorithmic level, especially when one considers |
| 196 | header files of arbitrary size.</p> |
| 197 | |
Ted Kremenek | 07f08d2 | 2009-04-09 18:03:21 +0000 | [diff] [blame^] | 198 | <p>There are plans to potentially implement an complementary PCH implementation |
| 199 | for Clang based on the lazy deserialization of ASTs. This approach would |
| 200 | theoretically have the same constant-time algorithmic advantages just mentioned |
| 201 | but would also retain some of the strengths of PTH such as reduced memory |
| 202 | pressure (ideal for multi-core builds).</p> |
Ted Kremenek | 797a247 | 2009-04-08 05:07:30 +0000 | [diff] [blame] | 203 | |
| 204 | <h3>Internal PTH Optimizations</h3> |
| 205 | |
| 206 | <p>While the main optimization employed by PTH is to reduce lexing time of |
| 207 | header files by caching pre-lexed tokens, PTH also employs several other |
| 208 | optimizations to speed up the processing of header files:</p> |
| 209 | |
| 210 | <ul> |
| 211 | |
| 212 | <li><p><em><tt>stat</tt> caching</em>: PTH files cache information obtained via |
| 213 | calls to <tt>stat</tt> that <tt>clang-cc</tt> uses to resolve which files are |
| 214 | included by <tt>#include</tt> directives. This greatly reduces the overhead |
| 215 | involved in context-switching to the kernel to resolve included files.</p></li> |
| 216 | |
| 217 | <li><p><em>Fasting skipping of <tt>#ifdef</tt>...<tt>#endif</tt> chains</em>: |
| 218 | PTH files record the basic structure of nested preprocessor blocks. When the |
| 219 | condition of the preprocessor block is false, all of its tokens are immediately |
| 220 | skipped instead of requiring them to be handled by Clang's |
| 221 | preprocessor.</p></li> |
| 222 | |
| 223 | </ul> |
| 224 | |
| 225 | </div> |
| 226 | </body> |
| 227 | </html> |