Skip to content

Commit 7d95de1

Browse files
axboegregkh
authored andcommitted
io_uring/sqpoll: be smarter on when to update the stime usage
commit a94e065 upstream. The current approach is a bit naive, and hence calls the time querying way too often. Only start the "doing work" timer when there's actual work to do, and then use that information to terminate (and account) the work time once done. This greatly reduces the frequency of these calls, when they cannot have changed anyway. Running a basic random reader that is setup to use SQPOLL, a profile before this change shows these as the top cycle consumers: + 32.60% iou-sqp-1074 [kernel.kallsyms] [k] thread_group_cputime_adjusted + 19.97% iou-sqp-1074 [kernel.kallsyms] [k] thread_group_cputime + 12.20% io_uring io_uring [.] submitter_uring_fn + 4.13% iou-sqp-1074 [kernel.kallsyms] [k] getrusage + 2.45% iou-sqp-1074 [kernel.kallsyms] [k] io_submit_sqes + 2.18% iou-sqp-1074 [kernel.kallsyms] [k] __pi_memset_generic + 2.09% iou-sqp-1074 [kernel.kallsyms] [k] cputime_adjust and after this change, top of profile looks as follows: + 36.23% io_uring io_uring [.] submitter_uring_fn + 23.26% iou-sqp-819 [kernel.kallsyms] [k] io_sq_thread + 10.14% iou-sqp-819 [kernel.kallsyms] [k] io_sq_tw + 6.52% iou-sqp-819 [kernel.kallsyms] [k] tctx_task_work_run + 4.82% iou-sqp-819 [kernel.kallsyms] [k] nvme_submit_cmds.part.0 + 2.91% iou-sqp-819 [kernel.kallsyms] [k] io_submit_sqes [...] 0.02% iou-sqp-819 [kernel.kallsyms] [k] cputime_adjust where it's spending the cycles on things that actually matter. Reported-by: Fengnan Chang <[email protected]> Cc: [email protected] Fixes: 3fcb9d1 ("io_uring/sqpoll: statistics of the true utilization of sq threads") Signed-off-by: Jens Axboe <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 09e5505 commit 7d95de1

File tree

1 file changed

+32
-11
lines changed

1 file changed

+32
-11
lines changed

io_uring/sqpoll.c

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ static inline bool io_sqd_events_pending(struct io_sq_data *sqd)
170170
return READ_ONCE(sqd->state);
171171
}
172172

173+
struct io_sq_time {
174+
bool started;
175+
u64 usec;
176+
};
177+
173178
u64 io_sq_cpu_usec(struct task_struct *tsk)
174179
{
175180
u64 utime, stime;
@@ -179,12 +184,24 @@ u64 io_sq_cpu_usec(struct task_struct *tsk)
179184
return stime;
180185
}
181186

182-
static void io_sq_update_worktime(struct io_sq_data *sqd, u64 usec)
187+
static void io_sq_update_worktime(struct io_sq_data *sqd, struct io_sq_time *ist)
188+
{
189+
if (!ist->started)
190+
return;
191+
ist->started = false;
192+
sqd->work_time += io_sq_cpu_usec(current) - ist->usec;
193+
}
194+
195+
static void io_sq_start_worktime(struct io_sq_time *ist)
183196
{
184-
sqd->work_time += io_sq_cpu_usec(current) - usec;
197+
if (ist->started)
198+
return;
199+
ist->started = true;
200+
ist->usec = io_sq_cpu_usec(current);
185201
}
186202

187-
static int __io_sq_thread(struct io_ring_ctx *ctx, bool cap_entries)
203+
static int __io_sq_thread(struct io_ring_ctx *ctx, struct io_sq_data *sqd,
204+
bool cap_entries, struct io_sq_time *ist)
188205
{
189206
unsigned int to_submit;
190207
int ret = 0;
@@ -197,6 +214,8 @@ static int __io_sq_thread(struct io_ring_ctx *ctx, bool cap_entries)
197214
if (to_submit || !wq_list_empty(&ctx->iopoll_list)) {
198215
const struct cred *creds = NULL;
199216

217+
io_sq_start_worktime(ist);
218+
200219
if (ctx->sq_creds != current_cred())
201220
creds = override_creds(ctx->sq_creds);
202221

@@ -278,7 +297,6 @@ static int io_sq_thread(void *data)
278297
unsigned long timeout = 0;
279298
char buf[TASK_COMM_LEN] = {};
280299
DEFINE_WAIT(wait);
281-
u64 start;
282300

283301
/* offload context creation failed, just exit */
284302
if (!current->io_uring) {
@@ -313,6 +331,7 @@ static int io_sq_thread(void *data)
313331
mutex_lock(&sqd->lock);
314332
while (1) {
315333
bool cap_entries, sqt_spin = false;
334+
struct io_sq_time ist = { };
316335

317336
if (io_sqd_events_pending(sqd) || signal_pending(current)) {
318337
if (io_sqd_handle_event(sqd))
@@ -321,25 +340,27 @@ static int io_sq_thread(void *data)
321340
}
322341

323342
cap_entries = !list_is_singular(&sqd->ctx_list);
324-
start = io_sq_cpu_usec(current);
325343
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) {
326-
int ret = __io_sq_thread(ctx, cap_entries);
344+
int ret = __io_sq_thread(ctx, sqd, cap_entries, &ist);
327345

328346
if (!sqt_spin && (ret > 0 || !wq_list_empty(&ctx->iopoll_list)))
329347
sqt_spin = true;
330348
}
331349
if (io_sq_tw(&retry_list, IORING_TW_CAP_ENTRIES_VALUE))
332350
sqt_spin = true;
333351

334-
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list)
335-
if (io_napi(ctx))
352+
list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) {
353+
if (io_napi(ctx)) {
354+
io_sq_start_worktime(&ist);
336355
io_napi_sqpoll_busy_poll(ctx);
356+
}
357+
}
358+
359+
io_sq_update_worktime(sqd, &ist);
337360

338361
if (sqt_spin || !time_after(jiffies, timeout)) {
339-
if (sqt_spin) {
340-
io_sq_update_worktime(sqd, start);
362+
if (sqt_spin)
341363
timeout = jiffies + sqd->sq_thread_idle;
342-
}
343364
if (unlikely(need_resched())) {
344365
mutex_unlock(&sqd->lock);
345366
cond_resched();

0 commit comments

Comments
 (0)