From patchwork Sat Feb 24 01:10:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13570171 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 33FAF17C9; Sat, 24 Feb 2024 01:10:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737022; cv=none; b=WxTfwSQLZLvJAiSB/B/8KODv+35Mzv/ZeqRXCyf5vHa1sdLPZXSzsf8E5RY/fckwljlAUccWUsRLwUQ6u2a87yx6Hth7adG1V6cQNuyB+Mbi9Hd0A7XOqTxeuATNfxlUa0Fa56HHZNw6XSG18QUt7eJ+bryPHYSGKz8mmm/pl2U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737022; c=relaxed/simple; bh=m/dGn8S+Tun6ctgDshvujNW5mlJCoNbY7DUPJFApM/A=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=WIBIqJHmC/3XTQgxn+pYo2jTRBoMvK7tdJMq0K2pPD6cE/fOFIXIYqYIezpVaoafxqZ5CJqdaRsiGUH+CtMyd1XhnDS7SBH2rrUQINc0VUdaMa4lixOUvM8giPF4sLQV1tGLMCrNUFFNbki2J+JpVcaHaDIh1uUn9b9cnjiKYqA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ro9cjf/q; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ro9cjf/q" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B58D7C433C7; Sat, 24 Feb 2024 01:10:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708737021; bh=m/dGn8S+Tun6ctgDshvujNW5mlJCoNbY7DUPJFApM/A=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Ro9cjf/q2cHCcquHPuUDHaQzSC5wXBIlSFxeXJ5jDUVGf1h9siSXu3Ni39ZDTnJXS b+hkazhno9vxHCMeUC6+dZihxhYlIXxzTXKlu2vFCC4FL+f9K9Epkmo25/PJPlvXJ8 5cjYuuIxTim7c4bRFj0t4rk+2g9jEeQUGP/v+OFDn0NEK91CaYekA9aCqcButtGGQa n3InHRJnNkaKgKPPAnS87LtZDYc0PDk+X7nuHipaJPTPxsZeeOQtLeUDUd8ytctw3X mWO4xdzF0j2zQ4znwJnYvVF07/mdRIvHpJTd4rb1nLlI9J2cwPKIbosa97EPqJECls CQMIFT2Y8sBww== Date: Fri, 23 Feb 2024 17:10:21 -0800 Subject: [PATCH 01/10] time_stats: report lifetime of the stats object From: "Darrick J. Wong" To: akpm@linux-foundation.org, daniel@gluo.nz, kent.overstreet@linux.dev, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, linux-bcachefs@vger.kernel.org, linux-kernel@vger.kernel.org Message-ID: <170873667957.1860949.223294173509859015.stgit@frogsfrogsfrogs> In-Reply-To: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> References: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Capture the initialization time of the time_stats object so that we can report how long the counter has been observing data. Signed-off-by: Darrick J. Wong Signed-off-by: Kent Overstreet --- include/linux/time_stats.h | 2 ++ lib/time_stats.c | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/include/linux/time_stats.h b/include/linux/time_stats.h index caefa7aba65a0..eb1957cb77c0d 100644 --- a/include/linux/time_stats.h +++ b/include/linux/time_stats.h @@ -78,6 +78,8 @@ struct time_stats { u64 last_event_start; struct quantiles quantiles; + u64 start_time; + struct mean_and_variance duration_stats; struct mean_and_variance_weighted duration_stats_weighted; struct mean_and_variance freq_stats; diff --git a/lib/time_stats.c b/lib/time_stats.c index 081aeba88b535..8df4b55fc6337 100644 --- a/lib/time_stats.c +++ b/lib/time_stats.c @@ -158,10 +158,16 @@ static void seq_buf_time_units_aligned(struct seq_buf *out, u64 ns) seq_buf_printf(out, "%8llu %s", div64_u64(ns, u->nsecs), u->name); } +static inline u64 time_stats_lifetime(const struct time_stats *stats) +{ + return local_clock() - stats->start_time; +} + void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats) { s64 f_mean = 0, d_mean = 0; u64 f_stddev = 0, d_stddev = 0; + u64 lifetime = time_stats_lifetime(stats); if (stats->buffer) { int cpu; @@ -183,6 +189,9 @@ void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats) } seq_buf_printf(out, "count: %llu\n", stats->duration_stats.n); + seq_buf_printf(out, "lifetime: "); + seq_buf_time_units_aligned(out, lifetime); + seq_buf_printf(out, "\n"); seq_buf_printf(out, " since mount recent\n"); @@ -263,6 +272,7 @@ void time_stats_init(struct time_stats *stats) stats->freq_stats_weighted.weight = 8; stats->min_duration = U64_MAX; stats->min_freq = U64_MAX; + stats->start_time = local_clock(); spin_lock_init(&stats->lock); } EXPORT_SYMBOL_GPL(time_stats_init); From patchwork Sat Feb 24 01:10:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13570172 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CCF374A04; Sat, 24 Feb 2024 01:10:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737037; cv=none; b=m/AAgGdj5KzWDPs33RLXck70+dKnANejoxq/xRFdHl4Nkh5jIAuGHCxWPcpuQedDBAxA15/MxEPF/aE0/bHyLJ8ls+wsT9uOmEhgHVzesDb6mq2S+hH2vwvB+wh6Dry6+/ZbxSQN8SHeKJXwlNixjO6e5vgtnqD5mOjnZmkTX8c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737037; c=relaxed/simple; bh=msKREk70q3ImqTUICukC5SdxHULI8AGb91OrJny9Oqw=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aZSolXQ3UBUA3rCWE0tQJ2adwHGo+jjHjNCSFDB5FcPa0dETS7dOV0pj6CvNiePwGO38TxFehG0vJRw0TAVynV252hOwb7eYNooGj86StQ0NQZy9XYKp4gUBtIv15iD05k6lbZtVgWekw9DBgvWekP7GkP1Peyg/r5Dxt/UBXZc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kkL76DTz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kkL76DTz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5CF9BC433F1; Sat, 24 Feb 2024 01:10:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708737037; bh=msKREk70q3ImqTUICukC5SdxHULI8AGb91OrJny9Oqw=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=kkL76DTzKcDSTjQSwB4C+ysgvOdvQkmyW1Sqj5/8ldjh/t2gAxF4QM8+KjTp/FMai 14hEgTJFsvRdedSplR0NSp5AeWtJ52axfGdOR/34A5uG04/0MqE57GPOw4CiusIuLD QT2wOhFSGIGhhVr3riwpU5MUfQBmC2t0GC6SbZ37XmHbVii6B9FEYIG/R4JMpooFuo 1GSXmwAIhaYxAjG1L4WJ4CCJh7GSP6FjYLUDydkRT0J5f9ozp922wTinWZFAs9J9+t a4ywM60luStALdGRxsjkl5MvMmH5LquqDO8yvUCMdTWc6bDMuwMEl6SX6R+MYNMbFb ICgpzBuqfkO8Q== Date: Fri, 23 Feb 2024 17:10:36 -0800 Subject: [PATCH 02/10] time_stats: split stats-with-quantiles into a separate structure From: "Darrick J. Wong" To: akpm@linux-foundation.org, daniel@gluo.nz, kent.overstreet@linux.dev, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, linux-bcachefs@vger.kernel.org, linux-kernel@vger.kernel.org Message-ID: <170873667973.1860949.13781519053507360563.stgit@frogsfrogsfrogs> In-Reply-To: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> References: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Currently, struct time_stats has the optional ability to quantize the information that it collects. This is /probably/ useful for callers who want to see quantized information, but it more than doubles the size of the structure from 224 bytes to 464. For users who don't care about that (e.g. upcoming xfs patches) and want to avoid wasting 240 bytes per counter, split the two into separate pieces. Signed-off-by: Darrick J. Wong Signed-off-by: Kent Overstreet --- fs/bcachefs/bcachefs.h | 2 +- fs/bcachefs/io_write.c | 2 +- fs/bcachefs/super.c | 10 ++++------ fs/bcachefs/sysfs.c | 4 ++-- fs/bcachefs/util.c | 7 ++++--- include/linux/time_stats.h | 36 ++++++++++++++++++++++++++++++++++-- lib/time_stats.c | 17 ++++++++++------- 7 files changed, 56 insertions(+), 22 deletions(-) diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index 92547d6fd2d95..04e4a65909a4f 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -594,7 +594,7 @@ struct bch_dev { /* The rest of this all shows up in sysfs */ atomic64_t cur_latency[2]; - struct time_stats io_latency[2]; + struct time_stats_quantiles io_latency[2]; #define CONGESTED_MAX 1024 atomic_t congested; diff --git a/fs/bcachefs/io_write.c b/fs/bcachefs/io_write.c index 8123a84320e3f..3fa2cb1d5b13a 100644 --- a/fs/bcachefs/io_write.c +++ b/fs/bcachefs/io_write.c @@ -88,7 +88,7 @@ void bch2_latency_acct(struct bch_dev *ca, u64 submit_time, int rw) bch2_congested_acct(ca, io_latency, now, rw); - __time_stats_update(&ca->io_latency[rw], submit_time, now); + __time_stats_update(&ca->io_latency[rw].stats, submit_time, now); } #endif diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index c491c5e102287..2c238030fb5d7 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -1168,8 +1168,8 @@ static void bch2_dev_free(struct bch_dev *ca) bch2_dev_buckets_free(ca); free_page((unsigned long) ca->sb_read_scratch); - time_stats_exit(&ca->io_latency[WRITE]); - time_stats_exit(&ca->io_latency[READ]); + time_stats_quantiles_exit(&ca->io_latency[WRITE]); + time_stats_quantiles_exit(&ca->io_latency[READ]); percpu_ref_exit(&ca->io_ref); percpu_ref_exit(&ca->ref); @@ -1260,10 +1260,8 @@ static struct bch_dev *__bch2_dev_alloc(struct bch_fs *c, INIT_WORK(&ca->io_error_work, bch2_io_error_work); - time_stats_init(&ca->io_latency[READ]); - time_stats_init(&ca->io_latency[WRITE]); - ca->io_latency[READ].quantiles_enabled = true; - ca->io_latency[WRITE].quantiles_enabled = true; + time_stats_quantiles_init(&ca->io_latency[READ]); + time_stats_quantiles_init(&ca->io_latency[WRITE]); ca->mi = bch2_mi_to_cpu(member); diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c index cee80c47feea2..c86a93a8d8fc8 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -930,10 +930,10 @@ SHOW(bch2_dev) sysfs_print(io_latency_write, atomic64_read(&ca->cur_latency[WRITE])); if (attr == &sysfs_io_latency_stats_read) - bch2_time_stats_to_text(out, &ca->io_latency[READ]); + bch2_time_stats_to_text(out, &ca->io_latency[READ].stats); if (attr == &sysfs_io_latency_stats_write) - bch2_time_stats_to_text(out, &ca->io_latency[WRITE]); + bch2_time_stats_to_text(out, &ca->io_latency[WRITE].stats); sysfs_printf(congested, "%u%%", clamp(atomic_read(&ca->congested), 0, CONGESTED_MAX) diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c index 88853513a15fa..ef620bfe76cd2 100644 --- a/fs/bcachefs/util.c +++ b/fs/bcachefs/util.c @@ -365,6 +365,7 @@ static inline void pr_name_and_units(struct printbuf *out, const char *name, u64 void bch2_time_stats_to_text(struct printbuf *out, struct time_stats *stats) { + struct quantiles *quantiles = time_stats_to_quantiles(stats); s64 f_mean = 0, d_mean = 0; u64 f_stddev = 0, d_stddev = 0; @@ -465,17 +466,17 @@ void bch2_time_stats_to_text(struct printbuf *out, struct time_stats *stats) printbuf_tabstops_reset(out); - if (stats->quantiles_enabled) { + if (quantiles) { int i = eytzinger0_first(NR_QUANTILES); const struct time_unit *u = - pick_time_units(stats->quantiles.entries[i].m); + pick_time_units(quantiles->entries[i].m); u64 last_q = 0; prt_printf(out, "quantiles (%s):\t", u->name); eytzinger0_for_each(i, NR_QUANTILES) { bool is_last = eytzinger0_next(i, NR_QUANTILES) == -1; - u64 q = max(stats->quantiles.entries[i].m, last_q); + u64 q = max(quantiles->entries[i].m, last_q); prt_printf(out, "%llu ", div_u64(q, u->nsecs)); if (is_last) prt_newline(out); diff --git a/include/linux/time_stats.h b/include/linux/time_stats.h index eb1957cb77c0d..c05490101d197 100644 --- a/include/linux/time_stats.h +++ b/include/linux/time_stats.h @@ -27,6 +27,7 @@ #include #include #include +#include struct time_unit { const char *name; @@ -67,7 +68,6 @@ struct time_stat_buffer { struct time_stats { spinlock_t lock; - bool quantiles_enabled; /* all fields are in nanoseconds */ u64 min_duration; u64 max_duration; @@ -76,7 +76,12 @@ struct time_stats { u64 min_freq; u64 last_event; u64 last_event_start; - struct quantiles quantiles; + +/* + * Is this really a struct time_stats_quantiled? Hide this flag in the least + * significant bit of the start time to avoid blowing up the structure size. + */ +#define TIME_STATS_HAVE_QUANTILES (1ULL << 0) u64 start_time; @@ -87,6 +92,22 @@ struct time_stats { struct time_stat_buffer __percpu *buffer; }; +struct time_stats_quantiles { + struct time_stats stats; + struct quantiles quantiles; +}; + +static inline struct quantiles *time_stats_to_quantiles(struct time_stats *stats) +{ + struct time_stats_quantiles *statq; + + if (!(stats->start_time & TIME_STATS_HAVE_QUANTILES)) + return NULL; + + statq = container_of(stats, struct time_stats_quantiles, stats); + return &statq->quantiles; +} + void __time_stats_clear_buffer(struct time_stats *, struct time_stat_buffer *); void __time_stats_update(struct time_stats *stats, u64, u64); @@ -133,4 +154,15 @@ void time_stats_to_seq_buf(struct seq_buf *, struct time_stats *); void time_stats_exit(struct time_stats *); void time_stats_init(struct time_stats *); +static inline void time_stats_quantiles_exit(struct time_stats_quantiles *statq) +{ + time_stats_exit(&statq->stats); +} +static inline void time_stats_quantiles_init(struct time_stats_quantiles *statq) +{ + time_stats_init(&statq->stats); + statq->stats.start_time |= TIME_STATS_HAVE_QUANTILES; + memset(&statq->quantiles, 0, sizeof(statq->quantiles)); +} + #endif /* _LINUX_TIME_STATS_H */ diff --git a/lib/time_stats.c b/lib/time_stats.c index 8df4b55fc6337..767b1a340e805 100644 --- a/lib/time_stats.c +++ b/lib/time_stats.c @@ -69,6 +69,8 @@ static inline void time_stats_update_one(struct time_stats *stats, u64 duration, freq; if (time_after64(end, start)) { + struct quantiles *quantiles = time_stats_to_quantiles(stats); + duration = end - start; mean_and_variance_update(&stats->duration_stats, duration); mean_and_variance_weighted_update(&stats->duration_stats_weighted, duration); @@ -76,8 +78,8 @@ static inline void time_stats_update_one(struct time_stats *stats, stats->min_duration = min(stats->min_duration, duration); stats->total_duration += duration; - if (stats->quantiles_enabled) - quantiles_update(&stats->quantiles, duration); + if (quantiles) + quantiles_update(quantiles, duration); } if (stats->last_event && time_after64(end, stats->last_event)) { @@ -160,11 +162,12 @@ static void seq_buf_time_units_aligned(struct seq_buf *out, u64 ns) static inline u64 time_stats_lifetime(const struct time_stats *stats) { - return local_clock() - stats->start_time; + return local_clock() - (stats->start_time & ~TIME_STATS_HAVE_QUANTILES); } void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats) { + struct quantiles *quantiles = time_stats_to_quantiles(stats); s64 f_mean = 0, d_mean = 0; u64 f_stddev = 0, d_stddev = 0; u64 lifetime = time_stats_lifetime(stats); @@ -239,17 +242,17 @@ void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats) seq_buf_time_units_aligned(out, mean_and_variance_weighted_get_stddev(stats->freq_stats_weighted)); seq_buf_printf(out, "\n"); - if (stats->quantiles_enabled) { + if (quantiles) { int i = eytzinger0_first(NR_QUANTILES); const struct time_unit *u = - pick_time_units(stats->quantiles.entries[i].m); + pick_time_units(quantiles->entries[i].m); u64 last_q = 0; seq_buf_printf(out, "quantiles (%s):\t", u->name); eytzinger0_for_each(i, NR_QUANTILES) { bool is_last = eytzinger0_next(i, NR_QUANTILES) == -1; - u64 q = max(stats->quantiles.entries[i].m, last_q); + u64 q = max(quantiles->entries[i].m, last_q); seq_buf_printf(out, "%llu ", div_u64(q, u->nsecs)); if (is_last) seq_buf_printf(out, "\n"); @@ -272,7 +275,7 @@ void time_stats_init(struct time_stats *stats) stats->freq_stats_weighted.weight = 8; stats->min_duration = U64_MAX; stats->min_freq = U64_MAX; - stats->start_time = local_clock(); + stats->start_time = local_clock() & ~TIME_STATS_HAVE_QUANTILES; spin_lock_init(&stats->lock); } EXPORT_SYMBOL_GPL(time_stats_init); From patchwork Sat Feb 24 01:10:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13570173 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3C0C63AC; Sat, 24 Feb 2024 01:10:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737053; cv=none; b=TA3voLpo6OyXFqHpTMs1+ucsyr9PiIap+wDO0l1vbTVCKGjBWpDaCh1y4khVc/glowL8D1iJ5yaT5z9yBNJeyPcNKkBAuOqei7EBesyc7gTOe3lS8ZzlBlZgji7QFNIf3Q9ZBpLhzSrQCH6GGudLtxxz/FLNBiXLwQcA/MEiB3Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737053; c=relaxed/simple; bh=eJon+naYLvX2TtPG4PA+bOIKoeqRl8FeptOhgYTmTjY=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TkWS7CqtztPQFb4lye3Qheo9Wh8B9SRVFcoBFWNRVRfRiklceMSN2MztIwEiD1VKbSQJxjgNCUrhRXghpbkszpjF3FRjMtkv6s3SxntA5bRUXhzNiDcgWKruFvE3TgS4Qv387+sip6PZtZF0KdRzuLbboKeXeqHwh8QyVDrnFcY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=caEkkQyz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="caEkkQyz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 157A1C433C7; Sat, 24 Feb 2024 01:10:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708737053; bh=eJon+naYLvX2TtPG4PA+bOIKoeqRl8FeptOhgYTmTjY=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=caEkkQyzIq0Ve+Ewj/ihNiVZjSYmf5e1Klx0MPBtyINMpbgb6aCxsqckZ+GRb8kKK zHIlArrJNyH+I13vprpxjOTejJt0fy5KpBtrBDFdLrF8getzqnngOgaRagSoc7hMiY rhyAo8S8GXIfP+Oe5ms1/NuSh5tAB/tywCZP/gkYPYjYQMJ4M0KD69CaAfIPpWShYJ 7OFgAkkMbi0XGgXjHiqbRpJrsuaq6pdNff6nrs+fE4EyuM7uR0gjEHs5twu8Btym2f Ao1hKS2DnwLicW4aFYYqZeIgm1M4BlajMV1TLu7akKwpYlP+0Xm0FcGsJKVpcme+nl IONWowmzq/AmA== Date: Fri, 23 Feb 2024 17:10:52 -0800 Subject: [PATCH 03/10] time_stats: fix struct layout bloat From: "Darrick J. Wong" To: akpm@linux-foundation.org, daniel@gluo.nz, kent.overstreet@linux.dev, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, linux-bcachefs@vger.kernel.org, linux-kernel@vger.kernel.org Message-ID: <170873667989.1860949.8776444464588431097.stgit@frogsfrogsfrogs> In-Reply-To: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> References: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Make these more efficient by getting rid of the holes. This reduces the structure size from 224 bytes to 208 bytes. Signed-off-by: Darrick J. Wong Signed-off-by: Kent Overstreet --- include/linux/time_stats.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/linux/time_stats.h b/include/linux/time_stats.h index c05490101d197..1c1ba8efa7bfe 100644 --- a/include/linux/time_stats.h +++ b/include/linux/time_stats.h @@ -77,19 +77,19 @@ struct time_stats { u64 last_event; u64 last_event_start; -/* - * Is this really a struct time_stats_quantiled? Hide this flag in the least - * significant bit of the start time to avoid blowing up the structure size. - */ -#define TIME_STATS_HAVE_QUANTILES (1ULL << 0) - - u64 start_time; - struct mean_and_variance duration_stats; - struct mean_and_variance_weighted duration_stats_weighted; struct mean_and_variance freq_stats; + struct mean_and_variance_weighted duration_stats_weighted; struct mean_and_variance_weighted freq_stats_weighted; struct time_stat_buffer __percpu *buffer; + +/* + * Is this really a struct time_stats_quantiled? Hide this flag in the least + * significant bit of the start time to avoid blowing up the structure size. + */ +#define TIME_STATS_HAVE_QUANTILES (1ULL << 0) + + u64 start_time; }; struct time_stats_quantiles { From patchwork Sat Feb 24 01:11:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13570174 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2DDC3C39; Sat, 24 Feb 2024 01:11:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737068; cv=none; b=dPXd6djycwmomhyekfCSI3wWXXeOZvCSOaQv3s/jrK8kARH+GJhDjVL4tzRCp/GT/EdNhG7pQo2kTF58APiGY9j+nuYEFf3jKLkbT+/kfIRAskTVuX4i7b5MJEuenpyVaN54tk7RORWM7jLtUvvFdY/Puu9XDM3saiT0E5wjgl4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737068; c=relaxed/simple; bh=G1a33vTP84d0+3QZ0jbrzf9wPqj/sGi8fNaIuQ1yvls=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=WInhHSii/bFXQFcruiAYapqHGK7daRnCaOcp5bljhk5keJMXVUtNcmkhgJj50rvZ2zrP1L/IQDhemOGPzIk67x11Y6n+C8HVt1C0RAFNbs6wMCv74KCTDbQShTNGVhfJfRkLvp0TLvso1/3sUEOSyMOtm+TzPCycZUWjfLcfleA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Sw3MujSS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Sw3MujSS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A8BBEC433F1; Sat, 24 Feb 2024 01:11:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708737068; bh=G1a33vTP84d0+3QZ0jbrzf9wPqj/sGi8fNaIuQ1yvls=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=Sw3MujSS2+6W5dVkxymiSSw4RXwbyxNk+O4NCLTO2/85DEFuKWTH8T84fqwUm5KjX fqleHvatvbRHsXuncO9auONelk2kj50dc340mVjDycRCDj7TrcLnXJgpBPABkUOoQ2 q30HcEIPOuFJ6SxDX2xHp4vRYZYmjrxFOVu6x5eP95VpgHWb0ImHoNWIqUOOC6mVuf 8pEYoDKefGdl+i1fbY6YrtcgA+nuiMPO3N97vEbjRQiYtEx/KozcWU80YcGtn/v9vl Ii9jfdvMpgg9LzK66BkygmmcH4IuoxKHSPJKnFy2Sq/CHWTIAbfIpwLVX7+VMA1UZM +CrbNZOZW8GLg== Date: Fri, 23 Feb 2024 17:11:08 -0800 Subject: [PATCH 04/10] time_stats: add larger units From: "Darrick J. Wong" To: akpm@linux-foundation.org, daniel@gluo.nz, kent.overstreet@linux.dev, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, linux-bcachefs@vger.kernel.org, linux-kernel@vger.kernel.org Message-ID: <170873668005.1860949.11612121203653366580.stgit@frogsfrogsfrogs> In-Reply-To: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> References: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Filesystems can stay mounted for a very long time, so add some larger units. Signed-off-by: Darrick J. Wong Signed-off-by: Kent Overstreet --- lib/time_stats.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/time_stats.c b/lib/time_stats.c index 767b1a340e805..43106bda43a92 100644 --- a/lib/time_stats.c +++ b/lib/time_stats.c @@ -16,6 +16,9 @@ static const struct time_unit time_units[] = { { "s", NSEC_PER_SEC }, { "m", (u64) NSEC_PER_SEC * 60}, { "h", (u64) NSEC_PER_SEC * 3600}, + { "d", (u64) NSEC_PER_SEC * 3600 * 24}, + { "w", (u64) NSEC_PER_SEC * 3600 * 24 * 7}, + { "y", (u64) NSEC_PER_SEC * ((3600 * 24 * 7 * 365) + (3600 * (24 / 4) * 7))}, /* 365.25d */ { "eon", U64_MAX }, }; From patchwork Sat Feb 24 01:11:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13570175 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8436E138A; Sat, 24 Feb 2024 01:11:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737084; cv=none; b=nue9XjGhufE1IK+LT/+G+zctbA+4U3+7DxgyeHdDje+na2De+46RGXmu6yq8wLLG7DU7ocri5aKI691lLPyjIdYzTC+053JUFg+3PNeMhfEje1uw700FIksbYz27JyAq3wFHgabA5okT59dKGkmj2gZl6RD2lEKTohiNYsdffIs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737084; c=relaxed/simple; bh=5vqSyO6kFxrfTkTwaLz92086RbonJjdYMybkf/+eKWQ=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jIMfLBZe08vkbGp6KTwAT2mDsyhERsI2YT7bSyHlEDulAMV1BmSRJgD9ygWcmPprWkk1Ejza5Nt2Of7RJPh+8pklx7/jbyfGYGtggxigPtFROMzVX5VAwmgkO2FjQVs/UMLYUvOvf3U/jSPftg7BBNmlhHDo3NxwL/eLEpMy1UY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fX16huxk; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fX16huxk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5BCEAC433C7; Sat, 24 Feb 2024 01:11:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708737084; bh=5vqSyO6kFxrfTkTwaLz92086RbonJjdYMybkf/+eKWQ=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=fX16huxkSBmeeN39raaLvkhSJLummWKhv0/sCeF62LoeLgPU6ROXoj2k3t+AphvVa KJkxj4AzoKnj7dLFd+znC+3p/tu2jVfpNUywn44qRSCuivV7F65nOJYIR/1Ks/sZNc 3PqlfnIy19Om7qaPJFFzqaVEC8kTdwYjokK4cjbW3Fza/x2o4Z4PZZPCx0Hjhl9b+q 3mXsW7Ic/boXp2qremR3KwKbJd7AMgP5zQp4r+SMLMvXioQf2hBuWeEgU0TtENfeb3 ziLJnlNa5pltxcXirKijPtSiS0H/qcYfvtVuOu//m5XuS1LPy7FY7tANwol29I3nY6 SIaBb/p/cxj7g== Date: Fri, 23 Feb 2024 17:11:23 -0800 Subject: [PATCH 05/10] time_stats: don't print any output if event count is zero From: "Darrick J. Wong" To: akpm@linux-foundation.org, daniel@gluo.nz, kent.overstreet@linux.dev, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, linux-bcachefs@vger.kernel.org, linux-kernel@vger.kernel.org Message-ID: <170873668021.1860949.13792887319624615306.stgit@frogsfrogsfrogs> In-Reply-To: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> References: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong There's no point in printing an empty report for no data, so add a flag that allows us to do that. Signed-off-by: Darrick J. Wong Signed-off-by: Kent Overstreet --- include/linux/time_stats.h | 4 +++- lib/time_stats.c | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/include/linux/time_stats.h b/include/linux/time_stats.h index 1c1ba8efa7bfe..994823c17bca9 100644 --- a/include/linux/time_stats.h +++ b/include/linux/time_stats.h @@ -148,8 +148,10 @@ static inline bool track_event_change(struct time_stats *stats, bool v) return false; } +#define TIME_STATS_PRINT_NO_ZEROES (1U << 0) /* print nothing if zero count */ struct seq_buf; -void time_stats_to_seq_buf(struct seq_buf *, struct time_stats *); +void time_stats_to_seq_buf(struct seq_buf *, struct time_stats *, + unsigned int flags); void time_stats_exit(struct time_stats *); void time_stats_init(struct time_stats *); diff --git a/lib/time_stats.c b/lib/time_stats.c index 43106bda43a92..382935979f8f7 100644 --- a/lib/time_stats.c +++ b/lib/time_stats.c @@ -168,7 +168,8 @@ static inline u64 time_stats_lifetime(const struct time_stats *stats) return local_clock() - (stats->start_time & ~TIME_STATS_HAVE_QUANTILES); } -void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats) +void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats, + unsigned int flags) { struct quantiles *quantiles = time_stats_to_quantiles(stats); s64 f_mean = 0, d_mean = 0; @@ -184,14 +185,15 @@ void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats) spin_unlock_irq(&stats->lock); } - /* - * avoid divide by zero - */ if (stats->freq_stats.n) { + /* avoid divide by zero */ f_mean = mean_and_variance_get_mean(stats->freq_stats); f_stddev = mean_and_variance_get_stddev(stats->freq_stats); d_mean = mean_and_variance_get_mean(stats->duration_stats); d_stddev = mean_and_variance_get_stddev(stats->duration_stats); + } else if (flags & TIME_STATS_PRINT_NO_ZEROES) { + /* unless we didn't want zeroes anyway */ + return; } seq_buf_printf(out, "count: %llu\n", stats->duration_stats.n); From patchwork Sat Feb 24 01:11:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13570176 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 299CA4416; Sat, 24 Feb 2024 01:11:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737100; cv=none; b=We/zSoOlB4ErjHrUD8OCZkHpGiSQ9uWhpPsZo40Xg5sS60Q1ehTNM8j5ntfiCERGNE24iedNDpeYpCRgVdGEYe5s4ek4slmNrpNG7l3znMYwd0yGhrrqRcRgsGLnruTuwT1k8FKX3ZPtQSdB7/elrFpYSfc8aywWGy4CJG3QtHc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737100; c=relaxed/simple; bh=YpmqV9X3OHUUtHw2bB58KIEaUKBC08TNG+/xCl014u8=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=nVGzawvgki7Yna3zHyW9GkqW5Ms/KcxWI0j/LG3GpWWJLK3jgyHBeB1Y2FjeZ+hZltpwkL3shfEWb03orF3hRFNJJZwn6HCJD83+BSzeyDZNfnz5Txy/SvQsG48bfxhUJkziDRPSB429HauIEwZunMcSWqh5gexF5yJLRQa/r9U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GhJOiylr; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GhJOiylr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F307AC433C7; Sat, 24 Feb 2024 01:11:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708737100; bh=YpmqV9X3OHUUtHw2bB58KIEaUKBC08TNG+/xCl014u8=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=GhJOiylrR1qtCUM2vC0LFagGq0u/JFyJUWKEUDw5mTBm3cfF4jr1A5ekxHSHEpakl XUcFs0uve3HvKkbTRVF2H62PHVeMpoGY3gA3QsiThMxmiFkXtb9mwvZ8XqqSbn+Byf 5OElv2U95g7FvZOFVuL9kvMQZgQCSXALRPwRMMavObEc9OdnoKup71iAlriSurz+fv 5mNmNA9yPYDRALXnsX1Urw3BSLS8NwV3uJq3VzFjTQW1HfyDiVzdzDEmWKuoSW5pbF XVzAge44d337VQOR2111vklFrcdCvHvk9K27AO1qRLAnnZxkinELDn3TwZXS10SiRd PXO/zCwO+1OJw== Date: Fri, 23 Feb 2024 17:11:39 -0800 Subject: [PATCH 06/10] time_stats: allow custom epoch names From: "Darrick J. Wong" To: akpm@linux-foundation.org, daniel@gluo.nz, kent.overstreet@linux.dev, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, linux-bcachefs@vger.kernel.org, linux-kernel@vger.kernel.org Message-ID: <170873668037.1860949.12345616435891382226.stgit@frogsfrogsfrogs> In-Reply-To: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> References: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Let callers of time_stats_to_seq_buf define the epoch name; "mount" doesn't make sense generally. Signed-off-by: Darrick J. Wong Signed-off-by: Kent Overstreet --- include/linux/time_stats.h | 2 +- lib/time_stats.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/time_stats.h b/include/linux/time_stats.h index 994823c17bca9..b2f71e3862c0f 100644 --- a/include/linux/time_stats.h +++ b/include/linux/time_stats.h @@ -151,7 +151,7 @@ static inline bool track_event_change(struct time_stats *stats, bool v) #define TIME_STATS_PRINT_NO_ZEROES (1U << 0) /* print nothing if zero count */ struct seq_buf; void time_stats_to_seq_buf(struct seq_buf *, struct time_stats *, - unsigned int flags); + const char *epoch_name, unsigned int flags); void time_stats_exit(struct time_stats *); void time_stats_init(struct time_stats *); diff --git a/lib/time_stats.c b/lib/time_stats.c index 382935979f8f7..f4a21409006bd 100644 --- a/lib/time_stats.c +++ b/lib/time_stats.c @@ -169,7 +169,7 @@ static inline u64 time_stats_lifetime(const struct time_stats *stats) } void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats, - unsigned int flags) + const char *epoch_name, unsigned int flags) { struct quantiles *quantiles = time_stats_to_quantiles(stats); s64 f_mean = 0, d_mean = 0; @@ -201,7 +201,7 @@ void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats, seq_buf_time_units_aligned(out, lifetime); seq_buf_printf(out, "\n"); - seq_buf_printf(out, " since mount recent\n"); + seq_buf_printf(out, " since %-12s recent\n", epoch_name); seq_buf_printf(out, "duration of events\n"); From patchwork Sat Feb 24 01:11:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13570177 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 13CA94A05; Sat, 24 Feb 2024 01:11:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737116; cv=none; b=ZKILXviPGvyyPL4851hFFaTFZKyCbGgwAveMmwC0bfVKSKupAr6wXBjZ8dqCJFWnXqbOt5qMLy6p6WRnuuM+69npwl7c1cCRqamio5dYtuarIzvKKBh/+3M8x0iBAYxu1p2jhfyQw9WSfyXnazZFG4lgbp/0a1SPSIHO9bCIRp8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737116; c=relaxed/simple; bh=2pup8be+b59a8UwXcZHhWDG/xYDa2uYcVmcAamFutSE=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PduLK8tpm6QidEm92suq/qnhufCdr/+ZJWCkU5lucbrhqqAQenyTU749WFoJzz0hROMM6LfiSUwxPz4rR0kkXs0+1zQQZca0wR0RGuuTsOEJDkthdoKyDTg7TuTa1K/TxunktBKBgg2MiXxnTNN6L1HodvG72spoWih6/AD7nY4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JM4y8pZv; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JM4y8pZv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8E5FFC433F1; Sat, 24 Feb 2024 01:11:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708737115; bh=2pup8be+b59a8UwXcZHhWDG/xYDa2uYcVmcAamFutSE=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=JM4y8pZvbjWfoCmqVRe6JsBIqsMUHdE2ik15RdBFGd+vw/a/FdPnP0HACr2vrsbqn eCdjH5r8ONLR4IsDypOAlOWdlRm69nxFj2l6bk0e3hr4pzTNdFmJfSDfMTzjgpVS/Y 4XZUsc39nz5bkT+MLnZ3pAIdNLfY/vuoVcDTsgimuIEESmPjEgrA2QRu5pcQ250lre 9P5y8cYElXQ4Y6pgnIqLJl9xyeJQ+PWKfSS2Ws0rAkBDpcMLwaYmNxSvohjP3TceJQ Om8Fg1bG7amBXT3+BPp/0JdDHZT9nNVCE1tlDdCiz8itrqof74DJMd33Od2IVcdPcg EDtiBA8U79jEw== Date: Fri, 23 Feb 2024 17:11:55 -0800 Subject: [PATCH 07/10] mean_and_variance: put struct mean_and_variance_weighted on a diet From: "Darrick J. Wong" To: akpm@linux-foundation.org, daniel@gluo.nz, kent.overstreet@linux.dev, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, linux-bcachefs@vger.kernel.org, linux-kernel@vger.kernel.org Message-ID: <170873668053.1860949.14729710277150920793.stgit@frogsfrogsfrogs> In-Reply-To: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> References: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong The only caller of this code (time_stats) always knows the weights and whether or not any information has been collected. Pass this information into the mean and variance code so that it doesn't have to store that information. This reduces the structure size from 24 to 16 bytes, which shrinks each time_stats counter to 192 bytes from 208. Signed-off-by: Darrick J. Wong Signed-off-by: Kent Overstreet --- fs/bcachefs/util.c | 8 ++-- include/linux/mean_and_variance.h | 14 ++++-- include/linux/time_stats.h | 4 ++ lib/math/mean_and_variance.c | 28 ++++++++----- lib/math/mean_and_variance_test.c | 80 ++++++++++++++++++++----------------- lib/time_stats.c | 23 +++++------ 6 files changed, 87 insertions(+), 70 deletions(-) diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c index ef620bfe76cd2..4c3e19d562852 100644 --- a/fs/bcachefs/util.c +++ b/fs/bcachefs/util.c @@ -429,14 +429,14 @@ void bch2_time_stats_to_text(struct printbuf *out, struct time_stats *stats) prt_tab(out); bch2_pr_time_units_aligned(out, d_mean); prt_tab(out); - bch2_pr_time_units_aligned(out, mean_and_variance_weighted_get_mean(stats->duration_stats_weighted)); + bch2_pr_time_units_aligned(out, mean_and_variance_weighted_get_mean(stats->duration_stats_weighted, TIME_STATS_MV_WEIGHT)); prt_newline(out); prt_printf(out, "stddev:"); prt_tab(out); bch2_pr_time_units_aligned(out, d_stddev); prt_tab(out); - bch2_pr_time_units_aligned(out, mean_and_variance_weighted_get_stddev(stats->duration_stats_weighted)); + bch2_pr_time_units_aligned(out, mean_and_variance_weighted_get_stddev(stats->duration_stats_weighted, TIME_STATS_MV_WEIGHT)); printbuf_indent_sub(out, 2); prt_newline(out); @@ -452,14 +452,14 @@ void bch2_time_stats_to_text(struct printbuf *out, struct time_stats *stats) prt_tab(out); bch2_pr_time_units_aligned(out, f_mean); prt_tab(out); - bch2_pr_time_units_aligned(out, mean_and_variance_weighted_get_mean(stats->freq_stats_weighted)); + bch2_pr_time_units_aligned(out, mean_and_variance_weighted_get_mean(stats->freq_stats_weighted, TIME_STATS_MV_WEIGHT)); prt_newline(out); prt_printf(out, "stddev:"); prt_tab(out); bch2_pr_time_units_aligned(out, f_stddev); prt_tab(out); - bch2_pr_time_units_aligned(out, mean_and_variance_weighted_get_stddev(stats->freq_stats_weighted)); + bch2_pr_time_units_aligned(out, mean_and_variance_weighted_get_stddev(stats->freq_stats_weighted, TIME_STATS_MV_WEIGHT)); printbuf_indent_sub(out, 2); prt_newline(out); diff --git a/include/linux/mean_and_variance.h b/include/linux/mean_and_variance.h index 64df11ab422bf..4fcf062dd22c7 100644 --- a/include/linux/mean_and_variance.h +++ b/include/linux/mean_and_variance.h @@ -154,8 +154,6 @@ struct mean_and_variance { /* expontentially weighted variant */ struct mean_and_variance_weighted { - bool init; - u8 weight; /* base 2 logarithim */ s64 mean; u64 variance; }; @@ -192,10 +190,14 @@ s64 mean_and_variance_get_mean(struct mean_and_variance s); u64 mean_and_variance_get_variance(struct mean_and_variance s1); u32 mean_and_variance_get_stddev(struct mean_and_variance s); -void mean_and_variance_weighted_update(struct mean_and_variance_weighted *s, s64 v); +void mean_and_variance_weighted_update(struct mean_and_variance_weighted *s, + s64 v, bool initted, u8 weight); -s64 mean_and_variance_weighted_get_mean(struct mean_and_variance_weighted s); -u64 mean_and_variance_weighted_get_variance(struct mean_and_variance_weighted s); -u32 mean_and_variance_weighted_get_stddev(struct mean_and_variance_weighted s); +s64 mean_and_variance_weighted_get_mean(struct mean_and_variance_weighted s, + u8 weight); +u64 mean_and_variance_weighted_get_variance(struct mean_and_variance_weighted s, + u8 weight); +u32 mean_and_variance_weighted_get_stddev(struct mean_and_variance_weighted s, + u8 weight); #endif // MEAN_AND_VAIRANCE_H_ diff --git a/include/linux/time_stats.h b/include/linux/time_stats.h index b2f71e3862c0f..dc539123f7997 100644 --- a/include/linux/time_stats.h +++ b/include/linux/time_stats.h @@ -79,6 +79,10 @@ struct time_stats { struct mean_and_variance duration_stats; struct mean_and_variance freq_stats; + +/* default weight for weighted mean and variance calculations */ +#define TIME_STATS_MV_WEIGHT 8 + struct mean_and_variance_weighted duration_stats_weighted; struct mean_and_variance_weighted freq_stats_weighted; struct time_stat_buffer __percpu *buffer; diff --git a/lib/math/mean_and_variance.c b/lib/math/mean_and_variance.c index ba90293204bae..21ec6afc67884 100644 --- a/lib/math/mean_and_variance.c +++ b/lib/math/mean_and_variance.c @@ -102,14 +102,17 @@ EXPORT_SYMBOL_GPL(mean_and_variance_get_stddev); * mean_and_variance_weighted_update() - exponentially weighted variant of mean_and_variance_update() * @s: mean and variance number of samples and their sums * @x: new value to include in the &mean_and_variance_weighted + * @initted: caller must track whether this is the first use or not + * @weight: ewma weight * * see linked pdf: function derived from equations 140-143 where alpha = 2^w. * values are stored bitshifted for performance and added precision. */ -void mean_and_variance_weighted_update(struct mean_and_variance_weighted *s, s64 x) +void mean_and_variance_weighted_update(struct mean_and_variance_weighted *s, + s64 x, bool initted, u8 weight) { // previous weighted variance. - u8 w = s->weight; + u8 w = weight; u64 var_w0 = s->variance; // new value weighted. s64 x_w = x << w; @@ -118,45 +121,50 @@ void mean_and_variance_weighted_update(struct mean_and_variance_weighted *s, s64 // new mean weighted. s64 u_w1 = s->mean + diff; - if (!s->init) { + if (!initted) { s->mean = x_w; s->variance = 0; } else { s->mean = u_w1; s->variance = ((var_w0 << w) - var_w0 + ((diff_w * (x_w - u_w1)) >> w)) >> w; } - s->init = true; } EXPORT_SYMBOL_GPL(mean_and_variance_weighted_update); /** * mean_and_variance_weighted_get_mean() - get mean from @s * @s: mean and variance number of samples and their sums + * @weight: ewma weight */ -s64 mean_and_variance_weighted_get_mean(struct mean_and_variance_weighted s) +s64 mean_and_variance_weighted_get_mean(struct mean_and_variance_weighted s, + u8 weight) { - return fast_divpow2(s.mean, s.weight); + return fast_divpow2(s.mean, weight); } EXPORT_SYMBOL_GPL(mean_and_variance_weighted_get_mean); /** * mean_and_variance_weighted_get_variance() -- get variance from @s * @s: mean and variance number of samples and their sums + * @weight: ewma weight */ -u64 mean_and_variance_weighted_get_variance(struct mean_and_variance_weighted s) +u64 mean_and_variance_weighted_get_variance(struct mean_and_variance_weighted s, + u8 weight) { // always positive don't need fast divpow2 - return s.variance >> s.weight; + return s.variance >> weight; } EXPORT_SYMBOL_GPL(mean_and_variance_weighted_get_variance); /** * mean_and_variance_weighted_get_stddev() - get standard deviation from @s * @s: mean and variance number of samples and their sums + * @weight: ewma weight */ -u32 mean_and_variance_weighted_get_stddev(struct mean_and_variance_weighted s) +u32 mean_and_variance_weighted_get_stddev(struct mean_and_variance_weighted s, + u8 weight) { - return int_sqrt64(mean_and_variance_weighted_get_variance(s)); + return int_sqrt64(mean_and_variance_weighted_get_variance(s, weight)); } EXPORT_SYMBOL_GPL(mean_and_variance_weighted_get_stddev); diff --git a/lib/math/mean_and_variance_test.c b/lib/math/mean_and_variance_test.c index f45591a169d87..0d8c2451a8588 100644 --- a/lib/math/mean_and_variance_test.c +++ b/lib/math/mean_and_variance_test.c @@ -30,53 +30,59 @@ static void mean_and_variance_basic_test(struct kunit *test) static void mean_and_variance_weighted_test(struct kunit *test) { - struct mean_and_variance_weighted s = { .weight = 2 }; + struct mean_and_variance_weighted s = { }; - mean_and_variance_weighted_update(&s, 10); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s), 10); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s), 0); + mean_and_variance_weighted_update(&s, 10, false, 2); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), 10); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 0); - mean_and_variance_weighted_update(&s, 20); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s), 12); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s), 18); + mean_and_variance_weighted_update(&s, 20, true, 2); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), 12); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 18); - mean_and_variance_weighted_update(&s, 30); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s), 16); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s), 72); + mean_and_variance_weighted_update(&s, 30, true, 2); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), 16); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 72); - s = (struct mean_and_variance_weighted) { .weight = 2 }; + s = (struct mean_and_variance_weighted) { }; - mean_and_variance_weighted_update(&s, -10); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s), -10); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s), 0); + mean_and_variance_weighted_update(&s, -10, false, 2); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), -10); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 0); - mean_and_variance_weighted_update(&s, -20); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s), -12); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s), 18); + mean_and_variance_weighted_update(&s, -20, true, 2); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), -12); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 18); - mean_and_variance_weighted_update(&s, -30); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s), -16); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s), 72); + mean_and_variance_weighted_update(&s, -30, true, 2); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 2), -16); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 2), 72); } static void mean_and_variance_weighted_advanced_test(struct kunit *test) { - struct mean_and_variance_weighted s = { .weight = 8 }; + struct mean_and_variance_weighted s = { }; + bool initted = false; s64 i; - for (i = 10; i <= 100; i += 10) - mean_and_variance_weighted_update(&s, i); + for (i = 10; i <= 100; i += 10) { + mean_and_variance_weighted_update(&s, i, initted, 8); + initted = true; + } - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s), 11); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s), 107); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 8), 11); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 8), 107); - s = (struct mean_and_variance_weighted) { .weight = 8 }; + s = (struct mean_and_variance_weighted) { }; + initted = false; - for (i = -10; i >= -100; i -= 10) - mean_and_variance_weighted_update(&s, i); + for (i = -10; i >= -100; i -= 10) { + mean_and_variance_weighted_update(&s, i, initted, 8); + initted = true; + } - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s), -11); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s), 107); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(s, 8), -11); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_variance(s, 8), 107); } static void do_mean_and_variance_test(struct kunit *test, @@ -91,26 +97,26 @@ static void do_mean_and_variance_test(struct kunit *test, s64 *weighted_stddev) { struct mean_and_variance mv = {}; - struct mean_and_variance_weighted vw = { .weight = weight }; + struct mean_and_variance_weighted vw = { }; for (unsigned i = 0; i < initial_n; i++) { mean_and_variance_update(&mv, initial_value); - mean_and_variance_weighted_update(&vw, initial_value); + mean_and_variance_weighted_update(&vw, initial_value, false, weight); KUNIT_EXPECT_EQ(test, mean_and_variance_get_mean(mv), initial_value); KUNIT_EXPECT_EQ(test, mean_and_variance_get_stddev(mv), 0); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(vw), initial_value); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_stddev(vw),0); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(vw, weight), initial_value); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_stddev(vw, weight),0); } for (unsigned i = 0; i < n; i++) { mean_and_variance_update(&mv, data[i]); - mean_and_variance_weighted_update(&vw, data[i]); + mean_and_variance_weighted_update(&vw, data[i], true, weight); KUNIT_EXPECT_EQ(test, mean_and_variance_get_mean(mv), mean[i]); KUNIT_EXPECT_EQ(test, mean_and_variance_get_stddev(mv), stddev[i]); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(vw), weighted_mean[i]); - KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_stddev(vw),weighted_stddev[i]); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_mean(vw, weight), weighted_mean[i]); + KUNIT_EXPECT_EQ(test, mean_and_variance_weighted_get_stddev(vw, weight),weighted_stddev[i]); } KUNIT_EXPECT_EQ(test, mv.n, initial_n + n); diff --git a/lib/time_stats.c b/lib/time_stats.c index f4a21409006bd..0fb3d854e503b 100644 --- a/lib/time_stats.c +++ b/lib/time_stats.c @@ -70,13 +70,15 @@ static inline void time_stats_update_one(struct time_stats *stats, u64 start, u64 end) { u64 duration, freq; + bool initted = stats->last_event != 0; if (time_after64(end, start)) { struct quantiles *quantiles = time_stats_to_quantiles(stats); duration = end - start; mean_and_variance_update(&stats->duration_stats, duration); - mean_and_variance_weighted_update(&stats->duration_stats_weighted, duration); + mean_and_variance_weighted_update(&stats->duration_stats_weighted, + duration, initted, TIME_STATS_MV_WEIGHT); stats->max_duration = max(stats->max_duration, duration); stats->min_duration = min(stats->min_duration, duration); stats->total_duration += duration; @@ -88,7 +90,8 @@ static inline void time_stats_update_one(struct time_stats *stats, if (stats->last_event && time_after64(end, stats->last_event)) { freq = end - stats->last_event; mean_and_variance_update(&stats->freq_stats, freq); - mean_and_variance_weighted_update(&stats->freq_stats_weighted, freq); + mean_and_variance_weighted_update(&stats->freq_stats_weighted, + freq, initted, TIME_STATS_MV_WEIGHT); stats->max_freq = max(stats->max_freq, freq); stats->min_freq = min(stats->min_freq, freq); } @@ -121,15 +124,11 @@ void __time_stats_update(struct time_stats *stats, u64 start, u64 end) { unsigned long flags; - WARN_ONCE(!stats->duration_stats_weighted.weight || - !stats->freq_stats_weighted.weight, - "uninitialized time_stats"); - if (!stats->buffer) { spin_lock_irqsave(&stats->lock, flags); time_stats_update_one(stats, start, end); - if (mean_and_variance_weighted_get_mean(stats->freq_stats_weighted) < 32 && + if (mean_and_variance_weighted_get_mean(stats->freq_stats_weighted, TIME_STATS_MV_WEIGHT) < 32 && stats->duration_stats.n > 1024) stats->buffer = alloc_percpu_gfp(struct time_stat_buffer, @@ -219,12 +218,12 @@ void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats, seq_buf_printf(out, " mean: "); seq_buf_time_units_aligned(out, d_mean); - seq_buf_time_units_aligned(out, mean_and_variance_weighted_get_mean(stats->duration_stats_weighted)); + seq_buf_time_units_aligned(out, mean_and_variance_weighted_get_mean(stats->duration_stats_weighted, TIME_STATS_MV_WEIGHT)); seq_buf_printf(out, "\n"); seq_buf_printf(out, " stddev: "); seq_buf_time_units_aligned(out, d_stddev); - seq_buf_time_units_aligned(out, mean_and_variance_weighted_get_stddev(stats->duration_stats_weighted)); + seq_buf_time_units_aligned(out, mean_and_variance_weighted_get_stddev(stats->duration_stats_weighted, TIME_STATS_MV_WEIGHT)); seq_buf_printf(out, "\n"); seq_buf_printf(out, "time between events\n"); @@ -239,12 +238,12 @@ void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats, seq_buf_printf(out, " mean: "); seq_buf_time_units_aligned(out, f_mean); - seq_buf_time_units_aligned(out, mean_and_variance_weighted_get_mean(stats->freq_stats_weighted)); + seq_buf_time_units_aligned(out, mean_and_variance_weighted_get_mean(stats->freq_stats_weighted, TIME_STATS_MV_WEIGHT)); seq_buf_printf(out, "\n"); seq_buf_printf(out, " stddev: "); seq_buf_time_units_aligned(out, f_stddev); - seq_buf_time_units_aligned(out, mean_and_variance_weighted_get_stddev(stats->freq_stats_weighted)); + seq_buf_time_units_aligned(out, mean_and_variance_weighted_get_stddev(stats->freq_stats_weighted, TIME_STATS_MV_WEIGHT)); seq_buf_printf(out, "\n"); if (quantiles) { @@ -276,8 +275,6 @@ EXPORT_SYMBOL_GPL(time_stats_exit); void time_stats_init(struct time_stats *stats) { memset(stats, 0, sizeof(*stats)); - stats->duration_stats_weighted.weight = 8; - stats->freq_stats_weighted.weight = 8; stats->min_duration = U64_MAX; stats->min_freq = U64_MAX; stats->start_time = local_clock() & ~TIME_STATS_HAVE_QUANTILES; From patchwork Sat Feb 24 01:12:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13570178 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B944817F5; Sat, 24 Feb 2024 01:12:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737131; cv=none; b=oiIfhT2EKdyD1QMcmnQa3OnUxVCdXl7mTWda0KkFbpUWF5feBjTuXCHPtHWxw81rj4fzGUlNii/BQsnUSJRLSTD8QFz2HkohFAYdRgeALW0xhMvkNHLnJM8f8K87qvdD+j7x2Iv2wADXS1+vOJ9n2L/m6KdcrSadqU+xWKTwCEs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737131; c=relaxed/simple; bh=t+a3dnfPOx4IIRgsSK8ZjS4LDPymxs2saneliaxtiAI=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=WmihWYLJmgoeYrdxB3jIQjBHeFiJgrKuqF6jSGZaqNE23CEOPuk7z3UTZLLiS32qoj7i1AvA+fwc5/tUEU40Ge6sw+NbMkW3j1ttR6PHGUZorS/eza6IFpO9anLJBrsEFsDiiqp8vb/tSOe+ZMCsTIe43wF4F2/OYAcGCMNTRhc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qKwgcty8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qKwgcty8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 30C49C433F1; Sat, 24 Feb 2024 01:12:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708737131; bh=t+a3dnfPOx4IIRgsSK8ZjS4LDPymxs2saneliaxtiAI=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=qKwgcty81/ZnYzIwfilwTthfSCEWrkWCGo05LxbzB79HvDWq5LrQdFFYzCa0h9V39 /Aklm9osV/suDs8g2Q6suqPXRJEAUkiLn4Yd5yzhZoA2oogYzwymyxu7a/vPXCdo63 2Mv4eCjDKekmcSdTB1J99blmh8/aE8hrvSUmK0Vq4kUDo55t8NQzdovNdruJev5hzG 9xPSHpcL0UArzt1DTAxrC5zpQX8Z1Vq26oZ+SPwOcHKODFvAQ8M5gh0bGPFzhxHSl1 KQd1XYQ549x0i9yuE0cR6YnMKoZ+ASN9PL3zyZ5JQmZQMrUDyQOBOiZwUeGgZfhEq/ guOVIcFBmzbmQ== Date: Fri, 23 Feb 2024 17:12:10 -0800 Subject: [PATCH 08/10] time_stats: shrink time_stat_buffer for better alignment From: "Darrick J. Wong" To: akpm@linux-foundation.org, daniel@gluo.nz, kent.overstreet@linux.dev, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, linux-bcachefs@vger.kernel.org, linux-kernel@vger.kernel.org Message-ID: <170873668069.1860949.912351762607273370.stgit@frogsfrogsfrogs> In-Reply-To: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> References: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Shrink this percpu object by one array element so that the object size becomes exactly 512 bytes. This will lead to more efficient memory use, hopefully. Signed-off-by: Darrick J. Wong Signed-off-by: Kent Overstreet --- include/linux/time_stats.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/time_stats.h b/include/linux/time_stats.h index dc539123f7997..b3c810fff963a 100644 --- a/include/linux/time_stats.h +++ b/include/linux/time_stats.h @@ -63,7 +63,7 @@ struct time_stat_buffer { struct time_stat_buffer_entry { u64 start; u64 end; - } entries[32]; + } entries[31]; }; struct time_stats { From patchwork Sat Feb 24 01:12:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13570179 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B5D56116; Sat, 24 Feb 2024 01:12:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737147; cv=none; b=QFbbNtwLrLqiErX+NiD6OtwJWbUtwJvkAYbSgxEcEtPXN+32046VwLEt9ttDjuSzjTzR/q+HVGh3faIB5j8jMxT0wd0JDk3JsXAjogNv2F9MGQKhYrUzChZnSwTDlXL+w7ZzWx3PvO9XhKpiCEzaSMyA6PKEfTBj0yDbACkQmmE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737147; c=relaxed/simple; bh=stCMDrWvmAsbsnRhDg01PkUkNRNpdLqZpFOiKHjm3Do=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fsjUaXUVknWWrD+pkMlLVbmtEddBhIk9uzL/Qvv7pPuBiBdZrcZ0+pMQLZkrOIaAQFEsW3WICVJVHCLtm2NFQAegUmPSW+aV8N0d318/0wKNoV8VgkURRdUMcrUh0Q4cK50LlR7d2QPGT6lEwjrzVw+ED/OvUpaDukdNXF/wnXo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=oMPxm1hy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="oMPxm1hy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D6F48C433C7; Sat, 24 Feb 2024 01:12:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708737146; bh=stCMDrWvmAsbsnRhDg01PkUkNRNpdLqZpFOiKHjm3Do=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=oMPxm1hyVNVOKZmazZDYU7hrTHAPU1VeOJgzDSHxKgfcl0U9Suj6X4/hpwtdqhJ+o AuMh/hJC2EmUhLQS+kyvjIPMvs2VwQKZoFE4lML/V/qDpyw9sBf762Yfpy2GImdCGL cuhR+IBIb8gZGb0AqSx+EcfOQlyUbI+YH0Mog/kQTp4STdIcbg8Oye5AoaSlKQe08m dvZ+N9NAX0t4N9PYfnezGNCylK9AKLOD9jBerabtH1YsBNNAavrCAhvaQH6EoHwLEc R4j6QKRtdFtTs4PuguZYGMlPCG5xElKqI8ulJo4CBZRvb0xGpOwGcCLM4ZUyMzY0sE kj2tQ62lJxQ5w== Date: Fri, 23 Feb 2024 17:12:26 -0800 Subject: [PATCH 09/10] time_stats: report information in json format From: "Darrick J. Wong" To: akpm@linux-foundation.org, daniel@gluo.nz, kent.overstreet@linux.dev, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, linux-bcachefs@vger.kernel.org, linux-kernel@vger.kernel.org Message-ID: <170873668085.1860949.11659237532415596101.stgit@frogsfrogsfrogs> In-Reply-To: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> References: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Darrick J. Wong Export json versions of time statistics information. Given the tabular nature of the numbers exposed, this will make it a lot easier for higher (than C) level languages (e.g. python) to import information without needing to write yet another clumsy string parser. Signed-off-by: Darrick J. Wong Signed-off-by: Kent Overstreet Reviewed-by: Darrick J. Wong --- include/linux/time_stats.h | 2 + lib/time_stats.c | 87 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/include/linux/time_stats.h b/include/linux/time_stats.h index b3c810fff963a..4e1f5485ed039 100644 --- a/include/linux/time_stats.h +++ b/include/linux/time_stats.h @@ -156,6 +156,8 @@ static inline bool track_event_change(struct time_stats *stats, bool v) struct seq_buf; void time_stats_to_seq_buf(struct seq_buf *, struct time_stats *, const char *epoch_name, unsigned int flags); +void time_stats_to_json(struct seq_buf *, struct time_stats *, + const char *epoch_name, unsigned int flags); void time_stats_exit(struct time_stats *); void time_stats_init(struct time_stats *); diff --git a/lib/time_stats.c b/lib/time_stats.c index 0fb3d854e503b..c0f209dd9f6dd 100644 --- a/lib/time_stats.c +++ b/lib/time_stats.c @@ -266,6 +266,93 @@ void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats, } EXPORT_SYMBOL_GPL(time_stats_to_seq_buf); +void time_stats_to_json(struct seq_buf *out, struct time_stats *stats, + const char *epoch_name, unsigned int flags) +{ + struct quantiles *quantiles = time_stats_to_quantiles(stats); + s64 f_mean = 0, d_mean = 0; + u64 f_stddev = 0, d_stddev = 0; + + if (stats->buffer) { + int cpu; + + spin_lock_irq(&stats->lock); + for_each_possible_cpu(cpu) + __time_stats_clear_buffer(stats, per_cpu_ptr(stats->buffer, cpu)); + spin_unlock_irq(&stats->lock); + } + + if (stats->freq_stats.n) { + /* avoid divide by zero */ + f_mean = mean_and_variance_get_mean(stats->freq_stats); + f_stddev = mean_and_variance_get_stddev(stats->freq_stats); + d_mean = mean_and_variance_get_mean(stats->duration_stats); + d_stddev = mean_and_variance_get_stddev(stats->duration_stats); + } else if (flags & TIME_STATS_PRINT_NO_ZEROES) { + /* unless we didn't want zeroes anyway */ + return; + } + + seq_buf_printf(out, "{\n"); + seq_buf_printf(out, " \"epoch\": \"%s\",\n", epoch_name); + seq_buf_printf(out, " \"count\": %llu,\n", stats->duration_stats.n); + + seq_buf_printf(out, " \"duration_ns\": {\n"); + seq_buf_printf(out, " \"min\": %llu,\n", stats->min_duration); + seq_buf_printf(out, " \"max\": %llu,\n", stats->max_duration); + seq_buf_printf(out, " \"total\": %llu,\n", stats->total_duration); + seq_buf_printf(out, " \"mean\": %llu,\n", d_mean); + seq_buf_printf(out, " \"stddev\": %llu\n", d_stddev); + seq_buf_printf(out, " },\n"); + + d_mean = mean_and_variance_weighted_get_mean(stats->duration_stats_weighted, TIME_STATS_MV_WEIGHT); + d_stddev = mean_and_variance_weighted_get_stddev(stats->duration_stats_weighted, TIME_STATS_MV_WEIGHT); + + seq_buf_printf(out, " \"duration_ewma_ns\": {\n"); + seq_buf_printf(out, " \"mean\": %llu,\n", d_mean); + seq_buf_printf(out, " \"stddev\": %llu\n", d_stddev); + seq_buf_printf(out, " },\n"); + + seq_buf_printf(out, " \"frequency_ns\": {\n"); + seq_buf_printf(out, " \"min\": %llu,\n", stats->min_freq); + seq_buf_printf(out, " \"max\": %llu,\n", stats->max_freq); + seq_buf_printf(out, " \"mean\": %llu,\n", f_mean); + seq_buf_printf(out, " \"stddev\": %llu\n", f_stddev); + seq_buf_printf(out, " },\n"); + + f_mean = mean_and_variance_weighted_get_mean(stats->freq_stats_weighted, TIME_STATS_MV_WEIGHT); + f_stddev = mean_and_variance_weighted_get_stddev(stats->freq_stats_weighted, TIME_STATS_MV_WEIGHT); + + seq_buf_printf(out, " \"frequency_ewma_ns\": {\n"); + seq_buf_printf(out, " \"mean\": %llu,\n", f_mean); + seq_buf_printf(out, " \"stddev\": %llu\n", f_stddev); + + if (quantiles) { + u64 last_q = 0; + + /* close frequency_ewma_ns but signal more items */ + seq_buf_printf(out, " },\n"); + + seq_buf_printf(out, " \"quantiles_ns\": [\n"); + eytzinger0_for_each(i, NR_QUANTILES) { + bool is_last = eytzinger0_next(i, NR_QUANTILES) == -1; + + u64 q = max(quantiles->entries[i].m, last_q); + seq_buf_printf(out, " %llu", q); + if (!is_last) + seq_buf_printf(out, ", "); + last_q = q; + } + seq_buf_printf(out, " ]\n"); + } else { + /* close frequency_ewma_ns without dumping further */ + seq_buf_printf(out, " }\n"); + } + + seq_buf_printf(out, "}\n"); +} +EXPORT_SYMBOL_GPL(time_stats_to_json); + void time_stats_exit(struct time_stats *stats) { free_percpu(stats->buffer); From patchwork Sat Feb 24 01:12:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13570180 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0F35C4688; Sat, 24 Feb 2024 01:12:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737163; cv=none; b=UyEUYoMm43u+huc7Kb8zZ6HEuYYNQbG2YeJSRRiDXQmWlb51PGcgTzXpXrlo6j49SH8WmVb7T9hLqKAdMCkiUQZiBP5sRie/7UlI6k4tH6jO7Dduu8sc4j+NgZeU3y1dDR9o39VMHtRow9FGPYKQ4qKN/iR27/Q0Wyxdhrjtqpc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708737163; c=relaxed/simple; bh=RhYBozOR/vT83f2iUyIcPaS4H6kLQSPsmlviIcctaow=; h=Date:Subject:From:To:Cc:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=YiEHz9yL5BkPbgMpgTgSmNEB6tdGm+28tg8unXNHEJU8x8uEtMmNP5h2jwXxhptQf4C/0koHHFdS05PePeAnYfSsXBTrZVeZK2G9mzh6869iCmqqCvA3noLk6Vw0PxxoEQnUFUdEmsqIE22kSNWXKFm97w+MoNelW9A/+E+A4os= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=h2oEJ8za; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="h2oEJ8za" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8701CC433C7; Sat, 24 Feb 2024 01:12:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1708737162; bh=RhYBozOR/vT83f2iUyIcPaS4H6kLQSPsmlviIcctaow=; h=Date:Subject:From:To:Cc:In-Reply-To:References:From; b=h2oEJ8zaC+YKy5CgRKbFQx0lMXQlGzNEjspfXJR6hq5ulRxPCZ6SckWUKHw6+0eTO TtGIYKBjDtv6qQV4e/GBHql5tt9/6pXJP/T3M1TmU6oVHWdrG9fwNxWXTLDOoEM3US 7ipzqEFeTVBXDJCemRPIZoiZk4/QVrLZTuWy3wNWQzgyVtWatnF6Wq/E0XXLYv9jy1 pTMAOWwG6hpZXMlrHsUTJGTE/xozmleLVQag3ZMpcnvasAJFL+wNUsJItR6TgOX/cL ugrbPGr+/8HQjpsYmEjxR2IjeXZAnVi2cD33BBV0tOOnYTs/HRjwASugskt0oLT54T Il7reyJ6cB68A== Date: Fri, 23 Feb 2024 17:12:42 -0800 Subject: [PATCH 10/10] time_stats: Kill TIME_STATS_HAVE_QUANTILES From: "Darrick J. Wong" To: akpm@linux-foundation.org, daniel@gluo.nz, kent.overstreet@linux.dev, djwong@kernel.org Cc: linux-xfs@vger.kernel.org, linux-bcachefs@vger.kernel.org, linux-kernel@vger.kernel.org Message-ID: <170873668101.1860949.4100731238233533238.stgit@frogsfrogsfrogs> In-Reply-To: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> References: <170873667916.1860949.11027844260383646446.stgit@frogsfrogsfrogs> User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-xfs@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Kent Overstreet We have 4 spare bytes next to the spinlock, no need for bit stuffing Signed-off-by: Kent Overstreet Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong --- include/linux/time_stats.h | 19 +++++-------------- lib/time_stats.c | 4 ++-- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/include/linux/time_stats.h b/include/linux/time_stats.h index 4e1f5485ed039..6df2b34aa274b 100644 --- a/include/linux/time_stats.h +++ b/include/linux/time_stats.h @@ -68,6 +68,7 @@ struct time_stat_buffer { struct time_stats { spinlock_t lock; + bool have_quantiles; /* all fields are in nanoseconds */ u64 min_duration; u64 max_duration; @@ -87,12 +88,6 @@ struct time_stats { struct mean_and_variance_weighted freq_stats_weighted; struct time_stat_buffer __percpu *buffer; -/* - * Is this really a struct time_stats_quantiled? Hide this flag in the least - * significant bit of the start time to avoid blowing up the structure size. - */ -#define TIME_STATS_HAVE_QUANTILES (1ULL << 0) - u64 start_time; }; @@ -103,13 +98,9 @@ struct time_stats_quantiles { static inline struct quantiles *time_stats_to_quantiles(struct time_stats *stats) { - struct time_stats_quantiles *statq; - - if (!(stats->start_time & TIME_STATS_HAVE_QUANTILES)) - return NULL; - - statq = container_of(stats, struct time_stats_quantiles, stats); - return &statq->quantiles; + return stats->have_quantiles + ? &container_of(stats, struct time_stats_quantiles, stats)->quantiles + : NULL; } void __time_stats_clear_buffer(struct time_stats *, struct time_stat_buffer *); @@ -169,7 +160,7 @@ static inline void time_stats_quantiles_exit(struct time_stats_quantiles *statq) static inline void time_stats_quantiles_init(struct time_stats_quantiles *statq) { time_stats_init(&statq->stats); - statq->stats.start_time |= TIME_STATS_HAVE_QUANTILES; + statq->stats.have_quantiles = true; memset(&statq->quantiles, 0, sizeof(statq->quantiles)); } diff --git a/lib/time_stats.c b/lib/time_stats.c index c0f209dd9f6dd..0b90c80cba9f1 100644 --- a/lib/time_stats.c +++ b/lib/time_stats.c @@ -164,7 +164,7 @@ static void seq_buf_time_units_aligned(struct seq_buf *out, u64 ns) static inline u64 time_stats_lifetime(const struct time_stats *stats) { - return local_clock() - (stats->start_time & ~TIME_STATS_HAVE_QUANTILES); + return local_clock() - stats->start_time; } void time_stats_to_seq_buf(struct seq_buf *out, struct time_stats *stats, @@ -364,7 +364,7 @@ void time_stats_init(struct time_stats *stats) memset(stats, 0, sizeof(*stats)); stats->min_duration = U64_MAX; stats->min_freq = U64_MAX; - stats->start_time = local_clock() & ~TIME_STATS_HAVE_QUANTILES; + stats->start_time = local_clock(); spin_lock_init(&stats->lock); } EXPORT_SYMBOL_GPL(time_stats_init);