* [PATCH v1 -next 0/3] Some optimizations about freezer
@ 2024-09-05 13:41 Chen Ridong
2024-09-05 13:41 ` [PATCH v1 -next 1/3] cgroup/freezer: Reduce redundant traversal for cgroup_freeze Chen Ridong
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Chen Ridong @ 2024-09-05 13:41 UTC (permalink / raw)
To: tj, lizefan.x, hannes, longman, adityakali, sergeh, mkoutny
Cc: cgroups, linux-kernel, chenridong
We optimized the freezer to reduce redundant loops. We add a selftest to
ensure our optimizations cause no harm, and we confirmed that the
performance can be improved.
We tested the following subtree: D, E, F and G each have n children.
A
/ \
B C
/ | \ \
D E F G
/ | \ \
1-n 1-n 1-n 0-n
Our test is to freeze A B C D E F G, and then unfreeze A B C D E F G.
We measured the elapsed time.
BEFORE(ns) AFTER(ns) SAVED(ns)
n=10 142679950 139666014 3,013,936
n=100 199832160 192773032 7,059,128
n=1000 488595100 414901570 73,693,530
As shown above, the larger the value of n, the more significant the time
savings can be. If tested with a deeper hierarchy, the difference could
become even more apparent.
Chen Ridong (3):
cgroup/freezer: Reduce redundant traversal for cgroup_freeze
cgroup/freezer: Reduce redundant propagation for
cgroup_propagate_frozen
cgroup/freezer: Add freeze selftest
include/linux/cgroup-defs.h | 2 +-
kernel/cgroup/freezer.c | 72 ++++++++----
.../testing/selftests/cgroup/test_freezer.sh | 111 ++++++++++++++++++
3 files changed, 160 insertions(+), 25 deletions(-)
create mode 100755 tools/testing/selftests/cgroup/test_freezer.sh
--
2.34.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 -next 1/3] cgroup/freezer: Reduce redundant traversal for cgroup_freeze
2024-09-05 13:41 [PATCH v1 -next 0/3] Some optimizations about freezer Chen Ridong
@ 2024-09-05 13:41 ` Chen Ridong
2024-09-09 19:01 ` Michal Koutný
2024-09-05 13:41 ` [PATCH v1 -next 2/3] cgroup/freezer: Reduce redundant propagation for cgroup_propagate_frozen Chen Ridong
` (2 subsequent siblings)
3 siblings, 1 reply; 13+ messages in thread
From: Chen Ridong @ 2024-09-05 13:41 UTC (permalink / raw)
To: tj, lizefan.x, hannes, longman, adityakali, sergeh, mkoutny
Cc: cgroups, linux-kernel, chenridong
Whether a cgroup is frozen is determined solely by whether it is set to
to be frozen and whether its parent is frozen. Currently, when is cgroup
is frozen or unfrozen, it iterates through the entire subtree to freeze
or unfreeze its descentdants. However, this is unesessary for a cgroup
that does not change its effective frozen status. This path aims to skip
the subtree if its parent does not have a change in effective freeze.
For an example, subtree like, a-b-c-d-e-f-g, when a is frozen, the
entire tree is frozen. If we freeze b and c again, it is unesessary to
iterate d, e, f and g. So does that If we unfreeze b/c.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
include/linux/cgroup-defs.h | 2 +-
kernel/cgroup/freezer.c | 41 ++++++++++++++++++++++---------------
2 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/include/linux/cgroup-defs.h b/include/linux/cgroup-defs.h
index d3aca2c61154..e9d175a1bf94 100644
--- a/include/linux/cgroup-defs.h
+++ b/include/linux/cgroup-defs.h
@@ -393,7 +393,7 @@ struct cgroup_freezer_state {
bool freeze;
/* Should the cgroup actually be frozen? */
- int e_freeze;
+ bool e_freeze;
/* Fields below are protected by css_set_lock */
diff --git a/kernel/cgroup/freezer.c b/kernel/cgroup/freezer.c
index 617861a54793..02af6c1fa957 100644
--- a/kernel/cgroup/freezer.c
+++ b/kernel/cgroup/freezer.c
@@ -45,6 +45,21 @@ static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen)
}
}
+/*
+ * Update cgroup freezer.e_freeze
+ * e_freeze will be set to true if freeze == true or parent's e_freeze == true
+ */
+static inline void cgroup_update_efreeze(struct cgroup *cgrp)
+{
+ struct cgroup *parent = cgroup_parent(cgrp);
+ bool p_e = false;
+
+ if (parent)
+ p_e = parent->freezer.e_freeze;
+
+ cgrp->freezer.e_freeze = cgrp->freezer.freeze | p_e;
+}
+
/*
* Revisit the cgroup frozen state.
* Checks if the cgroup is really frozen and perform all state transitions.
@@ -262,6 +277,7 @@ void cgroup_freeze(struct cgroup *cgrp, bool freeze)
struct cgroup_subsys_state *css;
struct cgroup *dsct;
bool applied = false;
+ bool old_e;
lockdep_assert_held(&cgroup_mutex);
@@ -282,22 +298,15 @@ void cgroup_freeze(struct cgroup *cgrp, bool freeze)
if (cgroup_is_dead(dsct))
continue;
- if (freeze) {
- dsct->freezer.e_freeze++;
- /*
- * Already frozen because of ancestor's settings?
- */
- if (dsct->freezer.e_freeze > 1)
- continue;
- } else {
- dsct->freezer.e_freeze--;
- /*
- * Still frozen because of ancestor's settings?
- */
- if (dsct->freezer.e_freeze > 0)
- continue;
-
- WARN_ON_ONCE(dsct->freezer.e_freeze < 0);
+ /*
+ * If old e_freeze eq new e_freeze, no change, its children
+ * will not be affected. So do nothing and skip the subtree
+ */
+ old_e = dsct->freezer.e_freeze;
+ cgroup_update_efreeze(dsct);
+ if (dsct->freezer.e_freeze == old_e) {
+ css = css_rightmost_descendant(css);
+ continue;
}
/*
--
2.34.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 -next 2/3] cgroup/freezer: Reduce redundant propagation for cgroup_propagate_frozen
2024-09-05 13:41 [PATCH v1 -next 0/3] Some optimizations about freezer Chen Ridong
2024-09-05 13:41 ` [PATCH v1 -next 1/3] cgroup/freezer: Reduce redundant traversal for cgroup_freeze Chen Ridong
@ 2024-09-05 13:41 ` Chen Ridong
2024-09-09 19:02 ` Michal Koutný
2024-09-05 13:41 ` [PATCH v1 -next 3/3] cgroup/freezer: Add freeze selftest Chen Ridong
2024-09-09 19:04 ` [PATCH v1 -next 0/3] Some optimizations about freezer Michal Koutný
3 siblings, 1 reply; 13+ messages in thread
From: Chen Ridong @ 2024-09-05 13:41 UTC (permalink / raw)
To: tj, lizefan.x, hannes, longman, adityakali, sergeh, mkoutny
Cc: cgroups, linux-kernel, chenridong
When a cgroup is frozen/unfrozen, it will always propagate down to up.
However it is unnecessary to propagate to the top every time. This patch
aims to reduce redundant propagation for cgroup_propagate_frozen.
For example, subtree like:
a
|
b
/ | \
c d e
If c is frozen, and d and e are not frozen now, it doesn't have to
propagate to a; Only when c, d and e are all frozen, b and a could be set
to frozen. Therefore, if nr_frozen_descendants is not equal to
nr_descendants, just stop propagate. If a descendant is frozen, the
parent's nr_frozen_descendants add child->nr_descendants + 1. This can
reduce redundant propagation.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
kernel/cgroup/freezer.c | 31 +++++++++++++++++++++++--------
1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/kernel/cgroup/freezer.c b/kernel/cgroup/freezer.c
index 02af6c1fa957..e4bcc41b6a30 100644
--- a/kernel/cgroup/freezer.c
+++ b/kernel/cgroup/freezer.c
@@ -13,7 +13,7 @@
*/
static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen)
{
- int desc = 1;
+ struct cgroup *child = cgrp;
/*
* If the new state is frozen, some freezing ancestor cgroups may change
@@ -23,23 +23,38 @@ static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen)
*/
while ((cgrp = cgroup_parent(cgrp))) {
if (frozen) {
- cgrp->freezer.nr_frozen_descendants += desc;
+ /*
+ * A cgroup is frozen, parent nr frozen descendants should add
+ * nr cgroups of the entire subtree , including child itself.
+ */
+ cgrp->freezer.nr_frozen_descendants += child->nr_descendants + 1;
+
+ /*
+ * If there is other descendant is not frozen,
+ * cgrp and its parent couldn't be frozen, just break
+ */
+ if (cgrp->freezer.nr_frozen_descendants !=
+ cgrp->nr_descendants)
+ break;
+
+ child = cgrp;
if (!test_bit(CGRP_FROZEN, &cgrp->flags) &&
- test_bit(CGRP_FREEZE, &cgrp->flags) &&
- cgrp->freezer.nr_frozen_descendants ==
- cgrp->nr_descendants) {
+ test_bit(CGRP_FREEZE, &cgrp->flags)) {
set_bit(CGRP_FROZEN, &cgrp->flags);
cgroup_file_notify(&cgrp->events_file);
TRACE_CGROUP_PATH(notify_frozen, cgrp, 1);
- desc++;
}
} else {
- cgrp->freezer.nr_frozen_descendants -= desc;
+ cgrp->freezer.nr_frozen_descendants -= (child->nr_descendants + 1);
+
+ child = cgrp;
if (test_bit(CGRP_FROZEN, &cgrp->flags)) {
clear_bit(CGRP_FROZEN, &cgrp->flags);
cgroup_file_notify(&cgrp->events_file);
TRACE_CGROUP_PATH(notify_frozen, cgrp, 0);
- desc++;
+ } else {
+ /* If parent is unfrozen, don't have to propagate more */
+ break;
}
}
}
--
2.34.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v1 -next 3/3] cgroup/freezer: Add freeze selftest
2024-09-05 13:41 [PATCH v1 -next 0/3] Some optimizations about freezer Chen Ridong
2024-09-05 13:41 ` [PATCH v1 -next 1/3] cgroup/freezer: Reduce redundant traversal for cgroup_freeze Chen Ridong
2024-09-05 13:41 ` [PATCH v1 -next 2/3] cgroup/freezer: Reduce redundant propagation for cgroup_propagate_frozen Chen Ridong
@ 2024-09-05 13:41 ` Chen Ridong
2024-09-09 19:03 ` Michal Koutný
2024-09-09 19:04 ` [PATCH v1 -next 0/3] Some optimizations about freezer Michal Koutný
3 siblings, 1 reply; 13+ messages in thread
From: Chen Ridong @ 2024-09-05 13:41 UTC (permalink / raw)
To: tj, lizefan.x, hannes, longman, adityakali, sergeh, mkoutny
Cc: cgroups, linux-kernel, chenridong
Add selftest to test cgroup.freeze and check cgroup.events state.
Signed-off-by: Chen Ridong <chenridong@huawei.com>
---
.../testing/selftests/cgroup/test_freezer.sh | 111 ++++++++++++++++++
1 file changed, 111 insertions(+)
create mode 100755 tools/testing/selftests/cgroup/test_freezer.sh
diff --git a/tools/testing/selftests/cgroup/test_freezer.sh b/tools/testing/selftests/cgroup/test_freezer.sh
new file mode 100755
index 000000000000..7178980b1db8
--- /dev/null
+++ b/tools/testing/selftests/cgroup/test_freezer.sh
@@ -0,0 +1,111 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test freeze hierarchy state
+#
+ROOT_PATH=/sys/fs/cgroup
+skip_test() {
+ echo "$1"
+ echo "Test SKIPPED"
+ exit 4 # ksft_skip
+}
+
+write_freeze() {
+ path=$1
+ value=$2
+ echo $value > $ROOT_PATH/$path/cgroup.freeze
+}
+
+get_event_frozen()
+{
+ path=$1
+ return $(cat $ROOT_PATH/$path/cgroup.events | grep frozen | awk '{print $2}')
+}
+
+# the test subtree:
+# A
+# / \
+# B C
+# / | \ \
+# D E F G
+# /
+# H
+
+PATH_MATRIX=(
+ 'A'
+ 'A/B'
+ 'A/C'
+ 'A/B/D'
+ 'A/B/E'
+ 'A/B/F'
+ 'A/C/G'
+ 'A/B/D/H'
+)
+CGRP_CNT=${#PATH_MATRIX[@]}
+
+# Interface value to set/check
+ITF_MATRIX=(
+ #value write to freeze expect event value
+ #A B C D E F G H | A B C D E F G H
+ '1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1'
+ '1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1'
+ '1 0 1 0 0 0 0 0 1 1 1 1 1 1 1 1'
+ '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0'
+
+ '1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1'
+ '1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1'
+ '1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1'
+ '1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1'
+
+ '0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1'
+ '0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1'
+ '0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1'
+ '0 0 1 1 0 0 0 0 0 0 1 1 0 0 1 1'
+ '0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0'
+)
+
+prepare()
+{
+ for i in "${PATH_MATRIX[@]}" ; do
+ path="$ROOT_PATH/$i"
+ mkdir $path
+ done
+}
+
+do_clean()
+{
+ for(( i=$CGRP_CNT-1; i>=0; i-- ));do
+ path="/sys/fs/cgroup/${PATH_MATRIX[i]}"
+ rmdir $path
+ done
+}
+
+run_test()
+{
+ prepare
+ cgrp_cnt="${PATH_MATRIX[@]}"
+ for i in "${ITF_MATRIX[@]}" ; do
+ args=($i)
+ #write freeze
+ for(( j=0; j<$CGRP_CNT; j++ ));do
+ write_freeze "${PATH_MATRIX[j]}" ${args[j]}
+ done
+ #event frozen should eq expected value
+ for(( j=0; j<$CGRP_CNT; j++ ));do
+ get_event_frozen "${PATH_MATRIX[j]}"
+ if [ $? -ne ${args[j + $CGRP_CNT]} ];then
+ echo "failed: $i"
+ do_clean
+ exit 1
+ fi
+ done
+ done
+ do_clean
+}
+
+start_time=$(date +%s%N)
+run_test
+end_time=$(date +%s%N)
+elapsed_time=$((end_time - start_time))
+echo "Test PASSED, elapsed_time:$elapsed_time (ns)"
+exit 0
--
2.34.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 -next 1/3] cgroup/freezer: Reduce redundant traversal for cgroup_freeze
2024-09-05 13:41 ` [PATCH v1 -next 1/3] cgroup/freezer: Reduce redundant traversal for cgroup_freeze Chen Ridong
@ 2024-09-09 19:01 ` Michal Koutný
2024-09-10 2:39 ` Chen Ridong
0 siblings, 1 reply; 13+ messages in thread
From: Michal Koutný @ 2024-09-09 19:01 UTC (permalink / raw)
To: Chen Ridong
Cc: tj, lizefan.x, hannes, longman, adityakali, sergeh, cgroups,
linux-kernel, chenridong
[-- Attachment #1: Type: text/plain, Size: 1220 bytes --]
On Thu, Sep 05, 2024 at 01:41:28PM GMT, Chen Ridong <chenridong@huawei.com> wrote:
> Whether a cgroup is frozen is determined solely by whether it is set to
> to be frozen and whether its parent is frozen. Currently, when is cgroup
> is frozen or unfrozen, it iterates through the entire subtree to freeze
> or unfreeze its descentdants.
It's more to maintain the numeric freeze "layers".
> However, this is unesessary for a cgroup that does not change its
> effective frozen status.
True.
> +static inline void cgroup_update_efreeze(struct cgroup *cgrp)
> +{
> + struct cgroup *parent = cgroup_parent(cgrp);
> + bool p_e = false;
> +
> + if (parent)
> + p_e = parent->freezer.e_freeze;
> +
> + cgrp->freezer.e_freeze = cgrp->freezer.freeze | p_e;
Better be || on bools
I'd open code this inside the loop of cgroup_freeze since it is not
context-less function and it relies on top-down processing.
Root cgrp cannot be frozen. You can bail out early in the beginning of
cgroup_freeze() (possibly with a WARN_ON) and then assume parent is
always valid when iterating.
I think maintaining the e_freeze in this "saturated arithmetic" form is
a sensible change.
Thanks,
Michal
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 -next 2/3] cgroup/freezer: Reduce redundant propagation for cgroup_propagate_frozen
2024-09-05 13:41 ` [PATCH v1 -next 2/3] cgroup/freezer: Reduce redundant propagation for cgroup_propagate_frozen Chen Ridong
@ 2024-09-09 19:02 ` Michal Koutný
2024-09-10 3:08 ` Chen Ridong
0 siblings, 1 reply; 13+ messages in thread
From: Michal Koutný @ 2024-09-09 19:02 UTC (permalink / raw)
To: Chen Ridong
Cc: tj, lizefan.x, hannes, longman, adityakali, sergeh, cgroups,
linux-kernel, chenridong
[-- Attachment #1: Type: text/plain, Size: 4086 bytes --]
On Thu, Sep 05, 2024 at 01:41:29PM GMT, Chen Ridong <chenridong@huawei.com> wrote:
> When a cgroup is frozen/unfrozen, it will always propagate down to up.
bottom up
> However it is unnecessary to propagate to the top every time. This patch
> aims to reduce redundant propagation for cgroup_propagate_frozen.
>
> For example, subtree like:
> a
> |
> b
> / | \
> c d e
> If c is frozen, and d and e are not frozen now, it doesn't have to
> propagate to a; Only when c, d and e are all frozen, b and a could be set
> to frozen. Therefore, if nr_frozen_descendants is not equal to
> nr_descendants, just stop propagate. If a descendant is frozen, the
> parent's nr_frozen_descendants add child->nr_descendants + 1. This can
> reduce redundant propagation.
So, IIUC, this saves the updates by aggregating updates of
nr_frozen_descendants into chunks sized same like each child's
nr_descendants, otherwise there's no effect to propagate upward,
correct?
This would deserve some update of the
cgroup_freezer_state.nr_frozen_descendants comment.
>
> Signed-off-by: Chen Ridong <chenridong@huawei.com>
> ---
> kernel/cgroup/freezer.c | 31 +++++++++++++++++++++++--------
> 1 file changed, 23 insertions(+), 8 deletions(-)
>
> diff --git a/kernel/cgroup/freezer.c b/kernel/cgroup/freezer.c
> index 02af6c1fa957..e4bcc41b6a30 100644
> --- a/kernel/cgroup/freezer.c
> +++ b/kernel/cgroup/freezer.c
> @@ -13,7 +13,7 @@
> */
> static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen)
> {
> - int desc = 1;
> + struct cgroup *child = cgrp;
>
> /*
> * If the new state is frozen, some freezing ancestor cgroups may change
> @@ -23,23 +23,38 @@ static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen)
> */
> while ((cgrp = cgroup_parent(cgrp))) {
> if (frozen) {
> - cgrp->freezer.nr_frozen_descendants += desc;
> + /*
> + * A cgroup is frozen, parent nr frozen descendants should add
> + * nr cgroups of the entire subtree , including child itself.
> + */
> + cgrp->freezer.nr_frozen_descendants += child->nr_descendants + 1;
Shouldn't this be
cgrp->freezer.nr_frozen_descendants += child->nr_frozen_descendants + 1;
?
> +
> + /*
> + * If there is other descendant is not frozen,
> + * cgrp and its parent couldn't be frozen, just break
> + */
> + if (cgrp->freezer.nr_frozen_descendants !=
> + cgrp->nr_descendants)
> + break;
Parent's (and ancestral) nr_frozen_descendants would be out of date.
This should be correct also wrt cgroup creation and removal.
> +
> + child = cgrp;
This is same in both branches, so it can be taken outside (maybe even
replace while() with for() if it's cleaner.)
> if (!test_bit(CGRP_FROZEN, &cgrp->flags) &&
> - test_bit(CGRP_FREEZE, &cgrp->flags) &&
> - cgrp->freezer.nr_frozen_descendants ==
> - cgrp->nr_descendants) {
> + test_bit(CGRP_FREEZE, &cgrp->flags)) {
> set_bit(CGRP_FROZEN, &cgrp->flags);
> cgroup_file_notify(&cgrp->events_file);
> TRACE_CGROUP_PATH(notify_frozen, cgrp, 1);
> - desc++;
> }
> } else {
> - cgrp->freezer.nr_frozen_descendants -= desc;
> + cgrp->freezer.nr_frozen_descendants -= (child->nr_descendants + 1);
nit: here you add parentheses but not in the frozen branch
> +
> + child = cgrp;
> if (test_bit(CGRP_FROZEN, &cgrp->flags)) {
> clear_bit(CGRP_FROZEN, &cgrp->flags);
> cgroup_file_notify(&cgrp->events_file);
> TRACE_CGROUP_PATH(notify_frozen, cgrp, 0);
> - desc++;
> + } else {
> + /* If parent is unfrozen, don't have to propagate more */
> + break;
> }
> }
> }
I understand the idea roughly. The code in cgroup_propagate_frozen was
(and stays after your change) slightly difficult to read smoothly but I
think if it can be changed, the reduced (tree) iteration may end up
correct.
Thanks,
Michal
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 -next 3/3] cgroup/freezer: Add freeze selftest
2024-09-05 13:41 ` [PATCH v1 -next 3/3] cgroup/freezer: Add freeze selftest Chen Ridong
@ 2024-09-09 19:03 ` Michal Koutný
2024-09-10 3:09 ` Chen Ridong
0 siblings, 1 reply; 13+ messages in thread
From: Michal Koutný @ 2024-09-09 19:03 UTC (permalink / raw)
To: Chen Ridong
Cc: tj, lizefan.x, hannes, longman, adityakali, sergeh, cgroups,
linux-kernel, chenridong
[-- Attachment #1: Type: text/plain, Size: 486 bytes --]
On Thu, Sep 05, 2024 at 01:41:30PM GMT, Chen Ridong <chenridong@huawei.com> wrote:
> Add selftest to test cgroup.freeze and check cgroup.events state.
There is already tools/testing/selftests/cgroup/test_freezer.c
Would you consider adding this as a new test for hierarchies there?
So that all freezer tests can be run at once and maintained in same style?
(There are already some creation/removal/event helpers so it shouldn't
be more difficult than the bash code.)
Thanks,
Michal
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 -next 0/3] Some optimizations about freezer
2024-09-05 13:41 [PATCH v1 -next 0/3] Some optimizations about freezer Chen Ridong
` (2 preceding siblings ...)
2024-09-05 13:41 ` [PATCH v1 -next 3/3] cgroup/freezer: Add freeze selftest Chen Ridong
@ 2024-09-09 19:04 ` Michal Koutný
2024-09-10 3:16 ` Chen Ridong
3 siblings, 1 reply; 13+ messages in thread
From: Michal Koutný @ 2024-09-09 19:04 UTC (permalink / raw)
To: Chen Ridong
Cc: tj, lizefan.x, hannes, longman, adityakali, sergeh, cgroups,
linux-kernel, chenridong
[-- Attachment #1: Type: text/plain, Size: 1408 bytes --]
Hello.
On Thu, Sep 05, 2024 at 01:41:27PM GMT, Chen Ridong <chenridong@huawei.com> wrote:
> We optimized the freezer to reduce redundant loops. We add a selftest to
> ensure our optimizations cause no harm, and we confirmed that the
> performance can be improved.
I think these patches have potential to make the code also cleaner and
better to understand (the numbers from optimization don't impress me
that much at the moment).
I post more comments on the individual patches.
> We tested the following subtree: D, E, F and G each have n children.
> A
> / \
> B C
> / | \ \
> D E F G
> / | \ \
> 1-n 1-n 1-n 0-n
(Why is the last one different?)
> Our test is to freeze A B C D E F G, and then unfreeze A B C D E F G.
I would say measuring freezing/unfreezing of only A would give better
idea about the impact of the change.
(Going through all descendants manually would unfairly show greater
improvement.)
> We measured the elapsed time.
>
> BEFORE(ns) AFTER(ns) SAVED(ns)
> n=10 142679950 139666014 3,013,936
> n=100 199832160 192773032 7,059,128
> n=1000 488595100 414901570 73,693,530
How many tasks were there inside cgroups in this benchmark?
(I assume in practice the freezing time would be dominated by waiting
for tasks' response, so it'd be good to note this beside this result.)
Thanks,
Michal
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 -next 1/3] cgroup/freezer: Reduce redundant traversal for cgroup_freeze
2024-09-09 19:01 ` Michal Koutný
@ 2024-09-10 2:39 ` Chen Ridong
0 siblings, 0 replies; 13+ messages in thread
From: Chen Ridong @ 2024-09-10 2:39 UTC (permalink / raw)
To: Michal Koutný, Chen Ridong
Cc: tj, lizefan.x, hannes, longman, adityakali, sergeh, cgroups,
linux-kernel
On 2024/9/10 3:01, Michal Koutný wrote:
> On Thu, Sep 05, 2024 at 01:41:28PM GMT, Chen Ridong <chenridong@huawei.com> wrote:
>> Whether a cgroup is frozen is determined solely by whether it is set to
>> to be frozen and whether its parent is frozen. Currently, when is cgroup
>> is frozen or unfrozen, it iterates through the entire subtree to freeze
>> or unfreeze its descentdants.
>
> It's more to maintain the numeric freeze "layers".
>
>> However, this is unesessary for a cgroup that does not change its
>> effective frozen status.
>
> True.
>
>> +static inline void cgroup_update_efreeze(struct cgroup *cgrp)
>> +{
>> + struct cgroup *parent = cgroup_parent(cgrp);
>> + bool p_e = false;
>> +
>> + if (parent)
>> + p_e = parent->freezer.e_freeze;
>> +
>> + cgrp->freezer.e_freeze = cgrp->freezer.freeze | p_e;
>
> Better be || on bools
>
Thanks you, that is right.
> I'd open code this inside the loop of cgroup_freeze since it is not
> context-less function and it relies on top-down processing.
>
> Root cgrp cannot be frozen. You can bail out early in the beginning of
> cgroup_freeze() (possibly with a WARN_ON) and then assume parent is
> always valid when iterating.
>
'cgroup.freeze' is with CFTYPE_NOT_ON_ROOT tag, root cgroup will never
be frozen, considering root cgroup seems to be unesessary. I will open
the code inside the loop of cgroup_freeze in next patch.
Thanks
Ridong
> I think maintaining the e_freeze in this "saturated arithmetic" form is
> a sensible change.
>
> Thanks,
> Michal
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 -next 2/3] cgroup/freezer: Reduce redundant propagation for cgroup_propagate_frozen
2024-09-09 19:02 ` Michal Koutný
@ 2024-09-10 3:08 ` Chen Ridong
2024-09-10 11:33 ` Michal Koutný
0 siblings, 1 reply; 13+ messages in thread
From: Chen Ridong @ 2024-09-10 3:08 UTC (permalink / raw)
To: Michal Koutný, Chen Ridong
Cc: tj, lizefan.x, hannes, longman, adityakali, sergeh, cgroups,
linux-kernel
On 2024/9/10 3:02, Michal Koutný wrote:
> On Thu, Sep 05, 2024 at 01:41:29PM GMT, Chen Ridong <chenridong@huawei.com> wrote:
>> When a cgroup is frozen/unfrozen, it will always propagate down to up.
> bottom up
>
>> However it is unnecessary to propagate to the top every time. This patch
>> aims to reduce redundant propagation for cgroup_propagate_frozen.
>>
>> For example, subtree like:
>> a
>> |
>> b
>> / | \
>> c d e
>> If c is frozen, and d and e are not frozen now, it doesn't have to
>> propagate to a; Only when c, d and e are all frozen, b and a could be set
>> to frozen. Therefore, if nr_frozen_descendants is not equal to
>> nr_descendants, just stop propagate. If a descendant is frozen, the
>> parent's nr_frozen_descendants add child->nr_descendants + 1. This can
>> reduce redundant propagation.
>
> So, IIUC, this saves the updates by aggregating updates of
> nr_frozen_descendants into chunks sized same like each child's
> nr_descendants, otherwise there's no effect to propagate upward,
> correct?
>
correct.
> This would deserve some update of the
> cgroup_freezer_state.nr_frozen_descendants comment.
>
>>
>> Signed-off-by: Chen Ridong <chenridong@huawei.com>
>> ---
>> kernel/cgroup/freezer.c | 31 +++++++++++++++++++++++--------
>> 1 file changed, 23 insertions(+), 8 deletions(-)
>>
>> diff --git a/kernel/cgroup/freezer.c b/kernel/cgroup/freezer.c
>> index 02af6c1fa957..e4bcc41b6a30 100644
>> --- a/kernel/cgroup/freezer.c
>> +++ b/kernel/cgroup/freezer.c
>> @@ -13,7 +13,7 @@
>> */
>> static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen)
>> {
>> - int desc = 1;
>> + struct cgroup *child = cgrp;
>>
>> /*
>> * If the new state is frozen, some freezing ancestor cgroups may change
>> @@ -23,23 +23,38 @@ static void cgroup_propagate_frozen(struct cgroup *cgrp, bool frozen)
>> */
>> while ((cgrp = cgroup_parent(cgrp))) {
>> if (frozen) {
>> - cgrp->freezer.nr_frozen_descendants += desc;
>> + /*
>> + * A cgroup is frozen, parent nr frozen descendants should add
>> + * nr cgroups of the entire subtree , including child itself.
>> + */
>> + cgrp->freezer.nr_frozen_descendants += child->nr_descendants + 1;
>
> Shouldn't this be
> cgrp->freezer.nr_frozen_descendants += child->nr_frozen_descendants + 1;
> ?
child->nr_frozen_descendants should be equal to child->nr_descendants if
the subtree is already frozen.
>
>> +
>> + /*
>> + * If there is other descendant is not frozen,
>> + * cgrp and its parent couldn't be frozen, just break
>> + */
>> + if (cgrp->freezer.nr_frozen_descendants !=
>> + cgrp->nr_descendants)
>> + break;
>
> Parent's (and ancestral) nr_frozen_descendants would be out of date.
> This should be correct also wrt cgroup creation and removal.
>
Before calling cgroup_freeze, cgroup_freeze_write have hold the
cgroup_mutex, could parent's nr_frozen_descendants be changed?
>> +
>> + child = cgrp;
>
> This is same in both branches, so it can be taken outside (maybe even
> replace while() with for() if it's cleaner.)
I will try.
>
>> if (!test_bit(CGRP_FROZEN, &cgrp->flags) &&
>> - test_bit(CGRP_FREEZE, &cgrp->flags) &&
>> - cgrp->freezer.nr_frozen_descendants ==
>> - cgrp->nr_descendants) {
>> + test_bit(CGRP_FREEZE, &cgrp->flags)) {
>> set_bit(CGRP_FROZEN, &cgrp->flags);
>> cgroup_file_notify(&cgrp->events_file);
>> TRACE_CGROUP_PATH(notify_frozen, cgrp, 1);
>> - desc++;
>> }
>> } else {
>> - cgrp->freezer.nr_frozen_descendants -= desc;
>> + cgrp->freezer.nr_frozen_descendants -= (child->nr_descendants + 1);
>
> nit: here you add parentheses but not in the frozen branch
>
>> +
>> + child = cgrp;
>> if (test_bit(CGRP_FROZEN, &cgrp->flags)) {
>> clear_bit(CGRP_FROZEN, &cgrp->flags);
>> cgroup_file_notify(&cgrp->events_file);
>> TRACE_CGROUP_PATH(notify_frozen, cgrp, 0);
>> - desc++;
>> + } else {
>> + /* If parent is unfrozen, don't have to propagate more */
>> + break;
>> }
>> }
>> }
>
> I understand the idea roughly. The code in cgroup_propagate_frozen was
> (and stays after your change) slightly difficult to read smoothly but I
> think if it can be changed, the reduced (tree) iteration may end up
> correct.
>
>
> Thanks,
> Michal
Thanks, I will update in next patch.
Best regards,
Ridong
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 -next 3/3] cgroup/freezer: Add freeze selftest
2024-09-09 19:03 ` Michal Koutný
@ 2024-09-10 3:09 ` Chen Ridong
0 siblings, 0 replies; 13+ messages in thread
From: Chen Ridong @ 2024-09-10 3:09 UTC (permalink / raw)
To: Michal Koutný, Chen Ridong
Cc: tj, lizefan.x, hannes, longman, adityakali, sergeh, cgroups,
linux-kernel
On 2024/9/10 3:03, Michal Koutný wrote:
> On Thu, Sep 05, 2024 at 01:41:30PM GMT, Chen Ridong <chenridong@huawei.com> wrote:
>> Add selftest to test cgroup.freeze and check cgroup.events state.
>
> There is already tools/testing/selftests/cgroup/test_freezer.c
> Would you consider adding this as a new test for hierarchies there?
> So that all freezer tests can be run at once and maintained in same style?
>
> (There are already some creation/removal/event helpers so it shouldn't
> be more difficult than the bash code.)
>
> Thanks,
> Michal
>
Okay, I will try.
Thanks,
Ridong
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 -next 0/3] Some optimizations about freezer
2024-09-09 19:04 ` [PATCH v1 -next 0/3] Some optimizations about freezer Michal Koutný
@ 2024-09-10 3:16 ` Chen Ridong
0 siblings, 0 replies; 13+ messages in thread
From: Chen Ridong @ 2024-09-10 3:16 UTC (permalink / raw)
To: Michal Koutný, Chen Ridong
Cc: tj, lizefan.x, hannes, longman, adityakali, sergeh, cgroups,
linux-kernel
On 2024/9/10 3:04, Michal Koutný wrote:
> Hello.
>
> On Thu, Sep 05, 2024 at 01:41:27PM GMT, Chen Ridong <chenridong@huawei.com> wrote:
>> We optimized the freezer to reduce redundant loops. We add a selftest to
>> ensure our optimizations cause no harm, and we confirmed that the
>> performance can be improved.
>
> I think these patches have potential to make the code also cleaner and
> better to understand (the numbers from optimization don't impress me
> that much at the moment).
>
> I post more comments on the individual patches.
>
Thanks.
>> We tested the following subtree: D, E, F and G each have n children.
>> A
>> / \
>> B C
>> / | \ \
>> D E F G
>> / | \ \
>> 1-n 1-n 1-n 0-n
>
> (Why is the last one different?)
>
Sorry, this should be same.
>> Our test is to freeze A B C D E F G, and then unfreeze A B C D E F G.
>
> I would say measuring freezing/unfreezing of only A would give better
> idea about the impact of the change.
> (Going through all descendants manually would unfairly show greater
> improvement.)
>
I will add this test.
And I only test freezing/unfreezing A, The first patch may not be effective.
>> We measured the elapsed time.
>>
>> BEFORE(ns) AFTER(ns) SAVED(ns)
>> n=10 142679950 139666014 3,013,936
>> n=100 199832160 192773032 7,059,128
>> n=1000 488595100 414901570 73,693,530
>
> How many tasks were there inside cgroups in this benchmark?
>
I didn't put tasks inside cgroups to test. Because this series didn't
change how the tasks be froze. That only reduced some redundant loop.
> (I assume in practice the freezing time would be dominated by waiting
> for tasks' response, so it'd be good to note this beside this result.)
>
> Thanks,
> Michal
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v1 -next 2/3] cgroup/freezer: Reduce redundant propagation for cgroup_propagate_frozen
2024-09-10 3:08 ` Chen Ridong
@ 2024-09-10 11:33 ` Michal Koutný
0 siblings, 0 replies; 13+ messages in thread
From: Michal Koutný @ 2024-09-10 11:33 UTC (permalink / raw)
To: Chen Ridong
Cc: Chen Ridong, tj, lizefan.x, hannes, longman, adityakali, sergeh,
cgroups, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 716 bytes --]
On Tue, Sep 10, 2024 at 11:08:12AM GMT, Chen Ridong <chenridong@huaweicloud.com> wrote:
> > This should be correct also wrt cgroup creation and removal.
> >
> Before calling cgroup_freeze, cgroup_freeze_write have hold the
> cgroup_mutex, could parent's nr_frozen_descendants be changed?
Sorry for ambigious wording, I meant that the code you posted appears
to me to be correct (and safe) wrt cgroup tree operations -- thanks to
css_set_lock because frozen bookkeeping is under it (cgroup_mutex would
be too heavy weight for all possible callers of
cgroup_propagate_frozen(), namely cgroup_enter_frozen).
Or do you suggest the current form would need cgroup_mutex
synchronization somehow?
Michal
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2024-09-10 11:33 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-09-05 13:41 [PATCH v1 -next 0/3] Some optimizations about freezer Chen Ridong
2024-09-05 13:41 ` [PATCH v1 -next 1/3] cgroup/freezer: Reduce redundant traversal for cgroup_freeze Chen Ridong
2024-09-09 19:01 ` Michal Koutný
2024-09-10 2:39 ` Chen Ridong
2024-09-05 13:41 ` [PATCH v1 -next 2/3] cgroup/freezer: Reduce redundant propagation for cgroup_propagate_frozen Chen Ridong
2024-09-09 19:02 ` Michal Koutný
2024-09-10 3:08 ` Chen Ridong
2024-09-10 11:33 ` Michal Koutný
2024-09-05 13:41 ` [PATCH v1 -next 3/3] cgroup/freezer: Add freeze selftest Chen Ridong
2024-09-09 19:03 ` Michal Koutný
2024-09-10 3:09 ` Chen Ridong
2024-09-09 19:04 ` [PATCH v1 -next 0/3] Some optimizations about freezer Michal Koutný
2024-09-10 3:16 ` Chen Ridong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®