82 static char profiling_file_name[PATH_MAX] =
"";
83 static const char *profiling_file_mode =
"a";
84 static int profiling_rule_json = 0;
99 static int profiling_rules_sort_orders[8] = {
112 static uint32_t profiling_rules_limit = UINT32_MAX;
116 #define SET_ONE(x) { \
117 profiling_rules_sort_orders[0] = (x); \
118 profiling_rules_sort_orders[1] = -1; \
131 if (strcmp(val,
"ticks") == 0) {
134 else if (strcmp(val,
"avgticks") == 0) {
137 else if (strcmp(val,
"avgticks_match") == 0) {
140 else if (strcmp(val,
"avgticks_no_match") == 0) {
143 else if (strcmp(val,
"checks") == 0) {
146 else if (strcmp(val,
"matches") == 0) {
149 else if (strcmp(val,
"maxticks") == 0) {
154 "Invalid profiling sort order: %s", val);
162 (uint16_t)strlen(val), val) <= 0) {
168 if (filename != NULL) {
173 snprintf(profiling_file_name,
sizeof(profiling_file_name),
174 "%s/%s", log_dir, filename);
178 profiling_file_mode =
"a";
180 profiling_file_mode =
"w";
186 profiling_rule_json = 1;
197 SCProfileSummarySortByTicks(
const void *a,
const void *b)
211 SCProfileSummarySortByAvgTicksMatch(
const void *a,
const void *b)
225 SCProfileSummarySortByAvgTicksNoMatch(
const void *a,
const void *b)
239 SCProfileSummarySortByAvgTicks(
const void *a,
const void *b)
253 SCProfileSummarySortByChecks(
const void *a,
const void *b)
267 SCProfileSummarySortByMatches(
const void *a,
const void *b)
281 SCProfileSummarySortByMaxTicks(
const void *a,
const void *b)
288 return s0->
max > s1->
max ? -1 : 1;
292 uint32_t count, uint64_t total_ticks,
293 const char *sort_desc)
299 json_t *js = json_object();
302 json_t *jsa = json_array();
308 gettimeofday(&tval, NULL);
310 json_object_set_new(js,
"timestamp", json_string(timebuf));
311 json_object_set_new(js,
"sort", json_string(sort_desc));
313 for (i = 0; i <
MIN(count, profiling_rules_limit); i++) {
317 if (summary[i].checks == 0)
320 json_t *jsm = json_object();
322 json_object_set_new(jsm,
"signature_id", json_integer(summary[i].sid));
323 json_object_set_new(jsm,
"gid", json_integer(summary[i].gid));
324 json_object_set_new(jsm,
"rev", json_integer(summary[i].rev));
326 json_object_set_new(jsm,
"checks", json_integer(summary[i].checks));
327 json_object_set_new(jsm,
"matches", json_integer(summary[i].matches));
329 json_object_set_new(jsm,
"ticks_total", json_integer(summary[i].ticks));
330 json_object_set_new(jsm,
"ticks_max", json_integer(summary[i].max));
331 json_object_set_new(jsm,
"ticks_avg", json_integer(summary[i].avgticks));
332 json_object_set_new(jsm,
"ticks_avg_match", json_integer(summary[i].avgticks_match));
333 json_object_set_new(jsm,
"ticks_avg_nomatch", json_integer(summary[i].avgticks_no_match));
335 double percent = (
long double)summary[i].ticks /
336 (
long double)total_ticks * 100;
337 json_object_set_new(jsm,
"percent", json_integer(percent));
338 json_array_append_new(jsa, jsm);
341 json_object_set_new(js,
"rules", jsa);
343 char *js_s = json_dumps(js,
344 JSON_PRESERVE_ORDER|JSON_COMPACT|JSON_ENSURE_ASCII|
349 fprintf(fp,
"%s", js_s);
355 uint32_t count, uint64_t total_ticks,
356 const char *sort_desc)
361 gettimeofday(&tval, NULL);
365 fprintf(fp,
" ----------------------------------------------"
366 "----------------------------\n");
367 fprintf(fp,
" Date: %" PRId32
"/%" PRId32
"/%04d -- "
368 "%02d:%02d:%02d.", tms->tm_mon + 1, tms->tm_mday, tms->tm_year + 1900,
369 tms->tm_hour,tms->tm_min, tms->tm_sec);
370 fprintf(fp,
" Sorted by: %s.\n", sort_desc);
371 fprintf(fp,
" ----------------------------------------------"
372 "----------------------------\n");
373 fprintf(fp,
" %-8s %-12s %-8s %-8s %-12s %-6s %-8s %-8s %-11s %-11s %-11s %-11s\n",
"Num",
"Rule",
"Gid",
"Rev",
"Ticks",
"%",
"Checks",
"Matches",
"Max Ticks",
"Avg Ticks",
"Avg Match",
"Avg No Match");
374 fprintf(fp,
" -------- "
387 for (i = 0; i <
MIN(count, profiling_rules_limit); i++) {
392 if (summary[i].checks == 0)
395 double percent = (
long double)summary[i].ticks /
396 (
long double)total_ticks * 100;
398 " %-8"PRIu32
" %-12u %-8"PRIu32
" %-8"PRIu32
" %-12"PRIu64
" %-6.2f %-8"PRIu64
" %-8"PRIu64
" %-11"PRIu64
" %-11.2f %-11.2f %-11.2f\n",
409 summary[i].avgticks_match,
410 summary[i].avgticks_no_match);
427 if (rules_ctx == NULL)
431 fp = fopen(profiling_file_name, profiling_file_mode);
449 uint32_t count = rules_ctx->
size;
450 uint64_t total_ticks = 0;
452 SCLogPerf(
"Dumping profiling data for %u rules.", count);
454 memset(summary, 0, summary_size);
455 for (i = 0; i < count; i++) {
463 if (summary[i].ticks > 0) {
464 summary[i].
avgticks = (
long double)summary[i].ticks / (
long double)summary[i].
checks;
471 if (summary[i].ticks_match > 0) {
473 (
long double)summary[i].
matches;
476 if (summary[i].ticks_no_match > 0) {
478 ((
long double)summary[i].
checks - (
long double)summary[i].matches);
480 total_ticks += summary[i].
ticks;
483 int *order = profiling_rules_sort_orders;
484 while (*order != -1) {
485 const char *sort_desc = NULL;
489 SCProfileSummarySortByTicks);
494 SCProfileSummarySortByAvgTicks);
495 sort_desc =
"average ticks";
499 SCProfileSummarySortByChecks);
500 sort_desc =
"number of checks";
504 SCProfileSummarySortByMatches);
505 sort_desc =
"number of matches";
509 SCProfileSummarySortByMaxTicks);
510 sort_desc =
"max ticks";
514 SCProfileSummarySortByAvgTicksMatch);
515 sort_desc =
"average ticks (match)";
519 SCProfileSummarySortByAvgTicksNoMatch);
520 sort_desc =
"average ticks (no match)";
523 if (profiling_rule_json) {
524 DumpJson(fp, summary, count, total_ticks, sort_desc);
526 DumpText(fp, summary, count, total_ticks, sort_desc);
534 SCLogPerf(
"Done dumping profiling data.");
579 if (pthread_mutex_init(&ctx->
data_m, NULL) != 0) {
581 "Failed to initialize hash table mutex.");
591 SCProfilingRuleDump(ctx);
592 if (ctx->
data != NULL)
594 pthread_mutex_destroy(&ctx->
data_m);
601 if (ctx == NULL|| ctx->
size == 0)
636 SCProfilingRuleThreadMerge(det_ctx->
de_ctx, det_ctx);
660 while (sig != NULL) {
672 while (sig != NULL) {
680 SCLogPerf(
"Registered %"PRIu32
" rule profiling counters.", count);