suricata
util-profiling.h
Go to the documentation of this file.
1 /* Copyright (C) 2007-2012 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Endace Technology Limited.
22  * \author Victor Julien <victor@inliniac.net>
23  */
24 
25 #ifndef __UTIL_PROFILE_H__
26 #define __UTIL_PROFILE_H__
27 
28 #ifdef PROFILING
29 
30 #include "util-profiling-locks.h"
31 #include "util-cpu.h"
32 
33 extern int profiling_rules_enabled;
34 extern int profiling_packets_enabled;
35 extern int profiling_sghs_enabled;
36 extern __thread int profiling_rules_entered;
37 
41 
42 #define RULE_PROFILING_START(p) \
43  uint64_t profile_rule_start_ = 0; \
44  uint64_t profile_rule_end_ = 0; \
45  if (profiling_rules_enabled && SCProfileRuleStart((p))) { \
46  if (profiling_rules_entered > 0) { \
47  SCLogError(SC_ERR_FATAL, "Re-entered profiling, exiting."); \
48  exit(1); \
49  } \
50  profiling_rules_entered++; \
51  profile_rule_start_ = UtilCpuGetTicks(); \
52  }
53 
54 #define RULE_PROFILING_END(ctx, r, m, p) \
55  if (profiling_rules_enabled && ((p)->flags & PKT_PROFILE)) { \
56  profile_rule_end_ = UtilCpuGetTicks(); \
57  SCProfilingRuleUpdateCounter(ctx, r->profiling_id, \
58  profile_rule_end_ - profile_rule_start_, m); \
59  profiling_rules_entered--; \
60  }
61 
62 extern int profiling_keyword_enabled;
63 extern __thread int profiling_keyword_entered;
64 
65 #define KEYWORD_PROFILING_SET_LIST(ctx, list) { \
66  (ctx)->keyword_perf_list = (list); \
67 }
68 
69 #define KEYWORD_PROFILING_START \
70  uint64_t profile_keyword_start_ = 0; \
71  uint64_t profile_keyword_end_ = 0; \
72  if (profiling_keyword_enabled) { \
73  if (profiling_keyword_entered > 0) { \
74  SCLogError(SC_ERR_FATAL, "Re-entered profiling, exiting."); \
75  abort(); \
76  } \
77  profiling_keyword_entered++; \
78  profile_keyword_start_ = UtilCpuGetTicks(); \
79  }
80 
81 /* we allow this macro to be called if profiling_keyword_entered == 0,
82  * so that we don't have to refactor some of the detection code. */
83 #define KEYWORD_PROFILING_END(ctx, type, m) \
84  if (profiling_keyword_enabled && profiling_keyword_entered) { \
85  profile_keyword_end_ = UtilCpuGetTicks(); \
86  SCProfilingKeywordUpdateCounter((ctx),(type),(profile_keyword_end_ - profile_keyword_start_),(m)); \
87  profiling_keyword_entered--; \
88  }
89 
91 
92 #define PACKET_PROFILING_START(p) \
93  if (profiling_packets_enabled) { \
94  (p)->profile = SCProfilePacketStart(); \
95  if ((p)->profile != NULL) \
96  (p)->profile->ticks_start = UtilCpuGetTicks(); \
97  }
98 
99 #define PACKET_PROFILING_RESTART(p) \
100  if (profiling_packets_enabled) { \
101  if ((p)->profile != NULL) \
102  (p)->profile->ticks_start = UtilCpuGetTicks(); \
103  }
104 
105 #define PACKET_PROFILING_END(p) \
106  if (profiling_packets_enabled && (p)->profile != NULL) { \
107  (p)->profile->ticks_end = UtilCpuGetTicks(); \
108  SCProfilingAddPacket((p)); \
109  }
110 
111 #ifdef PROFILE_LOCKING
112 #define PACKET_PROFILING_RESET_LOCKS do { \
113  mutex_lock_cnt = 0; \
114  mutex_lock_wait_ticks = 0; \
115  mutex_lock_contention = 0; \
116  spin_lock_cnt = 0; \
117  spin_lock_wait_ticks = 0; \
118  spin_lock_contention = 0; \
119  rww_lock_cnt = 0; \
120  rww_lock_wait_ticks = 0; \
121  rww_lock_contention = 0; \
122  rwr_lock_cnt = 0; \
123  rwr_lock_wait_ticks = 0; \
124  rwr_lock_contention = 0; \
125  locks_idx = 0; \
126  record_locks = 1;\
127  } while (0)
128 
129 #define PACKET_PROFILING_COPY_LOCKS(p, id) do { \
130  (p)->profile->tmm[(id)].mutex_lock_cnt = mutex_lock_cnt; \
131  (p)->profile->tmm[(id)].mutex_lock_wait_ticks = mutex_lock_wait_ticks; \
132  (p)->profile->tmm[(id)].mutex_lock_contention = mutex_lock_contention; \
133  (p)->profile->tmm[(id)].spin_lock_cnt = spin_lock_cnt; \
134  (p)->profile->tmm[(id)].spin_lock_wait_ticks = spin_lock_wait_ticks; \
135  (p)->profile->tmm[(id)].spin_lock_contention = spin_lock_contention; \
136  (p)->profile->tmm[(id)].rww_lock_cnt = rww_lock_cnt; \
137  (p)->profile->tmm[(id)].rww_lock_wait_ticks = rww_lock_wait_ticks; \
138  (p)->profile->tmm[(id)].rww_lock_contention = rww_lock_contention; \
139  (p)->profile->tmm[(id)].rwr_lock_cnt = rwr_lock_cnt; \
140  (p)->profile->tmm[(id)].rwr_lock_wait_ticks = rwr_lock_wait_ticks; \
141  (p)->profile->tmm[(id)].rwr_lock_contention = rwr_lock_contention; \
142  record_locks = 0; \
143  SCProfilingAddPacketLocks((p)); \
144  } while(0)
145 #else
146 #define PACKET_PROFILING_RESET_LOCKS
147 #define PACKET_PROFILING_COPY_LOCKS(p, id)
148 #endif
149 
150 #define PACKET_PROFILING_TMM_START(p, id) \
151  if (profiling_packets_enabled && (p)->profile != NULL) { \
152  if ((id) < TMM_SIZE) { \
153  (p)->profile->tmm[(id)].ticks_start = UtilCpuGetTicks();\
154  PACKET_PROFILING_RESET_LOCKS; \
155  } \
156  }
157 
158 #define PACKET_PROFILING_TMM_END(p, id) \
159  if (profiling_packets_enabled && (p)->profile != NULL) { \
160  if ((id) < TMM_SIZE) { \
161  PACKET_PROFILING_COPY_LOCKS((p), (id)); \
162  (p)->profile->tmm[(id)].ticks_end = UtilCpuGetTicks(); \
163  } \
164  }
165 
166 #define FLOWWORKER_PROFILING_START(p, id) \
167  if (profiling_packets_enabled && (p)->profile != NULL) { \
168  if ((id) < PROFILE_FLOWWORKER_SIZE) { \
169  (p)->profile->flowworker[(id)].ticks_start = UtilCpuGetTicks();\
170  } \
171  }
172 
173 #define FLOWWORKER_PROFILING_END(p, id) \
174  if (profiling_packets_enabled && (p)->profile != NULL) { \
175  if ((id) < PROFILE_FLOWWORKER_SIZE) { \
176  (p)->profile->flowworker[(id)].ticks_end = UtilCpuGetTicks(); \
177  } \
178  }
179 
180 #define PACKET_PROFILING_RESET(p) \
181  if (profiling_packets_enabled && (p)->profile != NULL) { \
182  SCFree((p)->profile); \
183  (p)->profile = NULL; \
184  }
185 
186 #define PACKET_PROFILING_APP_START(dp, id) \
187  if (profiling_packets_enabled) { \
188  (dp)->ticks_start = UtilCpuGetTicks(); \
189  (dp)->alproto = (id); \
190  }
191 
192 #define PACKET_PROFILING_APP_END(dp, id) \
193  if (profiling_packets_enabled) { \
194  BUG_ON((id) != (dp)->alproto); \
195  (dp)->ticks_end = UtilCpuGetTicks(); \
196  if ((dp)->ticks_start != 0 && (dp)->ticks_start < ((dp)->ticks_end)) { \
197  (dp)->ticks_spent = ((dp)->ticks_end - (dp)->ticks_start); \
198  } \
199  }
200 
201 #define PACKET_PROFILING_APP_PD_START(dp) \
202  if (profiling_packets_enabled) { \
203  (dp)->proto_detect_ticks_start = UtilCpuGetTicks(); \
204  }
205 
206 #define PACKET_PROFILING_APP_PD_END(dp) \
207  if (profiling_packets_enabled) { \
208  (dp)->proto_detect_ticks_end = UtilCpuGetTicks(); \
209  if ((dp)->proto_detect_ticks_start != 0 && (dp)->proto_detect_ticks_start < ((dp)->proto_detect_ticks_end)) { \
210  (dp)->proto_detect_ticks_spent = \
211  ((dp)->proto_detect_ticks_end - (dp)->proto_detect_ticks_start); \
212  } \
213  }
214 
215 #define PACKET_PROFILING_APP_RESET(dp) \
216  if (profiling_packets_enabled) { \
217  (dp)->ticks_start = 0; \
218  (dp)->ticks_end = 0; \
219  (dp)->ticks_spent = 0; \
220  (dp)->alproto = 0; \
221  (dp)->proto_detect_ticks_start = 0; \
222  (dp)->proto_detect_ticks_end = 0; \
223  (dp)->proto_detect_ticks_spent = 0; \
224  }
225 
226 #define PACKET_PROFILING_APP_STORE(dp, p) \
227  if (profiling_packets_enabled && (p)->profile != NULL) { \
228  if ((dp)->alproto < ALPROTO_MAX) { \
229  (p)->profile->app[(dp)->alproto].ticks_spent += (dp)->ticks_spent; \
230  (p)->profile->proto_detect += (dp)->proto_detect_ticks_spent; \
231  } \
232  }
233 
234 #define PACKET_PROFILING_DETECT_START(p, id) \
235  if (profiling_packets_enabled && (p)->profile != NULL) { \
236  if ((id) < PROF_DETECT_SIZE) { \
237  (p)->profile->detect[(id)].ticks_start = UtilCpuGetTicks(); \
238  } \
239  }
240 
241 #define PACKET_PROFILING_DETECT_END(p, id) \
242  if (profiling_packets_enabled && (p)->profile != NULL) { \
243  if ((id) < PROF_DETECT_SIZE) { \
244  (p)->profile->detect[(id)].ticks_end = UtilCpuGetTicks();\
245  if ((p)->profile->detect[(id)].ticks_start != 0 && \
246  (p)->profile->detect[(id)].ticks_start < (p)->profile->detect[(id)].ticks_end) { \
247  (p)->profile->detect[(id)].ticks_spent += \
248  ((p)->profile->detect[(id)].ticks_end - (p)->profile->detect[(id)].ticks_start); \
249  } \
250  } \
251  }
252 
253 #define PACKET_PROFILING_LOGGER_START(p, id) \
254  if (profiling_packets_enabled && (p)->profile != NULL) { \
255  if ((id) < LOGGER_SIZE) { \
256  (p)->profile->logger[(id)].ticks_start = UtilCpuGetTicks(); \
257  } \
258  }
259 
260 #define PACKET_PROFILING_LOGGER_END(p, id) \
261  if (profiling_packets_enabled && (p)->profile != NULL) { \
262  if ((id) < LOGGER_SIZE) { \
263  (p)->profile->logger[(id)].ticks_end = UtilCpuGetTicks();\
264  if ((p)->profile->logger[(id)].ticks_start != 0 && \
265  (p)->profile->logger[(id)].ticks_start < (p)->profile->logger[(id)].ticks_end) { \
266  (p)->profile->logger[(id)].ticks_spent += \
267  ((p)->profile->logger[(id)].ticks_end - (p)->profile->logger[(id)].ticks_start); \
268  } \
269  } \
270  }
271 
272 #define SGH_PROFILING_RECORD(det_ctx, sgh) \
273  if (profiling_sghs_enabled) { \
274  SCProfilingSghUpdateCounter((det_ctx), (sgh)); \
275  }
276 
277 extern int profiling_prefilter_enabled;
278 extern __thread int profiling_prefilter_entered;
279 
280 #define PREFILTER_PROFILING_START \
281  uint64_t profile_prefilter_start_ = 0; \
282  uint64_t profile_prefilter_end_ = 0; \
283  if (profiling_prefilter_enabled) { \
284  if (profiling_prefilter_entered > 0) { \
285  SCLogError(SC_ERR_FATAL, "Re-entered profiling, exiting."); \
286  abort(); \
287  } \
288  profiling_prefilter_entered++; \
289  profile_prefilter_start_ = UtilCpuGetTicks(); \
290  }
291 
292 /* we allow this macro to be called if profiling_prefilter_entered == 0,
293  * so that we don't have to refactor some of the detection code. */
294 #define PREFILTER_PROFILING_END(ctx, profile_id) \
295  if (profiling_prefilter_enabled && profiling_prefilter_entered) { \
296  profile_prefilter_end_ = UtilCpuGetTicks(); \
297  if (profile_prefilter_end_ > profile_prefilter_start_) \
298  SCProfilingPrefilterUpdateCounter((ctx),(profile_id),(profile_prefilter_end_ - profile_prefilter_start_)); \
299  profiling_prefilter_entered--; \
300  }
301 
302 void SCProfilingRulesGlobalInit(void);
305 void SCProfilingRuleUpdateCounter(DetectEngineThreadCtx *, uint16_t, uint64_t, int);
308 
310 void SCProfilingKeywordDestroyCtx(DetectEngineCtx *);//struct SCProfileKeywordDetectCtx_ *);
312 void SCProfilingKeywordUpdateCounter(DetectEngineThreadCtx *det_ctx, int id, uint64_t ticks, int match);
315 
320 void SCProfilingPrefilterUpdateCounter(DetectEngineThreadCtx *det_ctx, int id, uint64_t ticks);
323 
324 void SCProfilingSghsGlobalInit(void);
330 
331 void SCProfilingInit(void);
332 void SCProfilingDestroy(void);
333 void SCProfilingRegisterTests(void);
334 void SCProfilingDump(void);
335 
336 #else
337 
338 #define RULE_PROFILING_START(p)
339 #define RULE_PROFILING_END(a,b,c,p)
340 
341 #define KEYWORD_PROFILING_SET_LIST(a,b)
342 #define KEYWORD_PROFILING_START
343 #define KEYWORD_PROFILING_END(a,b,c)
344 
345 #define PACKET_PROFILING_START(p)
346 #define PACKET_PROFILING_RESTART(p)
347 #define PACKET_PROFILING_END(p)
348 
349 #define PACKET_PROFILING_TMM_START(p, id)
350 #define PACKET_PROFILING_TMM_END(p, id)
351 
352 #define PACKET_PROFILING_RESET(p)
353 
354 #define PACKET_PROFILING_APP_START(dp, id)
355 #define PACKET_PROFILING_APP_END(dp, id)
356 #define PACKET_PROFILING_APP_RESET(dp)
357 #define PACKET_PROFILING_APP_STORE(dp, p)
358 
359 #define PACKET_PROFILING_APP_PD_START(dp)
360 #define PACKET_PROFILING_APP_PD_END(dp)
361 
362 #define PACKET_PROFILING_DETECT_START(p, id)
363 #define PACKET_PROFILING_DETECT_END(p, id)
364 
365 #define PACKET_PROFILING_LOGGER_START(p, id)
366 #define PACKET_PROFILING_LOGGER_END(p, id)
367 
368 #define SGH_PROFILING_RECORD(det_ctx, sgh)
369 
370 #define FLOWWORKER_PROFILING_START(p, id)
371 #define FLOWWORKER_PROFILING_END(p, id)
372 
373 #define PREFILTER_PROFILING_START
374 #define PREFILTER_PROFILING_END(ctx, profile_id)
375 
376 #endif /* PROFILING */
377 
378 #endif /* ! __UTIL_PROFILE_H__ */
int profiling_prefilter_enabled
void SCProfilingRuleUpdateCounter(DetectEngineThreadCtx *, uint16_t, uint64_t, int)
Update a rule counter.
void SCProfilingRegisterTests(void)
int SCProfileRuleStart(Packet *p)
void SCProfilingSghDestroyCtx(DetectEngineCtx *)
Per pkt stats storage.
Definition: decode.h:373
void SCProfilingInit(void)
Initialize profiling.
PktProfiling * SCProfilePacketStart(void)
void SCProfilingPrintPacketProfile(Packet *)
void SCProfilingPrefilterThreadCleanup(DetectEngineThreadCtx *)
Container for matching data for a signature group.
Definition: detect.h:1295
void SCProfilingKeywordThreadSetup(struct SCProfileKeywordDetectCtx_ *, DetectEngineThreadCtx *)
void SCProfilingAddPacket(Packet *)
void SCProfilingKeywordUpdateCounter(DetectEngineThreadCtx *det_ctx, int id, uint64_t ticks, int match)
Update a rule counter.
void SCProfilingKeywordThreadCleanup(DetectEngineThreadCtx *)
int profiling_packets_enabled
main detection engine ctx
Definition: detect.h:720
int profiling_keyword_enabled
void SCProfilingRulesGlobalInit(void)
void SCProfilingDestroy(void)
Free resources used by profiling.
void SCProfilingRuleThreadCleanup(DetectEngineThreadCtx *)
void SCProfilingKeywordInitCounters(DetectEngineCtx *)
Register the keyword profiling counters.
__thread int profiling_rules_entered
void SCProfilingDump(void)
void SCProfilingSghInitCounters(DetectEngineCtx *)
Register the keyword profiling counters.
void SCProfilingPrefilterDestroyCtx(DetectEngineCtx *)
void SCProfilingSghsGlobalInit(void)
void SCProfilingRuleInitCounters(DetectEngineCtx *)
Register the rule profiling counters.
int profiling_sghs_enabled
__thread int profiling_keyword_entered
void SCProfilingRuleDestroyCtx(struct SCProfileDetectCtx_ *)
void SCProfilingPrefilterInitCounters(DetectEngineCtx *)
Register the prefilter profiling counters.
void SCProfilingKeywordDestroyCtx(DetectEngineCtx *)
void SCProfilingPrefilterThreadSetup(struct SCProfilePrefilterDetectCtx_ *, DetectEngineThreadCtx *)
__thread int profiling_prefilter_entered
void SCProfilingSghThreadSetup(struct SCProfileSghDetectCtx_ *, DetectEngineThreadCtx *)
void SCProfilingPrefilterUpdateCounter(DetectEngineThreadCtx *det_ctx, int id, uint64_t ticks)
Update a rule counter.
void SCProfilingSghUpdateCounter(DetectEngineThreadCtx *det_ctx, const SigGroupHead *sgh)
Update a rule counter.
void SCProfilingKeywordsGlobalInit(void)
int profiling_rules_enabled
void SCProfilingPrefilterGlobalInit(void)
void SCProfilingSghThreadCleanup(DetectEngineThreadCtx *)
void SCProfilingRuleThreadSetup(struct SCProfileDetectCtx_ *, DetectEngineThreadCtx *)