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