Line data Source code
1 : /*
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 : *
6 : * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
7 : */
8 :
9 : /*
10 : * Martin Kersten
11 : * Performance profiler
12 : * A key issue in developing fast programs using the Monet database
13 : * back-end requires a keen eye on where performance is lost.
14 : * Although performance tracking and measurements are highly
15 : * application dependent, a simple to use tool makes life
16 : * a lot easier.
17 : *
18 : * Activation of the performance monitor has a global effect,
19 : * i.e. all concurrent actions on the kernel are traced,
20 : * but the events are only sent to the client initiated
21 : * the profiler thread.
22 : *
23 : * The profiler event can be handled in several ways.
24 : * The default strategy is to ship the event record immediately over a stream
25 : * to a performance monitor.
26 : * An alternative strategy is preparation of off-line performance analysis.
27 : *
28 : * To reduce the interference of performance measurement with
29 : * the experiments, the user can use an event cache, which is
30 : * emptied explicitly upon need.
31 : */
32 : /*
33 : * Using the Monet Performance Profiler is constrained by the mal_profiler.
34 : */
35 : #include "monetdb_config.h"
36 : #include "gdk.h"
37 : #include <time.h>
38 : #include "mal_stack.h"
39 : #include "mal_resolve.h"
40 : #include "mal_exception.h"
41 : #include "mal_client.h"
42 : #include "mal_profiler.h"
43 : #include "mal_interpreter.h"
44 : #include "mal_runtime.h"
45 :
46 : static str
47 0 : CMDopenProfilerStream(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pc)
48 : {
49 : (void) cntxt;
50 : (void) mb;
51 : (void) stk;
52 : (void) pc;
53 0 : return openProfilerStream(cntxt);
54 : }
55 :
56 : static str
57 0 : CMDcloseProfilerStream(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pc)
58 : {
59 : (void) mb;
60 : (void) stk;
61 : (void) pc;
62 0 : return closeProfilerStream(cntxt);
63 : }
64 :
65 : // initialize SQL tracing
66 : static str
67 1 : CMDstartProfiler(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pc)
68 : {
69 : (void)mb;
70 : (void) stk;
71 : (void) pc;
72 : (void) cntxt;
73 1 : return startProfiler(cntxt);
74 : }
75 :
76 : static str
77 1 : CMDstopProfiler(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
78 : {
79 : (void) mb;
80 : (void) stk;
81 : (void) pci;
82 :
83 1 : return stopProfiler(cntxt);
84 : }
85 :
86 : // called by the SQL front end optional a directory to keep the traces.
87 : static str
88 18 : CMDstartTrace(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
89 : {
90 : (void) mb;
91 : (void) stk;
92 : (void) pci;
93 18 : renameVariables(mb); // to keep in sink with explain
94 18 : return startTrace(cntxt);
95 : }
96 :
97 : static str
98 20 : CMDstopTrace(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
99 : {
100 : (void) mb;
101 : (void) stk;
102 : (void) pci;
103 20 : return stopTrace(cntxt);
104 : }
105 :
106 : static str
107 0 : CMDnoopProfiler(void *res)
108 : {
109 : (void) res; /* fool compiler */
110 0 : return MAL_SUCCEED;
111 : }
112 :
113 : static str
114 0 : CMDcleanupTraces(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
115 : {
116 : (void) mb;
117 : (void) stk;
118 : (void) pci;
119 0 : cleanupTraces(cntxt);
120 0 : return MAL_SUCCEED;
121 : }
122 :
123 : static str
124 4 : CMDgetTrace(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
125 : {
126 4 : str path = *getArgReference_str(stk,pci,1);
127 4 : bat *res = getArgReference_bat(stk,pci,0);
128 : BAT *bn;
129 :
130 : (void) cntxt; /* fool compiler */
131 : (void) mb;
132 4 : bn = getTrace(cntxt, path);
133 4 : if (bn) {
134 4 : BBPkeepref(*res = bn->batCacheid);
135 4 : return MAL_SUCCEED;
136 : }
137 0 : throw(MAL, "getTrace", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING "%s", path);
138 : }
139 :
140 : static str
141 2 : CMDgetprofilerlimit(int *res)
142 : {
143 2 : *res = getprofilerlimit();
144 2 : return MAL_SUCCEED;
145 : }
146 :
147 : static str
148 0 : CMDsetprofilerlimit(void *res, int *lim)
149 : {
150 : (void) res;
151 0 : setprofilerlimit(*lim);
152 0 : return MAL_SUCCEED;
153 : }
154 :
155 : /*
156 : * Tracing an active system.
157 : */
158 :
159 : static str
160 0 : CMDsetHeartbeat(void *res, int *ev)
161 : {
162 : (void) res;
163 0 : setHeartbeat(*ev);
164 0 : return MAL_SUCCEED;
165 : }
166 :
167 : static str
168 0 : CMDgetDiskReads(lng *ret)
169 : {
170 0 : *ret= getDiskReads();
171 0 : return MAL_SUCCEED;
172 : }
173 : static str
174 0 : CMDgetDiskWrites(lng *ret)
175 : {
176 0 : *ret= getDiskWrites();
177 0 : return MAL_SUCCEED;
178 : }
179 : static str
180 0 : CMDgetUserTime(lng *ret)
181 : {
182 0 : *ret= getUserTime();
183 0 : return MAL_SUCCEED;
184 : }
185 : static str
186 0 : CMDgetSystemTime(lng *ret)
187 : {
188 0 : *ret= getUserTime();
189 0 : return MAL_SUCCEED;
190 : }
191 :
192 : static str
193 5 : CMDcpustats(lng *user, lng *nice, lng *sys, lng *idle, lng *iowait)
194 : {
195 5 : profilerGetCPUStat(user,nice,sys,idle,iowait);
196 5 : return MAL_SUCCEED;
197 : }
198 :
199 : static str
200 5 : CMDcpuloadPercentage(int *cycles, int *io, lng *user, lng *nice, lng *sys, lng *idle, lng *iowait)
201 : {
202 : lng userN, niceN, sysN, idleN, iowaitN, N;
203 5 : *cycles = 0;
204 5 : *io = 0;
205 5 : profilerGetCPUStat(&userN,&niceN,&sysN,&idleN,&iowaitN);
206 5 : N = (userN - *user + niceN - *nice + sysN - *sys);
207 5 : if ( N){
208 0 : *cycles = (int) ( ((double) N) / (N + idleN - *idle + iowaitN - *iowait) *100);
209 0 : *io = (int) ( ((double) iowaitN- *iowait) / (N + idleN - *idle + iowaitN - *iowait) *100);
210 : }
211 5 : return MAL_SUCCEED;
212 : }
213 :
214 : #include "mel.h"
215 : mel_func profiler_init_funcs[] = {
216 : pattern("profiler", "start", CMDstartProfiler, false, "Start offline performance profiling", noargs),
217 : pattern("profiler", "stop", CMDstopProfiler, false, "Stop offline performance profiling", args(1,1, arg("",void))),
218 : pattern("profiler", "starttrace", CMDstartTrace, false, "Start collecting trace information", noargs),
219 : pattern("profiler", "stoptrace", CMDstopTrace, false, "Stop collecting trace information", args(1,1, arg("",void))),
220 : command("profiler", "setheartbeat", CMDsetHeartbeat, false, "Set heart beat performance tracing", args(1,2, arg("",void),arg("b",int))),
221 : command("profiler", "getlimit", CMDgetprofilerlimit, false, "Set profiler limit", args(1,1, arg("",int))),
222 : command("profiler", "setlimit", CMDsetprofilerlimit, false, "Get profiler limit", args(1,2, arg("",void),arg("l",int))),
223 : pattern("profiler", "openstream", CMDopenProfilerStream, false, "Start profiling the events, send to output stream", args(1,1, arg("",void))),
224 : pattern("profiler", "closestream", CMDcloseProfilerStream, false, "Stop offline proviling", args(1,1, arg("",void))),
225 : command("profiler", "noop", CMDnoopProfiler, false, "Fetch any pending performance events", args(1,1, arg("",void))),
226 : pattern("profiler", "getTrace", CMDgetTrace, false, "Get the trace details of a specific event", args(1,2, batargany("",1),arg("e",str))),
227 : pattern("profiler", "cleanup", CMDcleanupTraces, false, "Remove the temporary tables for profiling", args(1,1, arg("",void))),
228 : command("profiler", "getDiskReads", CMDgetDiskReads, false, "Obtain the number of physical reads", args(1,1, arg("",lng))),
229 : command("profiler", "getDiskWrites", CMDgetDiskWrites, false, "Obtain the number of physical reads", args(1,1, arg("",lng))),
230 : command("profiler", "getUserTime", CMDgetUserTime, false, "Obtain the user timing information.", args(1,1, arg("",lng))),
231 : command("profiler", "getSystemTime", CMDgetSystemTime, false, "Obtain the user timing information.", args(1,1, arg("",lng))),
232 : command("profiler", "cpustats", CMDcpustats, false, "Extract cpu statistics from the kernel", args(5,5, arg("user",lng),arg("nice",lng),arg("sys",lng),arg("idle",lng),arg("iowait",lng))),
233 : command("profiler", "cpuload", CMDcpuloadPercentage, false, "Calculate the average cpu load percentage and io waiting times", args(2,7, arg("cycles",int),arg("io",int),arg("user",lng),arg("nice",lng),arg("sys",lng),arg("idle",lng),arg("iowait",lng))),
234 : { .imp=NULL }
235 : };
236 : #include "mal_import.h"
237 : #ifdef _MSC_VER
238 : #undef read
239 : #pragma section(".CRT$XCU",read)
240 : #endif
241 257 : LIB_STARTUP_FUNC(init_profiler_mal)
242 257 : { mal_module("profiler", NULL, profiler_init_funcs); }
|