From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id C19AEC83F01 for ; Sun, 27 Aug 2023 00:37:38 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id A4B398E0005; Sat, 26 Aug 2023 20:37:37 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 9FB6B8E0001; Sat, 26 Aug 2023 20:37:37 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 8C3B28E0005; Sat, 26 Aug 2023 20:37:37 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 7EC2E8E0001 for ; Sat, 26 Aug 2023 20:37:37 -0400 (EDT) Received: from smtpin18.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 5190514036A for ; Sun, 27 Aug 2023 00:37:37 +0000 (UTC) X-FDA: 81168021354.18.1749D2D Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf22.hostedemail.com (Postfix) with ESMTP id 9A45CC0009 for ; Sun, 27 Aug 2023 00:37:35 +0000 (UTC) Authentication-Results: imf22.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=Lo1DIY8g; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf22.hostedemail.com: domain of sj@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=sj@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1693096655; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:references:dkim-signature; bh=TLz5pVGZjQKqBabfGtEv5P2bas6p9XJHMe7z2lyAl2w=; b=YjpVIjWp0uMM4iOk8KiXKDspEzLG/9azUz98TyHGC8JClpNxtNB4hHglWZ+6PjHaUnKydB CQRqerEmypWTgEKpCaKT77sqSheU15H+0jCgAa4Su/vUwmBtkGRe7cPjb/eNV++RsThwsB hZRGhdI++eNcPHXQzPVMP7D6+o/hrcQ= ARC-Authentication-Results: i=1; imf22.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=Lo1DIY8g; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf22.hostedemail.com: domain of sj@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=sj@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1693096655; a=rsa-sha256; cv=none; b=rrPqZKRZPrjp0jVO2Db2Zg9gdEP+MaNMT1xhRZg7fPrESvHyGwQLAsZ346cZDPDvrzXCoS FfpgRESVpXY55OCSQpJPm1bKCfL//aP1cibOEzOkCCuPwB57zXXAimLJTPNz6Jmzq5ue8p B5GodWQzmU+cRM/A0PkqYaFVEfAHF5M= Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 799C760AC2; Sun, 27 Aug 2023 00:37:34 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 67961C433C8; Sun, 27 Aug 2023 00:37:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1693096653; bh=I6+EjuMhnMqA0A4SsaSLYkN9eETY2McANvNftJkI0dM=; h=From:To:Cc:Subject:Date:From; b=Lo1DIY8gtf7Th1wUHVHnXZJ3Je8HOVS7taKpYUE+ksqp1o3qqQAi8al7eP48M5cN+ GmG3Vqx/Bw8Cdmp8aIippxj1Or6nMYiNT/Eb2pC5XUgj011KZd4sLeKySRbWdSGTxG CA50E5u+hRNcxigWAd2byVptPZbNQElXZ9f7fNIJzGjx7qq0FjqfSA2ahVPDnkysmH gTrM485E4xuUdgtBCU8us98C6IYD424xWrIMR17/kc2ZQFETWgJ+IuQc67NHRGH7Zt WG8jgH85rjBPuhISdj4mqrlUtJ7aCQa++ElPL23Q0QJ63OGyc4tKTX5ZTNq/OPHaic ureLkSb8a+7LQ== From: SeongJae Park To: damon@lists.linux.dev Cc: SeongJae Park , Andrew Morton , linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH] mm/damon/core: use number of passed access sampling as a timer Date: Sun, 27 Aug 2023 00:37:27 +0000 Message-Id: <20230827003727.49369-1-sj@kernel.org> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 9A45CC0009 X-Rspam-User: X-Rspamd-Server: rspam04 X-Stat-Signature: xd4eafpuan179iunrxuk4crry9r5jbfy X-HE-Tag: 1693096655-94457 X-HE-Meta: U2FsdGVkX1+ca3GWZ4Phnj7SOQxJX9NqDO73Q+xYJxCKOwiCuDfmWiyvPTRPI2O8GPRfFAVFEtgWpBdMshbOamIi4HE39UunTwBnVk3Om5+R5SzfsfXarKBnM/BBB7ImbYXG2cf95NSgRa53YdCV8E6ZyB3acl8ASxq8sZfWaiISuEiSDd2PlQXt1Hja1EklApZDg13rdw+moiU+rf1dW+DOhpdBcEpMeCh4uHQLhTgftbgHWlk0Pj4334xjEUoh7I6KMp2VaUw5RU/13P61O89uS+Qrsi0OETBtgemJeVkY2yf5g+yOqSnzJZhLRxpRWU9dpMi2dSnr3SUlapn2QzvNiP/IdAYshBS2wKHI14SCY1CSZZKZDAgUZMwOVRALSxQG3FqzaYjnE0668kq8Z6gTJYWhqZgGR3Dw8/JKvGx8pcj324s8cjen8BhZmvD6Y/4lIJkv72qm3JmyqpQv0TlYezC5TBO0BjdIL+JcJWLHLgTMEM6YAZeVswoO665/f5XgxMN9l/KAJL/UfyWn62jYP1J4kI3NRxlrNYabY22OGrOofJdxyvE3lP3vd5GsT1W+uDasoaFEWMnBQ3w9kgMZ6+Npq7Q72JoYoYX/gp/Wvftq0qKJmcUto0cOI8c2wDV+ylvj2fg3xnA5whkuN3fq1+j6rY9hl904RSnrjGx6zNZWzEGHdc/vA0y5AC5Rq/sSMa3FVbzo1XFP/mwJNOuMp9128qRsXvJxi117vQkUkTS73vvfNmiCeYOBx2CHuT5+/66X/o8ISXSLuDDaM+NtZsnaFNoscGyXNtTnRNTk57tNYVp3PymEg/h0OoXcdx/YC8hkjjSVYSTlUBdJ2Eo9NYfHYR7/0nx2nstL5KvtObIRAS7EevgP4RnbkkxzGHyIMIeIP37/6hfJGeFGNBwO0huE08Dm7LcSMBGSo13rqhydIXe+7oAx3YM3scrnk0dS1iXs2jkcWFShI7P ktAVtFMw rK05QxPCcMlwoUtblv91z4nT8BYHFp2iF91cDcVhRu0v1cNtYj18cbZUpJ7BtdPv5GeXCwI6gaBwQzGTLZ1opmfzozP4VwDXR2b3k6lLFm6qyihfcQuPlwOK4Sn8hrb6lWjzRyGqfQXN6aUcvzr3CAND5YjPngmMbdnL/mx51snclC4sXqefn5fFXrGLBeJyifsqRmCZrGA3HlYfbVuWSht+51NED6E3wnJx/5UbpAwypb6a7TKiRiMJFqOwN/NNYTa+mxVtltvb29xA8TbFdDrZUUcf7jInWtl7xVlADjTddTqlo1zd4FwIHW9TOi420TC5tuY6uQglYuWFsAyoicJ2QsQ== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: DAMON sleeps for sampling interval after each sampling, and check if it's time for further doing aggregation and ops updating using ktime_get_coarse_ts64() and baseline timestamps for the two periodic operations. That's for making the operations occur at deterministic timing. However, it turned out it could still result in indeterministic and even not-that-intuitive results. After all, timer functions, and especially sleep functions that DAMON uses to wait for specific timing, could contain some errors. Those errors are legal, so no problem. However, depending on such legal timing errors, the nr_accesses can be larger than aggregation interval divided by sampling interval. For example, with the default setting (5 ms sampling interval and 100 ms aggregation interval) we frequently show regions having nr_accesses larger than 20. Also, if the execution of a DAMOS scheme takes a long time, next aggregation could happen before enough number of samples are collected. Since access check sampling is the smallest unit work of DAMON, using the number of passed sampling intervals as the DAMON-internal timer can easily avoid these problems. That is, convert aggregation and ops update intervals to numbers of sampling intervals that need to be passed before those operations be executed, count the number of passed sampling intervals, and invoke the operations as soon as the specific amount of sampling intervals passed. Make the change. Signed-off-by: SeongJae Park --- include/linux/damon.h | 14 ++++++-- mm/damon/core.c | 84 +++++++++++++++++++------------------------ 2 files changed, 48 insertions(+), 50 deletions(-) diff --git a/include/linux/damon.h b/include/linux/damon.h index ab3089de1478..9a32b8fd0bd3 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -524,8 +524,18 @@ struct damon_ctx { struct damon_attrs attrs; /* private: internal use only */ - struct timespec64 last_aggregation; - struct timespec64 last_ops_update; + /* number of sample intervals that passed since this context started */ + unsigned long passed_sample_intervals; + /* + * number of sample intervals that should be passed before next + * aggregation + */ + unsigned long next_aggregation_sis; + /* + * number of sample intervals that should be passed before next ops + * update + */ + unsigned long next_ops_update_sis; /* public: */ struct task_struct *kdamond; diff --git a/mm/damon/core.c b/mm/damon/core.c index 988dc39e44b1..83af336bb0e6 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -456,8 +456,11 @@ struct damon_ctx *damon_new_ctx(void) ctx->attrs.aggr_interval = 100 * 1000; ctx->attrs.ops_update_interval = 60 * 1000 * 1000; - ktime_get_coarse_ts64(&ctx->last_aggregation); - ctx->last_ops_update = ctx->last_aggregation; + ctx->passed_sample_intervals = 0; + ctx->next_aggregation_sis = ctx->attrs.aggr_interval / + ctx->attrs.sample_interval; + ctx->next_ops_update_sis = ctx->attrs.ops_update_interval / + ctx->attrs.sample_interval; mutex_init(&ctx->kdamond_lock); @@ -577,6 +580,9 @@ static void damon_update_monitoring_results(struct damon_ctx *ctx, */ int damon_set_attrs(struct damon_ctx *ctx, struct damon_attrs *attrs) { + unsigned long sample_interval; + unsigned long remaining_interval_us; + if (attrs->min_nr_regions < 3) return -EINVAL; if (attrs->min_nr_regions > attrs->max_nr_regions) @@ -584,6 +590,20 @@ int damon_set_attrs(struct damon_ctx *ctx, struct damon_attrs *attrs) if (attrs->sample_interval > attrs->aggr_interval) return -EINVAL; + sample_interval = attrs->sample_interval ? attrs->sample_interval : 1; + + /* adjust next_aggregation_sis */ + remaining_interval_us = ctx->attrs.sample_interval * + (ctx->next_aggregation_sis - ctx->passed_sample_intervals); + ctx->next_aggregation_sis = ctx->passed_sample_intervals + + remaining_interval_us / sample_interval; + + /* adjust next_ops_update_sis */ + remaining_interval_us = ctx->attrs.sample_interval * + (ctx->next_ops_update_sis - ctx->passed_sample_intervals); + ctx->next_ops_update_sis = ctx->passed_sample_intervals + + remaining_interval_us / sample_interval; + damon_update_monitoring_results(ctx, attrs); ctx->attrs = *attrs; return 0; @@ -757,38 +777,6 @@ int damon_stop(struct damon_ctx **ctxs, int nr_ctxs) return err; } -/* - * damon_check_reset_time_interval() - Check if a time interval is elapsed. - * @baseline: the time to check whether the interval has elapsed since - * @interval: the time interval (microseconds) - * - * See whether the given time interval has passed since the given baseline - * time. If so, it also updates the baseline to current time for next check. - * - * Return: true if the time interval has passed, or false otherwise. - */ -static bool damon_check_reset_time_interval(struct timespec64 *baseline, - unsigned long interval) -{ - struct timespec64 now; - - ktime_get_coarse_ts64(&now); - if ((timespec64_to_ns(&now) - timespec64_to_ns(baseline)) < - interval * 1000) - return false; - *baseline = now; - return true; -} - -/* - * Check whether it is time to flush the aggregated information - */ -static bool kdamond_aggregate_interval_passed(struct damon_ctx *ctx) -{ - return damon_check_reset_time_interval(&ctx->last_aggregation, - ctx->attrs.aggr_interval); -} - /* * Reset the aggregated monitoring results ('nr_accesses' of each region). */ @@ -1292,18 +1280,6 @@ static void kdamond_split_regions(struct damon_ctx *ctx) last_nr_regions = nr_regions; } -/* - * Check whether it is time to check and apply the operations-related data - * structures. - * - * Returns true if it is. - */ -static bool kdamond_need_update_operations(struct damon_ctx *ctx) -{ - return damon_check_reset_time_interval(&ctx->last_ops_update, - ctx->attrs.ops_update_interval); -} - /* * Check whether current monitoring should be stopped * @@ -1436,6 +1412,8 @@ static int kdamond_fn(void *data) sz_limit = damon_region_sz_limit(ctx); while (!kdamond_need_stop(ctx)) { + unsigned long sample_interval; + if (kdamond_wait_activation(ctx)) break; @@ -1446,11 +1424,17 @@ static int kdamond_fn(void *data) break; kdamond_usleep(ctx->attrs.sample_interval); + ctx->passed_sample_intervals++; if (ctx->ops.check_accesses) max_nr_accesses = ctx->ops.check_accesses(ctx); - if (kdamond_aggregate_interval_passed(ctx)) { + sample_interval = ctx->attrs.sample_interval ? + ctx->attrs.sample_interval : 1; + if (ctx->passed_sample_intervals == + ctx->next_aggregation_sis) { + ctx->next_aggregation_sis += + ctx->attrs.aggr_interval / sample_interval; kdamond_merge_regions(ctx, max_nr_accesses / 10, sz_limit); @@ -1465,7 +1449,11 @@ static int kdamond_fn(void *data) ctx->ops.reset_aggregated(ctx); } - if (kdamond_need_update_operations(ctx)) { + if (ctx->passed_sample_intervals == + ctx->next_ops_update_sis) { + ctx->next_ops_update_sis += + ctx->attrs.ops_update_interval / + sample_interval; if (ctx->ops.update) ctx->ops.update(ctx); sz_limit = damon_region_sz_limit(ctx); -- 2.25.1