diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2022-08-29 12:26:26 -0400 |
---|---|---|
committer | Suren Baghdasaryan <surenb@google.com> | 2023-03-13 15:11:37 +0000 |
commit | 9b5b14aa2050bb761657c52ec2488ee2c4d074f9 (patch) | |
tree | aad554bad8bc3281f504e035666e96647998de13 | |
parent | ae3193f1356d204ea620fe6f81bdd459b41215d3 (diff) |
Code tagging based latency tracking: swait
This adds the ability to easily instrument code for measuring latency.
To use, add the following to calls to your code, at the start and end of
the event you wish to measure:
code_tag_time_stats_start(start_time);
code_tag_time_stats_finish(start_time);
Stastistics will then show up in debugfs under
/sys/kernel/debug/time_stats, listed by file and line number.
Stastics measured include weighted averages of frequency, duration, max
duration, as well as quantiles.
This patch also instruments all calls to init_wait and finish_wait,
which includes all calls to wait_event. Example debugfs output:
fs/xfs/xfs_trans_ail.c:746 module:xfs func:xfs_ail_push_all_sync
count: 17
rate: 0/sec
frequency: 2 sec
avg duration: 10 us
max duration: 232 us
quantiles (ns): 128 128 128 128 128 128 128 128 128 128 128 128 128 128 128
lib/sbitmap.c:813 module:sbitmap func:sbitmap_finish_wait
count: 3
rate: 0/sec
frequency: 4 sec
avg duration: 4 sec
max duration: 4 sec
quantiles (ns): 0 4288669120 4288669120 5360836048 5360836048 5360836048 5360836048 5360836048 5360836048 5360836048 5360836048 5360836048 5360836048 5360836048 5360836048
net/core/datagram.c:122 module:datagram func:__skb_wait_for_more_packets
count: 10
rate: 1/sec
frequency: 859 ms
avg duration: 472 ms
max duration: 30 sec
quantiles (ns): 0 12279 12279 15669 15669 15669 15669 17217 17217 17217 17217 17217 17217 17217 17217
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | include/linux/swait.h | 20 | ||||
-rw-r--r-- | kernel/sched/swait.c | 6 |
2 files changed, 21 insertions, 5 deletions
diff --git a/include/linux/swait.h b/include/linux/swait.h index 6a8c22b8c2a5..b935d3b027fd 100644 --- a/include/linux/swait.h +++ b/include/linux/swait.h @@ -48,11 +48,15 @@ struct swait_queue_head { struct swait_queue { struct task_struct *task; struct list_head task_list; +#ifdef CONFIG_CODETAG_TIME_STATS + u64 start_time; +#endif }; #define __SWAITQUEUE_INITIALIZER(name) { \ .task = current, \ .task_list = LIST_HEAD_INIT((name).task_list), \ + WAIT_QUEUE_ENTRY_START_TIME_INITIALIZER \ } #define DECLARE_SWAITQUEUE(name) \ @@ -151,8 +155,20 @@ extern void swake_up_locked(struct swait_queue_head *q); extern void prepare_to_swait_exclusive(struct swait_queue_head *q, struct swait_queue *wait, int state); extern long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state); -extern void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait); -extern void finish_swait(struct swait_queue_head *q, struct swait_queue *wait); +extern void __finish_swait_notrace(struct swait_queue_head *q, struct swait_queue *wait); +extern void finish_swait_notrace(struct swait_queue_head *q, struct swait_queue *wait); + +#define __finish_swait(_q, _wait) \ +do { \ + __finish_swait_notrace(_q, _wait); \ + codetag_time_stats_finish((_wait)->start_time); \ +} while (0) + +#define finish_swait(_q, _wait) \ +do { \ + finish_swait_notrace(_q, _wait); \ + codetag_time_stats_finish((_wait)->start_time); \ +} while (0) /* as per ___wait_event() but for swait, therefore "exclusive == 1" */ #define ___swait_event(wq, condition, state, ret, cmd) \ diff --git a/kernel/sched/swait.c b/kernel/sched/swait.c index 76b9b796e695..61d46ddfcd69 100644 --- a/kernel/sched/swait.c +++ b/kernel/sched/swait.c @@ -122,14 +122,14 @@ long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait } EXPORT_SYMBOL(prepare_to_swait_event); -void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait) +void __finish_swait_notrace(struct swait_queue_head *q, struct swait_queue *wait) { __set_current_state(TASK_RUNNING); if (!list_empty(&wait->task_list)) list_del_init(&wait->task_list); } -void finish_swait(struct swait_queue_head *q, struct swait_queue *wait) +void finish_swait_notrace(struct swait_queue_head *q, struct swait_queue *wait) { unsigned long flags; @@ -141,4 +141,4 @@ void finish_swait(struct swait_queue_head *q, struct swait_queue *wait) raw_spin_unlock_irqrestore(&q->lock, flags); } } -EXPORT_SYMBOL(finish_swait); +EXPORT_SYMBOL(finish_swait_notrace); |