138daca63SDean Michael Berris=================== 238daca63SDean Michael BerrisDebugging with XRay 338daca63SDean Michael Berris=================== 438daca63SDean Michael Berris 538daca63SDean Michael BerrisThis document shows an example of how you would go about analyzing applications 638daca63SDean Michael Berrisbuilt with XRay instrumentation. Here we will attempt to debug ``llc`` 738daca63SDean Michael Berriscompiling some sample LLVM IR generated by Clang. 838daca63SDean Michael Berris 938daca63SDean Michael Berris.. contents:: 1038daca63SDean Michael Berris :local: 1138daca63SDean Michael Berris 1238daca63SDean Michael BerrisBuilding with XRay 1338daca63SDean Michael Berris------------------ 1438daca63SDean Michael Berris 1538daca63SDean Michael BerrisTo debug an application with XRay instrumentation, we need to build it with a 16be65893bSDean Michael BerrisClang that supports the ``-fxray-instrument`` option. See `XRay <XRay.html>`_ 17be65893bSDean Michael Berrisfor more technical details of how XRay works for background information. 1838daca63SDean Michael Berris 1938daca63SDean Michael BerrisIn our example, we need to add ``-fxray-instrument`` to the list of flags 2038daca63SDean Michael Berrispassed to Clang when building a binary. Note that we need to link with Clang as 2138daca63SDean Michael Berriswell to get the XRay runtime linked in appropriately. For building ``llc`` with 2238daca63SDean Michael BerrisXRay, we do something similar below for our LLVM build: 2338daca63SDean Michael Berris 2438daca63SDean Michael Berris:: 2538daca63SDean Michael Berris 2638daca63SDean Michael Berris $ mkdir -p llvm-build && cd llvm-build 2738daca63SDean Michael Berris # Assume that the LLVM sources are at ../llvm 2838daca63SDean Michael Berris $ cmake -GNinja ../llvm -DCMAKE_BUILD_TYPE=Release \ 2938daca63SDean Michael Berris -DCMAKE_C_FLAGS_RELEASE="-fxray-instrument" -DCMAKE_CXX_FLAGS="-fxray-instrument" \ 3038daca63SDean Michael Berris # Once this finishes, we should build llc 3138daca63SDean Michael Berris $ ninja llc 3238daca63SDean Michael Berris 3338daca63SDean Michael Berris 3438daca63SDean Michael BerrisTo verify that we have an XRay instrumented binary, we can use ``objdump`` to 3538daca63SDean Michael Berrislook for the ``xray_instr_map`` section. 3638daca63SDean Michael Berris 3738daca63SDean Michael Berris:: 3838daca63SDean Michael Berris 3938daca63SDean Michael Berris $ objdump -h -j xray_instr_map ./bin/llc 4038daca63SDean Michael Berris ./bin/llc: file format elf64-x86-64 4138daca63SDean Michael Berris 4238daca63SDean Michael Berris Sections: 4338daca63SDean Michael Berris Idx Name Size VMA LMA File off Algn 4438daca63SDean Michael Berris 14 xray_instr_map 00002fc0 00000000041516c6 00000000041516c6 03d516c6 2**0 4538daca63SDean Michael Berris CONTENTS, ALLOC, LOAD, READONLY, DATA 4638daca63SDean Michael Berris 4738daca63SDean Michael BerrisGetting Traces 4838daca63SDean Michael Berris-------------- 4938daca63SDean Michael Berris 5038daca63SDean Michael BerrisBy default, XRay does not write out the trace files or patch the application 5166c5bbc5SEric Christopherbefore main starts. If we run ``llc`` it should work like a normally built 5266c5bbc5SEric Christopherbinary. If we want to get a full trace of the application's operations (of the 5366c5bbc5SEric Christopherfunctions we do end up instrumenting with XRay) then we need to enable XRay 5466c5bbc5SEric Christopherat application start. To do this, XRay checks the ``XRAY_OPTIONS`` environment 5566c5bbc5SEric Christophervariable. 5638daca63SDean Michael Berris 5738daca63SDean Michael Berris:: 5838daca63SDean Michael Berris 5938daca63SDean Michael Berris # The following doesn't create an XRay trace by default. 6038daca63SDean Michael Berris $ ./bin/llc input.ll 6138daca63SDean Michael Berris 6238daca63SDean Michael Berris # We need to set the XRAY_OPTIONS to enable some features. 63eec462f0SDean Michael Berris $ XRAY_OPTIONS="patch_premain=true xray_mode=xray-basic verbosity=1" ./bin/llc input.ll 6438daca63SDean Michael Berris ==69819==XRay: Log file in 'xray-log.llc.m35qPB' 6538daca63SDean Michael Berris 6638daca63SDean Michael BerrisAt this point we now have an XRay trace we can start analysing. 6738daca63SDean Michael Berris 6838daca63SDean Michael BerrisThe ``llvm-xray`` Tool 6938daca63SDean Michael Berris---------------------- 7038daca63SDean Michael Berris 7138daca63SDean Michael BerrisHaving a trace then allows us to do basic accounting of the functions that were 7238daca63SDean Michael Berrisinstrumented, and how much time we're spending in parts of the code. To make 7338daca63SDean Michael Berrissense of this data, we use the ``llvm-xray`` tool which has a few subcommands 7438daca63SDean Michael Berristo help us understand our trace. 7538daca63SDean Michael Berris 7666c5bbc5SEric ChristopherOne of the things we can do is to get an accounting of the functions that have 7766c5bbc5SEric Christopherbeen instrumented. We can see an example accounting with ``llvm-xray account``: 7838daca63SDean Michael Berris 7938daca63SDean Michael Berris:: 8038daca63SDean Michael Berris 81*676f16beSFangrui Song $ llvm-xray account xray-log.llc.m35qPB --top=10 --sort=sum --sortorder=dsc --instr_map=./bin/llc 8238daca63SDean Michael Berris Functions with latencies: 29 8338daca63SDean Michael Berris funcid count [ min, med, 90p, 99p, max] sum function 8438daca63SDean Michael Berris 187 360 [ 0.000000, 0.000001, 0.000014, 0.000032, 0.000075] 0.001596 LLLexer.cpp:446:0: llvm::LLLexer::LexIdentifier() 8538daca63SDean Michael Berris 85 130 [ 0.000000, 0.000000, 0.000018, 0.000023, 0.000156] 0.000799 X86ISelDAGToDAG.cpp:1984:0: (anonymous namespace)::X86DAGToDAGISel::Select(llvm::SDNode*) 8638daca63SDean Michael Berris 138 130 [ 0.000000, 0.000000, 0.000017, 0.000155, 0.000155] 0.000774 SelectionDAGISel.cpp:2963:0: llvm::SelectionDAGISel::SelectCodeCommon(llvm::SDNode*, unsigned char const*, unsigned int) 8738daca63SDean Michael Berris 188 103 [ 0.000000, 0.000000, 0.000003, 0.000123, 0.000214] 0.000737 LLParser.cpp:2692:0: llvm::LLParser::ParseValID(llvm::ValID&, llvm::LLParser::PerFunctionState*) 8838daca63SDean Michael Berris 88 1 [ 0.000562, 0.000562, 0.000562, 0.000562, 0.000562] 0.000562 X86ISelLowering.cpp:83:0: llvm::X86TargetLowering::X86TargetLowering(llvm::X86TargetMachine const&, llvm::X86Subtarget const&) 8938daca63SDean Michael Berris 125 102 [ 0.000001, 0.000003, 0.000010, 0.000017, 0.000049] 0.000471 Verifier.cpp:3714:0: (anonymous namespace)::Verifier::visitInstruction(llvm::Instruction&) 9038daca63SDean Michael Berris 90 8 [ 0.000023, 0.000035, 0.000106, 0.000106, 0.000106] 0.000342 X86ISelLowering.cpp:3363:0: llvm::X86TargetLowering::LowerCall(llvm::TargetLowering::CallLoweringInfo&, llvm::SmallVectorImpl<llvm::SDValue>&) const 9138daca63SDean Michael Berris 124 32 [ 0.000003, 0.000007, 0.000016, 0.000041, 0.000041] 0.000310 Verifier.cpp:1967:0: (anonymous namespace)::Verifier::visitFunction(llvm::Function const&) 9238daca63SDean Michael Berris 123 1 [ 0.000302, 0.000302, 0.000302, 0.000302, 0.000302] 0.000302 LLVMContextImpl.cpp:54:0: llvm::LLVMContextImpl::~LLVMContextImpl() 9338daca63SDean Michael Berris 139 46 [ 0.000000, 0.000002, 0.000006, 0.000008, 0.000019] 0.000138 TargetLowering.cpp:506:0: llvm::TargetLowering::SimplifyDemandedBits(llvm::SDValue, llvm::APInt const&, llvm::APInt&, llvm::APInt&, llvm::TargetLowering::TargetLoweringOpt&, unsigned int, bool) const 9438daca63SDean Michael Berris 9538daca63SDean Michael BerrisThis shows us that for our input file, ``llc`` spent the most cumulative time 9638daca63SDean Michael Berrisin the lexer (a total of 1 millisecond). If we wanted for example to work with 9738daca63SDean Michael Berristhis data in a spreadsheet, we can output the results as CSV using the 9838daca63SDean Michael Berris``-format=csv`` option to the command for further analysis. 9938daca63SDean Michael Berris 10038daca63SDean Michael BerrisIf we want to get a textual representation of the raw trace we can use the 10138daca63SDean Michael Berris``llvm-xray convert`` tool to get YAML output. The first few lines of that 1023655495bSSylvestre Ledruoutput for an example trace would look like the following: 10338daca63SDean Michael Berris 10438daca63SDean Michael Berris:: 10538daca63SDean Michael Berris 106*676f16beSFangrui Song $ llvm-xray convert -f yaml --symbolize --instr_map=./bin/llc xray-log.llc.m35qPB 10738daca63SDean Michael Berris --- 10838daca63SDean Michael Berris header: 10938daca63SDean Michael Berris version: 1 11038daca63SDean Michael Berris type: 0 11138daca63SDean Michael Berris constant-tsc: true 11238daca63SDean Michael Berris nonstop-tsc: true 11338daca63SDean Michael Berris cycle-frequency: 2601000000 11438daca63SDean Michael Berris records: 11538daca63SDean Michael Berris - { type: 0, func-id: 110, function: __cxx_global_var_init.8, cpu: 37, thread: 69819, kind: function-enter, tsc: 5434426023268520 } 11638daca63SDean Michael Berris - { type: 0, func-id: 110, function: __cxx_global_var_init.8, cpu: 37, thread: 69819, kind: function-exit, tsc: 5434426023523052 } 11738daca63SDean Michael Berris - { type: 0, func-id: 164, function: __cxx_global_var_init, cpu: 37, thread: 69819, kind: function-enter, tsc: 5434426029925386 } 11838daca63SDean Michael Berris - { type: 0, func-id: 164, function: __cxx_global_var_init, cpu: 37, thread: 69819, kind: function-exit, tsc: 5434426030031128 } 11938daca63SDean Michael Berris - { type: 0, func-id: 142, function: '(anonymous namespace)::CommandLineParser::ParseCommandLineOptions(int, char const* const*, llvm::StringRef, llvm::raw_ostream*)', cpu: 37, thread: 69819, kind: function-enter, tsc: 5434426046951388 } 12038daca63SDean Michael Berris - { type: 0, func-id: 142, function: '(anonymous namespace)::CommandLineParser::ParseCommandLineOptions(int, char const* const*, llvm::StringRef, llvm::raw_ostream*)', cpu: 37, thread: 69819, kind: function-exit, tsc: 5434426047282020 } 12138daca63SDean Michael Berris - { type: 0, func-id: 187, function: 'llvm::LLLexer::LexIdentifier()', cpu: 37, thread: 69819, kind: function-enter, tsc: 5434426047857332 } 12238daca63SDean Michael Berris - { type: 0, func-id: 187, function: 'llvm::LLLexer::LexIdentifier()', cpu: 37, thread: 69819, kind: function-exit, tsc: 5434426047984152 } 12338daca63SDean Michael Berris - { type: 0, func-id: 187, function: 'llvm::LLLexer::LexIdentifier()', cpu: 37, thread: 69819, kind: function-enter, tsc: 5434426048036584 } 12438daca63SDean Michael Berris - { type: 0, func-id: 187, function: 'llvm::LLLexer::LexIdentifier()', cpu: 37, thread: 69819, kind: function-exit, tsc: 5434426048042292 } 12538daca63SDean Michael Berris - { type: 0, func-id: 187, function: 'llvm::LLLexer::LexIdentifier()', cpu: 37, thread: 69819, kind: function-enter, tsc: 5434426048055056 } 12638daca63SDean Michael Berris - { type: 0, func-id: 187, function: 'llvm::LLLexer::LexIdentifier()', cpu: 37, thread: 69819, kind: function-exit, tsc: 5434426048067316 } 12738daca63SDean Michael Berris 12838daca63SDean Michael BerrisControlling Fidelity 12938daca63SDean Michael Berris-------------------- 13038daca63SDean Michael Berris 13138daca63SDean Michael BerrisSo far in our examples, we haven't been getting full coverage of the functions 13238daca63SDean Michael Berriswe have in the binary. To get that, we need to modify the compiler flags so 13338daca63SDean Michael Berristhat we can instrument more (if not all) the functions we have in the binary. 13438daca63SDean Michael BerrisWe have two options for doing that, and we explore both of these below. 13538daca63SDean Michael Berris 13638daca63SDean Michael BerrisInstruction Threshold 13738daca63SDean Michael Berris````````````````````` 13838daca63SDean Michael Berris 13938daca63SDean Michael BerrisThe first "blunt" way of doing this is by setting the minimum threshold for 14038daca63SDean Michael Berrisfunction bodies to 1. We can do that with the 14138daca63SDean Michael Berris``-fxray-instruction-threshold=N`` flag when building our binary. We rebuild 14238daca63SDean Michael Berris``llc`` with this option and observe the results: 14338daca63SDean Michael Berris 14438daca63SDean Michael Berris:: 14538daca63SDean Michael Berris 14638daca63SDean Michael Berris $ rm CMakeCache.txt 14738daca63SDean Michael Berris $ cmake -GNinja ../llvm -DCMAKE_BUILD_TYPE=Release \ 14838daca63SDean Michael Berris -DCMAKE_C_FLAGS_RELEASE="-fxray-instrument -fxray-instruction-threshold=1" \ 14938daca63SDean Michael Berris -DCMAKE_CXX_FLAGS="-fxray-instrument -fxray-instruction-threshold=1" 15038daca63SDean Michael Berris $ ninja llc 15138daca63SDean Michael Berris $ XRAY_OPTIONS="patch_premain=true" ./bin/llc input.ll 15238daca63SDean Michael Berris ==69819==XRay: Log file in 'xray-log.llc.5rqxkU' 15338daca63SDean Michael Berris 154*676f16beSFangrui Song $ llvm-xray account xray-log.llc.5rqxkU --top=10 --sort=sum --sortorder=dsc --instr_map=./bin/llc 15538daca63SDean Michael Berris Functions with latencies: 36652 15638daca63SDean Michael Berris funcid count [ min, med, 90p, 99p, max] sum function 15738daca63SDean Michael Berris 75 1 [ 0.672368, 0.672368, 0.672368, 0.672368, 0.672368] 0.672368 llc.cpp:271:0: main 15838daca63SDean Michael Berris 78 1 [ 0.626455, 0.626455, 0.626455, 0.626455, 0.626455] 0.626455 llc.cpp:381:0: compileModule(char**, llvm::LLVMContext&) 15938daca63SDean Michael Berris 139617 1 [ 0.472618, 0.472618, 0.472618, 0.472618, 0.472618] 0.472618 LegacyPassManager.cpp:1723:0: llvm::legacy::PassManager::run(llvm::Module&) 16038daca63SDean Michael Berris 139610 1 [ 0.472618, 0.472618, 0.472618, 0.472618, 0.472618] 0.472618 LegacyPassManager.cpp:1681:0: llvm::legacy::PassManagerImpl::run(llvm::Module&) 16138daca63SDean Michael Berris 139612 1 [ 0.470948, 0.470948, 0.470948, 0.470948, 0.470948] 0.470948 LegacyPassManager.cpp:1564:0: (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) 16238daca63SDean Michael Berris 139607 2 [ 0.147345, 0.315994, 0.315994, 0.315994, 0.315994] 0.463340 LegacyPassManager.cpp:1530:0: llvm::FPPassManager::runOnModule(llvm::Module&) 16338daca63SDean Michael Berris 139605 21 [ 0.000002, 0.000002, 0.102593, 0.213336, 0.213336] 0.463331 LegacyPassManager.cpp:1491:0: llvm::FPPassManager::runOnFunction(llvm::Function&) 16438daca63SDean Michael Berris 139563 26096 [ 0.000002, 0.000002, 0.000037, 0.000063, 0.000215] 0.225708 LegacyPassManager.cpp:1083:0: llvm::PMDataManager::findAnalysisPass(void const*, bool) 16538daca63SDean Michael Berris 108055 188 [ 0.000002, 0.000120, 0.001375, 0.004523, 0.062624] 0.159279 MachineFunctionPass.cpp:38:0: llvm::MachineFunctionPass::runOnFunction(llvm::Function&) 16638daca63SDean Michael Berris 62635 22 [ 0.000041, 0.000046, 0.000050, 0.126744, 0.126744] 0.127715 X86TargetMachine.cpp:242:0: llvm::X86TargetMachine::getSubtargetImpl(llvm::Function const&) const 16738daca63SDean Michael Berris 16838daca63SDean Michael Berris 16938daca63SDean Michael BerrisInstrumentation Attributes 17038daca63SDean Michael Berris`````````````````````````` 17138daca63SDean Michael Berris 17238daca63SDean Michael BerrisThe other way is to use configuration files for selecting which functions 17338daca63SDean Michael Berrisshould always be instrumented by the compiler. This gives us a way of ensuring 17438daca63SDean Michael Berristhat certain functions are either always or never instrumented by not having to 17538daca63SDean Michael Berrisadd the attribute to the source. 17638daca63SDean Michael Berris 17738daca63SDean Michael BerrisTo use this feature, you can define one file for the functions to always 17838daca63SDean Michael Berrisinstrument, and another for functions to never instrument. The format of these 17938daca63SDean Michael Berrisfiles are exactly the same as the SanitizerLists files that control similar 18020dc6ef7SDean Michael Berristhings for the sanitizer implementations. For example: 18138daca63SDean Michael Berris 18238daca63SDean Michael Berris:: 18338daca63SDean Michael Berris 18420dc6ef7SDean Michael Berris # xray-attr-list.txt 18538daca63SDean Michael Berris # always instrument functions that match the following filters: 18620dc6ef7SDean Michael Berris [always] 18738daca63SDean Michael Berris fun:main 18838daca63SDean Michael Berris 18938daca63SDean Michael Berris # never instrument functions that match the following filters: 19020dc6ef7SDean Michael Berris [never] 19138daca63SDean Michael Berris fun:__cxx_* 19238daca63SDean Michael Berris 19320dc6ef7SDean Michael BerrisGiven the file above we can re-build by providing it to the 19420dc6ef7SDean Michael Berris``-fxray-attr-list=`` flag to clang. You can have multiple files, each defining 19520dc6ef7SDean Michael Berrisdifferent sets of attribute sets, to be combined into a single list by clang. 19638daca63SDean Michael Berris 197b2f894ffSKeith WyssThe XRay stack tool 198b2f894ffSKeith Wyss------------------- 199b2f894ffSKeith Wyss 200b2f894ffSKeith WyssGiven a trace, and optionally an instrumentation map, the ``llvm-xray stack`` 201b2f894ffSKeith Wysscommand can be used to analyze a call stack graph constructed from the function 202b2f894ffSKeith Wysscall timeline. 203b2f894ffSKeith Wyss 20466c5bbc5SEric ChristopherThe way to use the command is to output the top stacks by call count and time spent. 205b2f894ffSKeith Wyss 206b2f894ffSKeith Wyss:: 207b2f894ffSKeith Wyss 208*676f16beSFangrui Song $ llvm-xray stack xray-log.llc.5rqxkU --instr_map=./bin/llc 209b2f894ffSKeith Wyss 210b2f894ffSKeith Wyss Unique Stacks: 3069 211b2f894ffSKeith Wyss Top 10 Stacks by leaf sum: 212b2f894ffSKeith Wyss 213b2f894ffSKeith Wyss Sum: 9633790 214b2f894ffSKeith Wyss lvl function count sum 215b2f894ffSKeith Wyss #0 main 1 58421550 216b2f894ffSKeith Wyss #1 compileModule(char**, llvm::LLVMContext&) 1 51440360 217b2f894ffSKeith Wyss #2 llvm::legacy::PassManagerImpl::run(llvm::Module&) 1 40535375 218b2f894ffSKeith Wyss #3 llvm::FPPassManager::runOnModule(llvm::Module&) 2 39337525 219b2f894ffSKeith Wyss #4 llvm::FPPassManager::runOnFunction(llvm::Function&) 6 39331465 220b2f894ffSKeith Wyss #5 llvm::PMDataManager::verifyPreservedAnalysis(llvm::Pass*) 399 16628590 221b2f894ffSKeith Wyss #6 llvm::PMTopLevelManager::findAnalysisPass(void const*) 4584 15155600 222b2f894ffSKeith Wyss #7 llvm::PMDataManager::findAnalysisPass(void const*, bool) 32088 9633790 223b2f894ffSKeith Wyss 224b2f894ffSKeith Wyss ..etc.. 225b2f894ffSKeith Wyss 226b2f894ffSKeith WyssIn the default mode, identical stacks on different threads are independently 227b2f894ffSKeith Wyssaggregated. In a multithreaded program, you may end up having identical call 228b2f894ffSKeith Wyssstacks fill your list of top calls. 229b2f894ffSKeith Wyss 230*676f16beSFangrui SongTo address this, you may specify the ``--aggregate-threads`` or 231*676f16beSFangrui Song``--per-thread-stacks`` flags. ``--per-thread-stacks`` treats the thread id as an 232*676f16beSFangrui Songimplicit root in each call stack tree, while ``--aggregate-threads`` combines 233b2f894ffSKeith Wyssidentical stacks from all threads. 234b2f894ffSKeith Wyss 235b2f894ffSKeith WyssFlame Graph Generation 236b2f894ffSKeith Wyss---------------------- 237b2f894ffSKeith Wyss 238b2f894ffSKeith WyssThe ``llvm-xray stack`` tool may also be used to generate flamegraphs for 239b2f894ffSKeith Wyssvisualizing your instrumented invocations. The tool does not generate the graphs 240b2f894ffSKeith Wyssthemselves, but instead generates a format that can be used with Brendan Gregg's 241b2f894ffSKeith WyssFlameGraph tool, currently available on `github 242b2f894ffSKeith Wyss<https://github.com/brendangregg/FlameGraph>`_. 243b2f894ffSKeith Wyss 244b2f894ffSKeith WyssTo generate output for a flamegraph, a few more options are necessary. 245b2f894ffSKeith Wyss 246*676f16beSFangrui Song- ``--all-stacks`` - Emits all of the stacks. 247*676f16beSFangrui Song- ``--stack-format`` - Choose the flamegraph output format 'flame'. 248*676f16beSFangrui Song- ``--aggregation-type`` - Choose the metric to graph. 249b2f894ffSKeith Wyss 250b2f894ffSKeith WyssYou may pipe the command output directly to the flamegraph tool to obtain an 251b2f894ffSKeith Wysssvg file. 252b2f894ffSKeith Wyss 253b2f894ffSKeith Wyss:: 254b2f894ffSKeith Wyss 255*676f16beSFangrui Song $ llvm-xray stack xray-log.llc.5rqxkU --instr_map=./bin/llc --stack-format=flame --aggregation-type=time --all-stacks | \ 256b2f894ffSKeith Wyss /path/to/FlameGraph/flamegraph.pl > flamegraph.svg 257b2f894ffSKeith Wyss 258b2f894ffSKeith WyssIf you open the svg in a browser, mouse events allow exploring the call stacks. 259b2f894ffSKeith Wyss 26041a21475SDean Michael BerrisChrome Trace Viewer Visualization 26141a21475SDean Michael Berris--------------------------------- 26241a21475SDean Michael Berris 26341a21475SDean Michael BerrisWe can also generate a trace which can be loaded by the Chrome Trace Viewer 26441a21475SDean Michael Berrisfrom the same generated trace: 26541a21475SDean Michael Berris 26641a21475SDean Michael Berris:: 26741a21475SDean Michael Berris 268*676f16beSFangrui Song $ llvm-xray convert --symbolize --instr_map=./bin/llc \ 269*676f16beSFangrui Song --output-format=trace_event xray-log.llc.5rqxkU \ 27041a21475SDean Michael Berris | gzip > llc-trace.txt.gz 27141a21475SDean Michael Berris 27241a21475SDean Michael BerrisFrom a Chrome browser, navigating to ``chrome:///tracing`` allows us to load 27341a21475SDean Michael Berristhe ``sample-trace.txt.gz`` file to visualize the execution trace. 27441a21475SDean Michael Berris 27538daca63SDean Michael BerrisFurther Exploration 27638daca63SDean Michael Berris------------------- 27738daca63SDean Michael Berris 27838daca63SDean Michael BerrisThe ``llvm-xray`` tool has a few other subcommands that are in various stages 27938daca63SDean Michael Berrisof being developed. One interesting subcommand that can highlight a few 28038daca63SDean Michael Berrisinteresting things is the ``graph`` subcommand. Given for example the following 28138daca63SDean Michael Berristoy program that we build with XRay instrumentation, we can see how the 28238daca63SDean Michael Berrisgenerated graph may be a helpful indicator of where time is being spent for the 28338daca63SDean Michael Berrisapplication. 28438daca63SDean Michael Berris 28538daca63SDean Michael Berris.. code-block:: c++ 28638daca63SDean Michael Berris 28738daca63SDean Michael Berris // sample.cc 28838daca63SDean Michael Berris #include <iostream> 28938daca63SDean Michael Berris #include <thread> 29038daca63SDean Michael Berris 291cc1328c1SFangrui Song [[clang::xray_always_instrument]] void f() { 29238daca63SDean Michael Berris std::cerr << '.'; 29338daca63SDean Michael Berris } 29438daca63SDean Michael Berris 295cc1328c1SFangrui Song [[clang::xray_always_instrument]] void g() { 29638daca63SDean Michael Berris for (int i = 0; i < 1 << 10; ++i) { 29738daca63SDean Michael Berris std::cerr << '-'; 29838daca63SDean Michael Berris } 29938daca63SDean Michael Berris } 30038daca63SDean Michael Berris 30138daca63SDean Michael Berris int main(int argc, char* argv[]) { 30238daca63SDean Michael Berris std::thread t1([] { 30338daca63SDean Michael Berris for (int i = 0; i < 1 << 10; ++i) 30438daca63SDean Michael Berris f(); 30538daca63SDean Michael Berris }); 30638daca63SDean Michael Berris std::thread t2([] { 30738daca63SDean Michael Berris g(); 30838daca63SDean Michael Berris }); 30938daca63SDean Michael Berris t1.join(); 31038daca63SDean Michael Berris t2.join(); 31138daca63SDean Michael Berris std::cerr << '\n'; 31238daca63SDean Michael Berris } 31338daca63SDean Michael Berris 31438daca63SDean Michael BerrisWe then build the above with XRay instrumentation: 31538daca63SDean Michael Berris 31638daca63SDean Michael Berris:: 31738daca63SDean Michael Berris 31838daca63SDean Michael Berris $ clang++ -o sample -O3 sample.cc -std=c++11 -fxray-instrument -fxray-instruction-threshold=1 319f0a1088aSDean Michael Berris $ XRAY_OPTIONS="patch_premain=true xray_mode=xray-basic" ./sample 32038daca63SDean Michael Berris 32138daca63SDean Michael BerrisWe can then explore the graph rendering of the trace generated by this sample 32298cbdba2SYao Zhaoapplication. We assume you have the graphviz tools available in your system, 32338daca63SDean Michael Berrisincluding both ``unflatten`` and ``dot``. If you prefer rendering or exploring 32438daca63SDean Michael Berristhe graph using another tool, then that should be feasible as well. ``llvm-xray 32538daca63SDean Michael Berrisgraph`` will create DOT format graphs which should be usable in most graph 32638daca63SDean Michael Berrisrendering applications. One example invocation of the ``llvm-xray graph`` 32738daca63SDean Michael Berriscommand should yield some interesting insights to the workings of C++ 32838daca63SDean Michael Berrisapplications: 32938daca63SDean Michael Berris 33038daca63SDean Michael Berris:: 33138daca63SDean Michael Berris 332*676f16beSFangrui Song $ llvm-xray graph xray-log.sample.* -m sample --color-edges=sum --edge-label=sum \ 33338daca63SDean Michael Berris | unflatten -f -l10 | dot -Tsvg -o sample.svg 33438daca63SDean Michael Berris 33541a21475SDean Michael Berris 33638daca63SDean Michael BerrisNext Steps 33738daca63SDean Michael Berris---------- 33838daca63SDean Michael Berris 33938daca63SDean Michael BerrisIf you have some interesting analyses you'd like to implement as part of the 34038daca63SDean Michael Berrisllvm-xray tool, please feel free to propose them on the llvm-dev@ mailing list. 34138daca63SDean Michael BerrisThe following are some ideas to inspire you in getting involved and potentially 34238daca63SDean Michael Berrismaking things better. 34338daca63SDean Michael Berris 34438daca63SDean Michael Berris - Implement a query/filtering library that allows for finding patterns in the 34538daca63SDean Michael Berris XRay traces. 34638daca63SDean Michael Berris - Collecting function call stacks and how often they're encountered in the 34738daca63SDean Michael Berris XRay trace. 348