-
Notifications
You must be signed in to change notification settings - Fork 0
/
plprofiler.h
231 lines (207 loc) · 6.82 KB
/
plprofiler.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/* ----------------------------------------------------------------------
*
* plprofiler.h
*
* Declarations for profiling plugin for PL/pgSQL instrumentation
*
* Copyright (c) 2014-2022, OSCG-Partners
* Copyright (c) 2008-2014, PostgreSQL Global Development Group
* Copyright 2006,2007 - EnterpriseDB, Inc.
*
* Major Change History:
* 2012 - Removed from PostgreSQL plDebugger Extension
* 2015 - Resurrected as standalone plProfiler by OpenSCG
* 2016 - Rewritten as v2 to use shared hash tables, have lower overhead
* - v3 Major performance improvements, flame graph UI
*
* ----------------------------------------------------------------------
*/
#ifndef PLPROFILER_H
#define PLPROFILER_H
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include "access/hash.h"
#include "access/htup.h"
#if PG_VERSION_NUM >= 90300
#include "access/htup_details.h"
#endif
#include "access/sysattr.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/pg_extension.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "commands/extension.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "plpgsql.h"
#include "storage/ipc.h"
#include "storage/spin.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/palloc.h"
#include "utils/syscache.h"
PG_MODULE_MAGIC;
#define PL_PROFILE_COLS 5
#define PL_CALLGRAPH_COLS 5
#define PL_FUNCS_SRC_COLS 3
#define PL_MAX_STACK_DEPTH 200
#define PL_MIN_FUNCTIONS 2000
#define PL_MIN_CALLGRAPH 20000
#define PL_MIN_LINES 200000
#define PL_DBG_PRINT_STACK(_d, _s) do { \
int _i; \
printf("stack %s: db=%d bt=", _d, _s.db_oid); \
for (_i = 0; _i < PL_MAX_STACK_DEPTH && _s.stack[_i] != InvalidOid; _i++) { \
printf("%d,", _s.stack[_i]); \
} \
printf("\n"); \
} while(0);
/**********************************************************************
* Type and structure definitions
**********************************************************************/
/* ----
* profilerLineInfo
*
* Per source code line stats kept in the profilerInfo below, which
* is the data we put into the plugin_info of the executor state.
* ----
*/
typedef struct
{
int64 us_max; /* Slowest iteration of this stmt */
int64 us_total; /* Total time spent executing this stmt */
int64 exec_count; /* Number of times we executed this stmt */
instr_time start_time; /* Start time for this statement */
} profilerLineInfo;
/* ----
* profilerInfo
*
* The information we keep in the estate->plugin_info.
* ----
*/
typedef struct
{
Oid fn_oid; /* The functions OID */
int line_count; /* Number of lines in this function */
profilerLineInfo *line_info; /* Performance counters for each line */
} profilerInfo;
/* ----
* linestatsHashKey
*
* Hash key for the linestats hash tables (both local and shared).
* ----
*/
typedef struct
{
Oid db_oid; /* The OID of the database */
Oid fn_oid; /* The OID of the function */
} linestatsHashKey;
/* ----
* linestatsLineInfo
*
* Per source code line statistics kept in the linestats hash table.
* ----
*/
typedef struct
{
int64 us_max; /* Maximum execution time of statement */
int64 us_total; /* Total sum of statement exec time */
int64 exec_count; /* Count of statement executions */
} linestatsLineInfo;
/* ----
* linestatsEntry
*
* Per function data kept in the linestats hash table.
* ----
*/
typedef struct
{
linestatsHashKey key; /* hash key of entry */
slock_t mutex; /* Spin lock for updating counters */
int line_count; /* Number of lines in this function */
linestatsLineInfo *line_info; /* Performance counters for each line */
} linestatsEntry;
typedef struct callGraphKey
{
Oid db_oid;
Oid stack[PL_MAX_STACK_DEPTH];
} callGraphKey;
typedef struct callGraphEntry
{
callGraphKey key;
slock_t mutex;
PgStat_Counter callCount;
uint64 totalTime;
uint64 childTime;
uint64 selfTime;
} callGraphEntry;
typedef struct
{
LWLockId lock;
bool profiler_enabled_global;
int profiler_enabled_pid;
int profiler_collect_interval;
bool callgraph_overflow;
bool functions_overflow;
bool lines_overflow;
int lines_used;
linestatsLineInfo line_info[1];
} profilerSharedState;
/**********************************************************************
* Exported function prototypes
**********************************************************************/
void _PG_init(void);
void _PG_fini(void);
Datum pl_profiler_get_stack(PG_FUNCTION_ARGS);
Datum pl_profiler_linestats_local(PG_FUNCTION_ARGS);
Datum pl_profiler_linestats_shared(PG_FUNCTION_ARGS);
Datum pl_profiler_callgraph_local(PG_FUNCTION_ARGS);
Datum pl_profiler_callgraph_shared(PG_FUNCTION_ARGS);
Datum pl_profiler_func_oids_local(PG_FUNCTION_ARGS);
Datum pl_profiler_func_oids_shared(PG_FUNCTION_ARGS);
Datum pl_profiler_funcs_source(PG_FUNCTION_ARGS);
Datum pl_profiler_reset_local(PG_FUNCTION_ARGS);
Datum pl_profiler_reset_shared(PG_FUNCTION_ARGS);
Datum pl_profiler_set_enabled_global(PG_FUNCTION_ARGS);
Datum pl_profiler_get_enabled_global(PG_FUNCTION_ARGS);
Datum pl_profiler_set_enabled_local(PG_FUNCTION_ARGS);
Datum pl_profiler_get_enabled_local(PG_FUNCTION_ARGS);
Datum pl_profiler_set_enabled_pid(PG_FUNCTION_ARGS);
Datum pl_profiler_get_enabled_pid(PG_FUNCTION_ARGS);
Datum pl_profiler_set_collect_interval(PG_FUNCTION_ARGS);
Datum pl_profiler_get_collect_interval(PG_FUNCTION_ARGS);
Datum pl_profiler_collect_data(PG_FUNCTION_ARGS);
Datum pl_profiler_callgraph_overflow(PG_FUNCTION_ARGS);
Datum pl_profiler_functions_overflow(PG_FUNCTION_ARGS);
Datum pl_profiler_lines_overflow(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(pl_profiler_get_stack);
PG_FUNCTION_INFO_V1(pl_profiler_linestats_local);
PG_FUNCTION_INFO_V1(pl_profiler_linestats_shared);
PG_FUNCTION_INFO_V1(pl_profiler_callgraph_local);
PG_FUNCTION_INFO_V1(pl_profiler_callgraph_shared);
PG_FUNCTION_INFO_V1(pl_profiler_func_oids_local);
PG_FUNCTION_INFO_V1(pl_profiler_func_oids_shared);
PG_FUNCTION_INFO_V1(pl_profiler_funcs_source);
PG_FUNCTION_INFO_V1(pl_profiler_reset_local);
PG_FUNCTION_INFO_V1(pl_profiler_reset_shared);
PG_FUNCTION_INFO_V1(pl_profiler_set_enabled_global);
PG_FUNCTION_INFO_V1(pl_profiler_get_enabled_global);
PG_FUNCTION_INFO_V1(pl_profiler_set_enabled_local);
PG_FUNCTION_INFO_V1(pl_profiler_get_enabled_local);
PG_FUNCTION_INFO_V1(pl_profiler_set_enabled_pid);
PG_FUNCTION_INFO_V1(pl_profiler_get_enabled_pid);
PG_FUNCTION_INFO_V1(pl_profiler_set_collect_interval);
PG_FUNCTION_INFO_V1(pl_profiler_get_collect_interval);
PG_FUNCTION_INFO_V1(pl_profiler_collect_data);
PG_FUNCTION_INFO_V1(pl_profiler_callgraph_overflow);
PG_FUNCTION_INFO_V1(pl_profiler_functions_overflow);
PG_FUNCTION_INFO_V1(pl_profiler_lines_overflow);
#endif /* PLPROFILER_H */