Skip to content

Commit 79b3f75

Browse files
committed
Report: Support max/min timestamp in report output
This patch introduces timestamps for special function calls that take the minimum or maximum time. With this capability, users can identify function calls that exhibit unusual execution times and investigate the underlying reasons. Example usage: $ uftrace report -f total-min-ts,total-max-ts Total min ts Total max ts Function ============ ============ ==================== 12.009 h 12.009 h main 12.009 h 12.009 h printf 12.009 h 12.009 h __monstartup 12.009 h 12.009 h __cxa_atexit Resolves: #1898 Signed-off-by: Hanyu Cui <[email protected]>
1 parent d79deba commit 79b3f75

File tree

5 files changed

+41
-8
lines changed

5 files changed

+41
-8
lines changed

utils/debug.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,12 @@ void print_time_unit(uint64_t delta_nsec)
384384
__print_time_unit(delta_nsec, false);
385385
}
386386

387+
void print_time_unit_padding(uint64_t delta_nsec, uint32_t padding)
388+
{
389+
pr_out("%*s", padding, "");
390+
__print_time_unit(delta_nsec, false);
391+
}
392+
387393
void print_diff_percent(uint64_t base_nsec, uint64_t pair_nsec)
388394
{
389395
double percent;

utils/field.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,16 @@ enum display_field_id {
3939
REPORT_F_TOTAL_TIME = 0,
4040
REPORT_F_TOTAL_TIME_AVG,
4141
REPORT_F_TOTAL_TIME_MIN,
42+
REPORT_F_TOTAL_TIME_MIN_TS,
4243
REPORT_F_TOTAL_TIME_MAX,
44+
REPORT_F_TOTAL_TIME_MAX_TS,
4345

4446
REPORT_F_SELF_TIME,
4547
REPORT_F_SELF_TIME_AVG,
4648
REPORT_F_SELF_TIME_MIN,
49+
REPORT_F_SELF_TIME_MIN_TS,
4750
REPORT_F_SELF_TIME_MAX,
51+
REPORT_F_SELF_TIME_MAX_TS,
4852

4953
REPORT_F_CALL,
5054
REPORT_F_SIZE,

utils/report.c

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ static void init_time_stat(struct report_time_stat *ts)
1414
ts->min = -1ULL;
1515
}
1616

17-
static void update_time_stat(struct report_time_stat *ts, uint64_t time_ns, bool recursive)
17+
static void update_time_stat(struct report_time_stat *ts, uint64_t time_ns, uint64_t timestamp,
18+
bool recursive)
1819
{
1920
if (recursive) {
2021
ts->rec += time_ns;
@@ -25,10 +26,14 @@ static void update_time_stat(struct report_time_stat *ts, uint64_t time_ns, bool
2526
ts->sum_sq += time_ns * time_ns;
2627
}
2728

28-
if (ts->min > time_ns)
29+
if (ts->min > time_ns) {
2930
ts->min = time_ns;
30-
if (ts->max < time_ns)
31+
ts->min_ts = timestamp;
32+
}
33+
if (ts->max < time_ns) {
3134
ts->max = time_ns;
35+
ts->max_ts = timestamp;
36+
}
3237
}
3338

3439
static void finish_time_stat(struct report_time_stat *ts, unsigned long call)
@@ -98,6 +103,7 @@ void report_update_node(struct uftrace_report_node *node, struct uftrace_task_re
98103
struct uftrace_fstack *fstack;
99104
uint64_t total_time;
100105
uint64_t self_time;
106+
uint64_t timestamp;
101107
bool recursive = false;
102108
int i;
103109

@@ -118,9 +124,10 @@ void report_update_node(struct uftrace_report_node *node, struct uftrace_task_re
118124

119125
total_time = fstack->total_time;
120126
self_time = fstack->total_time - fstack->child_time;
127+
timestamp = task->rstack->time - total_time;
121128

122-
update_time_stat(&node->total, total_time, recursive);
123-
update_time_stat(&node->self, self_time, false);
129+
update_time_stat(&node->total, total_time, timestamp, recursive);
130+
update_time_stat(&node->self, self_time, timestamp, false);
124131
node->call++;
125132
node->loc = loc;
126133
if (task->func != NULL)
@@ -769,6 +776,14 @@ void report_sort_tasks(struct uftrace_data *handle, struct rb_root *name_root,
769776
} \
770777
FIELD_STRUCT(_id, _name, _func, _header, 10)
771778

779+
#define FIELD_TIMESTAMP(_id, _name, _field, _func, _header) \
780+
static void print_##_func(struct field_data *fd) \
781+
{ \
782+
struct uftrace_report_node *node = fd->arg; \
783+
print_time_unit_padding(node->_field, 2); \
784+
} \
785+
FIELD_STRUCT(_id, _name, _func, _header, 12)
786+
772787
#define FIELD_UINT(_id, _name, _field, _func, _header) \
773788
static void print_##_func(struct field_data *fd) \
774789
{ \
@@ -869,10 +884,14 @@ FIELD_TIME(REPORT_F_TOTAL_TIME, total, total.sum, total, "Total time");
869884
FIELD_TIME(REPORT_F_TOTAL_TIME_AVG, total-avg, total.avg, total_avg, "Total avg");
870885
FIELD_TIME(REPORT_F_TOTAL_TIME_MIN, total-min, total.min, total_min, "Total min");
871886
FIELD_TIME(REPORT_F_TOTAL_TIME_MAX, total-max, total.max, total_max, "Total max");
887+
FIELD_TIMESTAMP(REPORT_F_TOTAL_TIME_MIN_TS, total-min-ts, total.min_ts, total_min_ts, "Total min ts");
888+
FIELD_TIMESTAMP(REPORT_F_TOTAL_TIME_MAX_TS, total-max-ts, total.max_ts, total_max_ts, "Total max ts");
872889
FIELD_TIME(REPORT_F_SELF_TIME, self, self.sum, self, "Self time");
873890
FIELD_TIME(REPORT_F_SELF_TIME_AVG, self-avg, self.avg, self_avg, "Self avg");
874891
FIELD_TIME(REPORT_F_SELF_TIME_MIN, self-min, self.min, self_min, "Self min");
875892
FIELD_TIME(REPORT_F_SELF_TIME_MAX, self-max, self.max, self_max, "Self max");
893+
FIELD_TIMESTAMP(REPORT_F_SELF_TIME_MIN_TS, self-min-ts, self.min_ts, self_min_ts, "Self min ts");
894+
FIELD_TIMESTAMP(REPORT_F_SELF_TIME_MAX_TS, self-max-ts, self.max_ts, self_max_ts, "Self max ts");
876895
FIELD_UINT(REPORT_F_CALL, call, call, call, "Calls");
877896
FIELD_UINT(REPORT_F_SIZE, size, size, size, "Size");
878897
FIELD_PERCENTAGE(REPORT_F_TOTAL_TIME_STDV, total-stdv, total.stdv, total_stdv, "Total stdv");
@@ -919,9 +938,10 @@ FIELD_UINT(REPORT_F_TASK_NR_FUNC, func, call, task_nr_func, "Num funcs");
919938

920939
/* index of this table should be matched to display_field_id */
921940
static struct display_field *field_table[] = {
922-
&field_total, &field_total_avg, &field_total_min, &field_total_max,
923-
&field_self, &field_self_avg, &field_self_min, &field_self_max,
924-
&field_call, &field_size, &field_total_stdv, &field_self_stdv,
941+
&field_total, &field_total_avg, &field_total_min, &field_total_min_ts,
942+
&field_total_max, &field_total_max_ts, &field_self, &field_self_avg,
943+
&field_self_min, &field_self_min_ts, &field_self_max, &field_self_max_ts,
944+
&field_call, &field_size, &field_total_stdv, &field_self_stdv,
925945
};
926946

927947
/* index of this table should be matched to display_field_id */

utils/report.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ struct report_time_stat {
2323
double stdv;
2424
uint64_t min;
2525
uint64_t max;
26+
uint64_t min_ts;
27+
uint64_t max_ts;
2628
};
2729

2830
struct uftrace_report_node {

utils/utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ extern clockid_t clock_source;
363363
void setup_clock_id(const char *clock_str);
364364

365365
void print_time_unit(uint64_t delta_nsec);
366+
void print_time_unit_padding(uint64_t delta_nsec, uint32_t padding);
366367
void print_diff_percent(uint64_t base_nsec, uint64_t delta_nsec);
367368
void print_diff_time_unit(uint64_t base_nsec, uint64_t pair_nsec);
368369
void print_diff_count(uint64_t base, uint64_t pair);

0 commit comments

Comments
 (0)