]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/jit/docs/topics/performance.rst
Update copyright years.
[thirdparty/gcc.git] / gcc / jit / docs / topics / performance.rst
1 .. Copyright (C) 2015-2024 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 <https://www.gnu.org/licenses/>.
17
18 .. default-domain:: c
19
20 Performance
21 ===========
22
23 The timing API
24 --------------
25
26 As of GCC 6, libgccjit exposes a timing API, for printing reports on
27 how long was spent in different parts of code.
28
29 You can create a :c:type:`gcc_jit_timer` instance, which will
30 measure time spent since its creation. The timer maintains a stack
31 of "timer items": as control flow moves through your code, you can push
32 and pop named items relating to your code onto the stack, and the timer
33 will account the time spent accordingly.
34
35 You can also asssociate a timer with a :c:type:`gcc_jit_context`, in
36 which case the time spent inside compilation will be subdivided.
37
38 For 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
88 giving output like this, showing the internal GCC items at the top, then
89 client 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
122 The 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