1.. Copyright (C) 2015-2020 Free Software Foundation, Inc. 2 Originally contributed by David Malcolm <dmalcolm@redhat.com> 3 4 This is free software: you can redistribute it and/or modify it 5 under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see 16 <http://www.gnu.org/licenses/>. 17 18.. default-domain:: c 19 20Performance 21=========== 22 23The timing API 24-------------- 25 26As of GCC 6, libgccjit exposes a timing API, for printing reports on 27how long was spent in different parts of code. 28 29You can create a :c:type:`gcc_jit_timer` instance, which will 30measure time spent since its creation. The timer maintains a stack 31of "timer items": as control flow moves through your code, you can push 32and pop named items relating to your code onto the stack, and the timer 33will account the time spent accordingly. 34 35You can also asssociate a timer with a :c:type:`gcc_jit_context`, in 36which case the time spent inside compilation will be subdivided. 37 38For example, the following code uses a timer, recording client items 39"create_code", "compile", and "running code": 40 41.. code-block:: c 42 43 /* Create a timer. */ 44 gcc_jit_timer *timer = gcc_jit_timer_new (); 45 if (!timer) 46 { 47 error ("gcc_jit_timer_new failed"); 48 return -1; 49 } 50 51 /* Let's repeatedly compile and run some code, accumulating it 52 all into the timer. */ 53 for (int i = 0; i < num_iterations; i++) 54 { 55 /* Create a context and associate it with the timer. */ 56 gcc_jit_context *ctxt = gcc_jit_context_acquire (); 57 if (!ctxt) 58 { 59 error ("gcc_jit_context_acquire failed"); 60 return -1; 61 } 62 gcc_jit_context_set_timer (ctxt, timer); 63 64 /* Populate the context, timing it as client item "create_code". */ 65 gcc_jit_timer_push (timer, "create_code"); 66 create_code (ctxt); 67 gcc_jit_timer_pop (timer, "create_code"); 68 69 /* Compile the context, timing it as client item "compile". */ 70 gcc_jit_timer_push (timer, "compile"); 71 result = gcc_jit_context_compile (ctxt); 72 gcc_jit_timer_pop (timer, "compile"); 73 74 /* Run the generated code, timing it as client item "running code". */ 75 gcc_jit_timer_push (timer, "running code"); 76 run_the_code (ctxt, result); 77 gcc_jit_timer_pop (timer, "running code"); 78 79 /* Clean up. */ 80 gcc_jit_context_release (ctxt); 81 gcc_jit_result_release (result); 82 } 83 84 /* Print the accumulated timings. */ 85 gcc_jit_timer_print (timer, stderr); 86 gcc_jit_timer_release (timer); 87 88giving output like this, showing the internal GCC items at the top, then 89client items, then the total:: 90 91 Execution times (seconds) 92 GCC items: 93 phase setup : 0.29 (14%) usr 0.00 ( 0%) sys 0.32 ( 5%) wall 10661 kB (50%) ggc 94 phase parsing : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 653 kB ( 3%) ggc 95 phase finalize : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 96 dump files : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 0 kB ( 0%) ggc 97 callgraph construction : 0.02 ( 1%) usr 0.01 ( 6%) sys 0.01 ( 0%) wall 242 kB ( 1%) ggc 98 callgraph optimization : 0.03 ( 2%) usr 0.00 ( 0%) sys 0.02 ( 0%) wall 142 kB ( 1%) ggc 99 trivially dead code : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 100 df scan insns : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 9 kB ( 0%) ggc 101 df live regs : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 0 kB ( 0%) ggc 102 inline parameters : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 82 kB ( 0%) ggc 103 tree CFG cleanup : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 104 tree PHI insertion : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.02 ( 0%) wall 64 kB ( 0%) ggc 105 tree SSA other : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.01 ( 0%) wall 18 kB ( 0%) ggc 106 expand : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 398 kB ( 2%) ggc 107 jump : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 108 loop init : 0.01 ( 0%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 67 kB ( 0%) ggc 109 integrated RA : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 2468 kB (12%) ggc 110 thread pro- & epilogue : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 162 kB ( 1%) ggc 111 final : 0.01 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 216 kB ( 1%) ggc 112 rest of compilation : 1.37 (69%) usr 0.00 ( 0%) sys 1.13 (18%) wall 1391 kB ( 6%) ggc 113 assemble JIT code : 0.01 ( 1%) usr 0.00 ( 0%) sys 4.04 (66%) wall 0 kB ( 0%) ggc 114 load JIT result : 0.02 ( 1%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 115 JIT client code : 0.00 ( 0%) usr 0.01 ( 6%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 116 Client items: 117 create_code : 0.00 ( 0%) usr 0.01 ( 6%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 118 compile : 0.36 (18%) usr 0.15 (83%) sys 0.86 (14%) wall 14939 kB (70%) ggc 119 running code : 0.00 ( 0%) usr 0.00 ( 0%) sys 0.00 ( 0%) wall 0 kB ( 0%) ggc 120 TOTAL : 2.00 0.18 6.12 21444 kB 121 122The exact format is intended to be human-readable, and is subject to change. 123 124.. macro:: LIBGCCJIT_HAVE_TIMING_API 125 126 The timer API was added to libgccjit in GCC 6. 127 This macro is only defined in versions of libgccjit.h which have the 128 timer API, and so can be used to guard code that may need to compile 129 against earlier releases:: 130 131 #ifdef LIBGCCJIT_HAVE_TIMING_API 132 gcc_jit_timer *t = gcc_jit_timer_new (); 133 gcc_jit_context_set_timer (ctxt, t); 134 #endif 135 136.. type:: gcc_jit_timer 137 138.. function:: gcc_jit_timer * gcc_jit_timer_new(void) 139 140 Create a :c:type:`gcc_jit_timer` instance, and start timing:: 141 142 gcc_jit_timer *t = gcc_jit_timer_new (); 143 144 This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test 145 for its presence using 146 147 .. code-block:: c 148 149 #ifdef LIBGCCJIT_HAVE_TIMING_API 150 151.. function:: void gcc_jit_timer_release(gcc_jit_timer *timer) 152 153 Release a :c:type:`gcc_jit_timer` instance:: 154 155 gcc_jit_timer_release (t); 156 157 This should be called exactly once on a timer. 158 159 This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test 160 for its presence using 161 162 .. code-block:: c 163 164 #ifdef LIBGCCJIT_HAVE_TIMING_API 165 166.. function:: void gcc_jit_context_set_timer(gcc_jit_context *ctxt, \ 167 gcc_jit_timer *timer) 168 169 Associate a :c:type:`gcc_jit_timer` instance with a context:: 170 171 gcc_jit_context_set_timer (ctxt, t); 172 173 A timer instance can be shared between multiple 174 :c:type:`gcc_jit_context` instances. 175 176 Timers have no locking, so if you have a multithreaded program, you 177 must provide your own locks if more than one thread could be working 178 with the same timer via timer-associated contexts. 179 180 This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test 181 for its presence using 182 183 .. code-block:: c 184 185 #ifdef LIBGCCJIT_HAVE_TIMING_API 186 187.. function:: gcc_jit_timer *gcc_jit_context_get_timer(gcc_jit_context *ctxt) 188 189 Get the timer associated with a context (if any). 190 191 This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test 192 for its presence using 193 194 .. code-block:: c 195 196 #ifdef LIBGCCJIT_HAVE_TIMING_API 197 198.. function:: void gcc_jit_timer_push(gcc_jit_timer *timer, \ 199 const char *item_name) 200 201 Push the given item onto the timer's stack:: 202 203 gcc_jit_timer_push (t, "running code"); 204 run_the_code (ctxt, result); 205 gcc_jit_timer_pop (t, "running code"); 206 207 This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test 208 for its presence using 209 210 .. code-block:: c 211 212 #ifdef LIBGCCJIT_HAVE_TIMING_API 213 214.. function:: void gcc_jit_timer_pop(gcc_jit_timer *timer, \ 215 const char *item_name) 216 217 Pop the top item from the timer's stack. 218 219 If "item_name" is provided, it must match that of the top item. 220 Alternatively, ``NULL`` can be passed in, to suppress checking. 221 222 This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test 223 for its presence using 224 225 .. code-block:: c 226 227 #ifdef LIBGCCJIT_HAVE_TIMING_API 228 229.. function:: void gcc_jit_timer_print(gcc_jit_timer *timer, \ 230 FILE *f_out) 231 232 Print timing information to the given stream about activity since 233 the timer was started. 234 235 This API entrypoint was added in :ref:`LIBGCCJIT_ABI_4`; you can test 236 for its presence using 237 238 .. code-block:: c 239 240 #ifdef LIBGCCJIT_HAVE_TIMING_API 241