<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jan 17, 2019 at 3:25 PM Manman Ren <<a href="mailto:manman.ren@gmail.com">manman.ren@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail-m_8096178839700176914gmail_attr">On Thu, Jan 17, 2019 at 2:47 PM Xinliang David Li <<a href="mailto:davidxl@google.com" target="_blank">davidxl@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail-m_8096178839700176914gmail-m_-7170412012052321gmail_attr">On Thu, Jan 17, 2019 at 2:32 PM Manman Ren <<a href="mailto:manman.ren@gmail.com" target="_blank">manman.ren@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail-m_8096178839700176914gmail-m_-7170412012052321gmail-m_6346669425385714280gmail_attr">On Thu, Jan 17, 2019 at 10:53 AM Xinliang David Li <<a href="mailto:davidxl@google.com" target="_blank">davidxl@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Hi Manman,<div><br></div><div>Ordering profiling is certainly something very useful to have to startup time performance. GCC has something similar.</div><div><br></div><div>In terms of implementation, it is possible to simply extend the edge profiling counters by 1 for each function, and instrument the function to record the time stamp the first time the function is executed. The overhead will be minimized and you can leverage all the other existing support in profiling runtime.</div></div></blockquote><div><br></div><div>Hi David,</div><div><br></div><div>Just to clarify, are you suggesting to add an edge profiling counter per function to record the time stamp? Where are the edge profiling counters defined?</div></div></div></blockquote><div><br></div><div>There is no needed to define the counter explicitly. What is needed is to introduce a new intrinsic to update the order counter, and the InstProf lowerer will create the counter for you. See Transforms/Instrumentation/InstrProfiling.cpp.   <a class="gmail_plusreply" id="gmail-m_8096178839700176914gmail-m_-7170412012052321plusReplyChip-0" href="mailto:vsk@apple.com" target="_blank">+Vedant Kumar</a> </div></div></div></blockquote><div><br></div><div>We need the instrumentation to be run late as an IR pass, so it has all the function symbols. Are you suggesting a front-end instrumentation by mentioning InstrProfiling.cpp?</div><div>  </div></div></div></blockquote><div><br></div><div>The lowering is actually shared by both FE instrumentation and IR PGO.   For ordering profiling, it needs to run the pass after the inliner pass in theory (which is later even than the current IR PGO instrumentation pass).  One way to achieve the same effect is lower the time stamp counter update intrinsic in a separate pass (after inlining).  In the lowerer, the counter update intrinsic can be eliminated if it is in an inline instance, but this is not ideal either as the inlining decisions may be affected due to instrumentation.  </div><div><br></div><div>To combine the ordering profiling requirements (post inlining) and the benefit of sharing (runtime, tooling etc),  the proposed implementation can be modified with the following changes:</div><div>0) keep the phase ordering in the patch</div><div>1) the instrumentation just does insert intrinsics</div><div>2) enhance lowering to handle new intrinsics.</div><div><br></div><div>I assume ordering profiling is not intended to work together with PGO instrumentation (to make sure inlining decisions are the same), so the you end up with a counter section with one counter per out of line function. The rest will just work. The changes to runtime will be minimal.</div><div><br></div><div>If  PGO (IR or FE) + Ordering profiling is a desired use case, it can be made working too -- the lowerer needs to update the per function counter array size (appending one).</div><div><br></div><div><br></div><div>David</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div><br></div><div>So the difference will be where we store the profile information and in what format?</div><div><br></div></div></div></blockquote><div><br></div><div>Time stamp can be simply a uint64 value just like any edge/block profile count.   llvm_profdata tool can be taught to dump the ordering file to be exported to the linker.</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div></div><div>With the suggested approach, we need to allocate one time stamp for each function, what is implemented is a pair of numbers for each executed function. The runtime performance can be different as well, the suggested approach gets the time stamp, and saves it to memory, what is implemented is saving the pair of numbers and incrementing a counter.</div><div><br></div></div></div></blockquote><div><br></div><div>The runtime cost is probably not much for either approach. The suggested approach eliminates the trouble to maintain/implement a different way to identify functions.</div></div></div></blockquote><div><br></div><div>Agree that using existing infra is better!</div><div><br></div></div></div></blockquote><div><br></div><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div></div><div>Manman </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div>Another possibility is to use xray to implement the functionality -- xray is useful for trace like profiling by design.</div></div></blockquote><div><br></div><div>We have not looked into XRay. We need something with low binary size penalty and low runtime perf degradation, not sure if XRay is a good fit!</div><div><br></div></div></div></blockquote><div><br></div><div>xray can achieve very low runtime overhead. <a class="gmail_plusreply" id="gmail-m_8096178839700176914gmail-m_-7170412012052321plusReplyChip-1" href="mailto:dberris@google.com" target="_blank">+Dean Michael Berris</a> for additional comments.</div><div><br></div><div>David</div><div> </div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_quote"><div></div><div>Thanks,</div><div>Manman</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div>David </div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail-m_8096178839700176914gmail-m_-7170412012052321gmail-m_6346669425385714280gmail-m_-363471169000708715gmail_attr">On Thu, Jan 17, 2019 at 10:24 AM Manman Ren <<a href="mailto:manman.ren@gmail.com" target="_blank">manman.ren@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Order file is used to teach ld64 how to order the functions in a binary. If we put all functions executed during startup together in the right order, we will greatly reduce the page faults during startup.<br>
<br>
To generate order file for iOS apps, we usually use dtrace, but some apps have various startup scenarios that we want to capture in the order file. dtrace approach is not easy to automate, it is hard to capture the different ways of starting an app without automation. Instrumented builds however can be deployed to phones and profile data can be automatically collected.<br>
<br>
For the Facebook app, by looking at the startup distribution, we are expecting a big win out of the order file instrumentation, from 100ms to 500ms+, in startup time.<br>
<br>
The basic idea of the pass is to use a circular buffer to log the execution ordering of the functions. We only log the function when it is first executed. Instead of logging the symbol name of the function, we log a pair of integers, with one integer specifying the module id, and the other specifying the function id within the module.<br>
<br>
In this pass, we add three global variables:<br>
(1) an order file buffer<br>
The order file buffer is a circular buffer at its own llvm section. Each entry is a pair of integers, with one integer specifying the module id, and the other specifying the function id within the module.<br>
(2) a bitmap for each module: one bit for each function to say if the function is already executed;<br>
(3) a global index to the buffer<br>
<br>
At the function prologue, if the function has not been executed (by checking the bitmap), log the module id and the function id, then atomically increase the index.<br>
<br>
This pass is intended to be used as a ThinLTO pass or a LTO pass. It maps each module to a distinct integer, it also generate a mapping file so we can decode the function symbol name from the pair of ids.<br>
<br>
clang has '-finstrument-function-entry-bare' which inserts a function call and is not as efficient.<br><br>Three patches are attached, for llvm, clang, and compiler-rt respectively.<div><br>
TODO:<br>
(1) Migrate to the new pass manager with a shim for the legacy pass manager.<br>
(2) For the order file buffer, consider always emitting definitions, making them LinkOnceODR with a COMDAT group.<br>
(3) Add testing case for clang/compiler-rt patches.<br>
(4) Add utilities to deobfuscate the profile dump.<br>
(5) The size of the buffer is currently hard-coded (<code>INSTR_ORDER_FILE_BUFFER_SIZE).</code><br><br>
Thanks Kamal for contributing to the patches! Thanks to Aditya and Saleem for doing an initial review pass over the patches!<br><div><br></div><div>Manman</div><div><br></div><div><br></div></div></div>
</blockquote></div>
</blockquote></div></div>
</blockquote></div></div>
</blockquote></div></div>
</blockquote></div></div>