Skip to contentSkip to conversation

Memory controller soft limit patches (v5)

PATCH In review Balbir Singh 4 participants 38 messages Mar 12, 2009 – Mar 13, 2009

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

cover Memory controller soft limit patches (v5)

From: Balbir Singh <[email protected]>

New Feature: Soft limits for memory resource controller.

Changelog v5...v4
1. Several changes to the reclaim logic, please see the patch 4 (reclaim on contention). I've experimented with several possibilities for reclaim and chose to come back to this due to the excellent behaviour seen while testing the patchset.
2. Reduced the overhead of soft limits on resource counters very significantly. Reaim benchmark now shows almost no drop in performance.

Changelog v4...v3
1. Adopted suggestions from Kamezawa to do a per-zone-per-node reclaim while doing soft limit reclaim. We don't record priorities while doing soft reclaim
2. Some of the overheads associated with soft limits (like calculating excess each time) is eliminated
3. The time_after(jiffies, 0) bug has been fixed
4. Tasks are throttled if the mem cgroup they belong to is being soft reclaimed and at the same time tasks are increasing the memory footprint and causing the mem cgroup to exceed its soft limit.

Changelog v3...v2
1. Implemented several review comments from Kosaki-San and Kamezawa-San Please see individual changelogs for changes

Changelog v2...v1
1. Soft limits now support hierarchies
2. Use spinlocks instead of mutexes for synchronization of the RB tree

Here is v5 of the new soft limit implementation. Soft limits is a new feature for the memory resource controller, something similar has existed in the group scheduler in the form of shares. The CPU controllers interpretation of shares is very different though.

Soft limits are the most useful feature to have for environments where the administrator wants to overcommit the system, such that only on memory contention do the limits become active. The current soft limits implementation provides a soft_limit_in_bytes interface for the memory controller and not for memory+swap controller. The implementation maintains an RB-Tree of groups that exceed their soft limit and starts reclaiming from the group that exceeds this limit by the maximum amount.

Kamezawa-San has another patchset for soft limits, but I don't like the reclaim logic of watermark based balancing of zones for global memory cgroup limits. I also don't like the data structures, a list does not scale well. Kamezawa's
objection to this patch is the cost of sorting, which is really negligible,
since the updates happen at a fixed interval (curently four times a second).
I however do like the priority feature in Kamezawa's patchset. The feature
can be easily adopted to this incrementally.

TODOs

1. The current implementation maintains the delta from the soft limit and pushes back groups to their soft limits, a ratio of delta/soft_limit might be more useful
2. It would be nice to have more targetted reclaim (in terms of pages to recalim) interface. So that groups are pushed back, close to their soft limits.

Tests
-----

I've run two memory intensive workloads with differing soft limits and seen that they are pushed back to their soft limit on contention. Their usage was their soft limit plus additional memory that they were able to grab on the system. Soft limit can take a while before we see the expected results.

The other tests I've run are
1. Deletion of groups while soft limit is in progress in the hierarchy
2. Setting the soft limit to zero and running other groups with non-zero soft limits.
3. Setting the soft limit to zero and testing if the mem cgroup is able to use available memory

Please review, comment.

Series
------

memcg-soft-limit-documentation.patch
memcg-add-soft-limit-interface.patch
memcg-organize-over-soft-limit-groups.patch
memcg-soft-limit-reclaim-on-contention.patch

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#1 lore raw

PATCH 1/4 Memory controller soft limit documentation (v5)

Feature: Add documentation for soft limits

From: Balbir Singh <[email protected]>

---

 Documentation/cgroups/memory.txt |   31 ++++++++++++++++++++++++++++++-
 1 files changed, 30 insertions(+), 1 deletions(-)
Documentation/cgroups/memory.txt +30 -1
index a98a7fe..c5f73d9 100644
@@ -360,7 +360,36 @@ cgroups created below it.
 
 NOTE2: This feature can be enabled/disabled per subtree.
 
-7. TODO
+7. Soft limits
+
+Soft limits allow for greater sharing of memory. The idea behind soft limits
+is to allow control groups to use as much of the memory as needed, provided
+
+a. There is no memory contention
+b. They do not exceed their hard limit
+
+When the system detects memory contention or low memory control groups
+are pushed back to their soft limits. If the soft limit of each control
+group is very high, they are pushed back as much as possible to make
+sure that one control group does not starve the others of memory.
+
+7.1 Interface
+
+Soft limits can be setup by using the following commands (in this example we
+assume a soft limit of 256 megabytes)
+
+# echo 256M > memory.soft_limit_in_bytes
+
+If we want to change this to 1G, we can at any time use
+
+# echo 1G > memory.soft_limit_in_bytes
+
+NOTE1: Soft limits take effect over a long period of time, since they involve
+       reclaiming memory for balancing between memory cgroups
+NOTE2: It is recommended to set the soft limit always below the hard limit,
+       otherwise the hard limit will take precedence.
+
+8. TODO
 
 1. Add support for accounting huge pages (as a separate controller)
 2. Make per-cgroup scanner reclaim not-shared pages first
Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#2 lore raw

PATCH 2/4 Memory controller soft limit interface (v5)

In reply to Balbir Singh

Feature: Add soft limits interface to resource counters

From: Balbir Singh <[email protected]>

Changelog v2...v1
1. Add support for res_counter_check_soft_limit_locked. This is used by the hierarchy code.

Add an interface to allow get/set of soft limits. Soft limits for memory plus swap controller (memsw) is currently not supported. Resource counters have been enhanced to support soft limits and new type RES_SOFT_LIMIT has been added. Unlike hard limits, soft limits can be directly set and do not need any reclaim or checks before setting them to a newer value.

Kamezawa-San raised a question as to whether soft limit should belong to res_counter. Since all resources understand the basic concepts of hard and soft limits, it is justified to add soft limits here. Soft limits are a generic resource usage feature, even file system quotas support soft limits.

---

 include/linux/res_counter.h |   58 +++++++++++++++++++++++++++++++++++++++++++
 kernel/res_counter.c        |    3 ++
 mm/memcontrol.c             |   20 +++++++++++++++
 3 files changed, 81 insertions(+), 0 deletions(-)
include/linux/res_counter.h +58 -0
index 4c5bcf6..5c821fd 100644
@@ -35,6 +35,10 @@ struct res_counter {
 	 */
 	unsigned long long limit;
 	/*
+	 * the limit that usage can be exceed
+	 */
+	unsigned long long soft_limit;
+	/*
 	 * the number of unsuccessful attempts to consume the resource
 	 */
 	unsigned long long failcnt;
@@ -85,6 +89,7 @@ enum {
 	RES_MAX_USAGE,
 	RES_LIMIT,
 	RES_FAILCNT,
+	RES_SOFT_LIMIT,
 };
 
 /*
@@ -130,6 +135,36 @@ static inline bool res_counter_limit_check_locked(struct res_counter *cnt)
 	return false;
 }
 
+static inline bool res_counter_soft_limit_check_locked(struct res_counter *cnt)
+{
+	if (cnt->usage < cnt->soft_limit)
+		return true;
+
+	return false;
+}
+
+/**
+ * Get the difference between the usage and the soft limit
+ * @cnt: The counter
+ *
+ * Returns 0 if usage is less than or equal to soft limit
+ * The difference between usage and soft limit, otherwise.
+ */
+static inline unsigned long long
+res_counter_soft_limit_excess(struct res_counter *cnt)
+{
+	unsigned long long excess;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cnt->lock, flags);
+	if (cnt->usage <= cnt->soft_limit)
+		excess = 0;
+	else
+		excess = cnt->usage - cnt->soft_limit;
+	spin_unlock_irqrestore(&cnt->lock, flags);
+	return excess;
+}
+
 /*
  * Helper function to detect if the cgroup is within it's limit or
  * not. It's currently called from cgroup_rss_prepare()
@@ -145,6 +180,17 @@ static inline bool res_counter_check_under_limit(struct res_counter *cnt)
 	return ret;
 }
 
+static inline bool res_counter_check_under_soft_limit(struct res_counter *cnt)
+{
+	bool ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cnt->lock, flags);
+	ret = res_counter_soft_limit_check_locked(cnt);
+	spin_unlock_irqrestore(&cnt->lock, flags);
+	return ret;
+}
+
 static inline void res_counter_reset_max(struct res_counter *cnt)
 {
 	unsigned long flags;
@@ -178,4 +224,16 @@ static inline int res_counter_set_limit(struct res_counter *cnt,
 	return ret;
 }
 
+static inline int
+res_counter_set_soft_limit(struct res_counter *cnt,
+				unsigned long long soft_limit)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&cnt->lock, flags);
+	cnt->soft_limit = soft_limit;
+	spin_unlock_irqrestore(&cnt->lock, flags);
+	return 0;
+}
+
 #endif
kernel/res_counter.c +3 -0
index bf8e753..4e6dafe 100644
@@ -19,6 +19,7 @@ void res_counter_init(struct res_counter *counter, struct res_counter *parent)
 {
 	spin_lock_init(&counter->lock);
 	counter->limit = (unsigned long long)LLONG_MAX;
+	counter->soft_limit = (unsigned long long)LLONG_MAX;
 	counter->parent = parent;
 }
 
@@ -101,6 +102,8 @@ res_counter_member(struct res_counter *counter, int member)
 		return &counter->limit;
 	case RES_FAILCNT:
 		return &counter->failcnt;
+	case RES_SOFT_LIMIT:
+		return &counter->soft_limit;
 	};
 
 	BUG();
mm/memcontrol.c +20 -0
index 804bbae..b4f5b15 100644
@@ -1986,6 +1986,20 @@ static int mem_cgroup_write(struct cgroup *cont, struct cftype *cft,
 		else
 			ret = mem_cgroup_resize_memsw_limit(memcg, val);
 		break;
+	case RES_SOFT_LIMIT:
+		ret = res_counter_memparse_write_strategy(buffer, &val);
+		if (ret)
+			break;
+		/*
+		 * For memsw, soft limits are hard to implement in terms
+		 * of semantics, for now, we support soft limits for
+		 * control without swap
+		 */
+		if (type == _MEM)
+			ret = res_counter_set_soft_limit(&memcg->res, val);
+		else
+			ret = -EINVAL;
+		break;
 	default:
 		ret = -EINVAL; /* should be BUG() ? */
 		break;
@@ -2235,6 +2249,12 @@ static struct cftype mem_cgroup_files[] = {
 		.read_u64 = mem_cgroup_read,
 	},
 	{
+		.name = "soft_limit_in_bytes",
+		.private = MEMFILE_PRIVATE(_MEM, RES_SOFT_LIMIT),
+		.write_string = mem_cgroup_write,
+		.read_u64 = mem_cgroup_read,
+	},
+	{
 		.name = "failcnt",
 		.private = MEMFILE_PRIVATE(_MEM, RES_FAILCNT),
 		.trigger = mem_cgroup_reset,
Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#3 lore raw

Re: [PATCH 2/4] Memory controller soft limit interface (v5)

Quoted 38 lines · On Thu, 12 Mar 2009 23:26:20 +0530 Balbir Singh <[email protected]>…
(quoted diff) +32 -0
+/**
+ * Get the difference between the usage and the soft limit
+ * @cnt: The counter
+ *
+ * Returns 0 if usage is less than or equal to soft limit
+ * The difference between usage and soft limit, otherwise.
+ */
+static inline unsigned long long
+res_counter_soft_limit_excess(struct res_counter *cnt)
+{
+	unsigned long long excess;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cnt->lock, flags);
+	if (cnt->usage <= cnt->soft_limit)
+		excess = 0;
+	else
+		excess = cnt->usage - cnt->soft_limit;
+	spin_unlock_irqrestore(&cnt->lock, flags);
+	return excess;
+}
 
...
 
+static inline bool res_counter_check_under_soft_limit(struct res_counter *cnt)
+{
+	bool ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cnt->lock, flags);
+	ret = res_counter_soft_limit_check_locked(cnt);
+	spin_unlock_irqrestore(&cnt->lock, flags);
+	return ret;
+}
 
...
 
+static inline int

Review

Quoted 10 lines
(quoted diff) +10 -0
+res_counter_set_soft_limit(struct res_counter *cnt,
+				unsigned long long soft_limit)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&cnt->lock, flags);
+	cnt->soft_limit = soft_limit;
+	spin_unlock_irqrestore(&cnt->lock, flags);
+	return 0;
+}

These functions look too large to be inlined?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#4 lore raw

Re: [PATCH 2/4] Memory controller soft limit interface (v5)

Quoted 40 lines · Andrew Morton
Quoted 37 lines · On Thu, 12 Mar 2009 23:26:20 +0530 Balbir Singh <[email protected]>…
include/linux/res_counter.h +31 -0
+/**
+ * Get the difference between the usage and the soft limit
+ * @cnt: The counter
+ *
+ * Returns 0 if usage is less than or equal to soft limit
+ * The difference between usage and soft limit, otherwise.
+ */
+static inline unsigned long long
+res_counter_soft_limit_excess(struct res_counter *cnt)
+{
+	unsigned long long excess;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cnt->lock, flags);
+	if (cnt->usage <= cnt->soft_limit)
+		excess = 0;
+	else
+		excess = cnt->usage - cnt->soft_limit;
+	spin_unlock_irqrestore(&cnt->lock, flags);
+	return excess;
+}
 
...
 
+static inline bool res_counter_check_under_soft_limit(struct res_counter *cnt)
+{
+	bool ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cnt->lock, flags);
+	ret = res_counter_soft_limit_check_locked(cnt);
+	spin_unlock_irqrestore(&cnt->lock, flags);
+	return ret;
+}
 
...
Quoted 14 lines

include/linux/res_counter.h static inline int res_counter_set_limit(struct res_counter *cnt, · line 237

Quoted 11 lines
include/linux/res_counter.h +11 -0
+static inline int
+res_counter_set_soft_limit(struct res_counter *cnt,
+				unsigned long long soft_limit)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&cnt->lock, flags);
+	cnt->soft_limit = soft_limit;
+	spin_unlock_irqrestore(&cnt->lock, flags);
+	return 0;
+}

These functions look too large to be inlined?

I'll send a patch to fix it and move them to res_counter.c

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#5 lore raw

PATCH 3/4 Memory controller soft limit organize cgroups (v5)

In reply to Balbir Singh

Feature: Organize cgroups over soft limit in a RB-Tree

From: Balbir Singh <[email protected]>

Changelog v5...v4
1. res_counter_uncharge has an additional parameter to indicate if the counter was over its soft limit, before uncharge.

Changelog v4...v3
1. Optimizations to ensure we don't uncessarily get res_counter values
2. Fixed a bug in usage of time_after()

Changelog v3...v2
1. Add only the ancestor to the RB-Tree
2. Use css_tryget/css_put instead of mem_cgroup_get/mem_cgroup_put

Changelog v2...v1
1. Add support for hierarchies
2. The res_counter that is highest in the hierarchy is returned on soft limit being exceeded. Since we do hierarchical reclaim and add all groups exceeding their soft limits, this approach seems to work well in practice.

This patch introduces a RB-Tree for storing memory cgroups that are over their soft limit. The overall goal is to

1. Add a memory cgroup to the RB-Tree when the soft limit is exceeded. We are careful about updates, updates take place only after a particular time interval has passed
2. We remove the node from the RB-Tree when the usage goes below the soft limit

The next set of patches will exploit the RB-Tree to get the group that is over its soft limit by the largest amount and reclaim from it, when we face memory contention.

---

 include/linux/res_counter.h |    6 +-
 kernel/res_counter.c        |   18 +++++
 mm/memcontrol.c             |  141 ++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 143 insertions(+), 22 deletions(-)
include/linux/res_counter.h +4 -2
index 5c821fd..5bbf8b1 100644
@@ -112,7 +112,8 @@ void res_counter_init(struct res_counter *counter, struct res_counter *parent);
 int __must_check res_counter_charge_locked(struct res_counter *counter,
 		unsigned long val);
 int __must_check res_counter_charge(struct res_counter *counter,
-		unsigned long val, struct res_counter **limit_fail_at);
+		unsigned long val, struct res_counter **limit_fail_at,
+		struct res_counter **soft_limit_at);
 
 /*
  * uncharge - tell that some portion of the resource is released
@@ -125,7 +126,8 @@ int __must_check res_counter_charge(struct res_counter *counter,
  */
 
 void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val);
-void res_counter_uncharge(struct res_counter *counter, unsigned long val);
+void res_counter_uncharge(struct res_counter *counter, unsigned long val,
+				bool *was_soft_limit_excess);
 
 static inline bool res_counter_limit_check_locked(struct res_counter *cnt)
 {
kernel/res_counter.c +16 -2
index 4e6dafe..51ec438 100644
@@ -37,17 +37,27 @@ int res_counter_charge_locked(struct res_counter *counter, unsigned long val)
 }
 
 int res_counter_charge(struct res_counter *counter, unsigned long val,
-			struct res_counter **limit_fail_at)
+			struct res_counter **limit_fail_at,
+			struct res_counter **soft_limit_fail_at)
 {
 	int ret;
 	unsigned long flags;
 	struct res_counter *c, *u;
 
 	*limit_fail_at = NULL;
+	if (soft_limit_fail_at)
+		*soft_limit_fail_at = NULL;
 	local_irq_save(flags);
 	for (c = counter; c != NULL; c = c->parent) {
 		spin_lock(&c->lock);
 		ret = res_counter_charge_locked(c, val);
+		/*
+		 * With soft limits, we return the highest ancestor
+		 * that exceeds its soft limit
+		 */
+		if (soft_limit_fail_at &&
+			!res_counter_soft_limit_check_locked(c))
+			*soft_limit_fail_at = c;
 		spin_unlock(&c->lock);
 		if (ret < 0) {
 			*limit_fail_at = c;
@@ -75,7 +85,8 @@ void res_counter_uncharge_locked(struct res_counter *counter, unsigned long val)
 	counter->usage -= val;
 }
 
-void res_counter_uncharge(struct res_counter *counter, unsigned long val)
+void res_counter_uncharge(struct res_counter *counter, unsigned long val,
+				bool *was_soft_limit_excess)
 {
 	unsigned long flags;
 	struct res_counter *c;
@@ -83,6 +94,9 @@ void res_counter_uncharge(struct res_counter *counter, unsigned long val)
 	local_irq_save(flags);
 	for (c = counter; c != NULL; c = c->parent) {
 		spin_lock(&c->lock);
+		if (c == counter && was_soft_limit_excess)
+			*was_soft_limit_excess =
+				!res_counter_soft_limit_check_locked(c);
 		res_counter_uncharge_locked(c, val);
 		spin_unlock(&c->lock);
 	}
mm/memcontrol.c +123 -18

287 lines not on this page · raw message

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#6 lore raw

Re: [PATCH 3/4] Memory controller soft limit organize cgroups (v5)

Quoted 32 lines · On Thu, 12 Mar 2009 23:26:25 +0530 Balbir Singh <[email protected]>…

Feature: Organize cgroups over soft limit in a RB-Tree

From: Balbir Singh <[email protected]>

Changelog v5...v4
1. res_counter_uncharge has an additional parameter to indicate if the counter was over its soft limit, before uncharge.

Changelog v4...v3
1. Optimizations to ensure we don't uncessarily get res_counter values
2. Fixed a bug in usage of time_after()

Changelog v3...v2
1. Add only the ancestor to the RB-Tree
2. Use css_tryget/css_put instead of mem_cgroup_get/mem_cgroup_put

Changelog v2...v1
1. Add support for hierarchies
2. The res_counter that is highest in the hierarchy is returned on soft limit being exceeded. Since we do hierarchical reclaim and add all groups exceeding their soft limits, this approach seems to work well in practice.

This patch introduces a RB-Tree for storing memory cgroups that are over their soft limit. The overall goal is to

1. Add a memory cgroup to the RB-Tree when the soft limit is exceeded. We are careful about updates, updates take place only after a particular time interval has passed
2. We remove the node from the RB-Tree when the usage goes below the soft limit

Quoted 8 lines

The next set of patches will exploit the RB-Tree to get the group that is over its soft limit by the largest amount and reclaim from it, when we face memory contention.

...

+#define MEM_CGROUP_TREE_UPDATE_INTERVAL (HZ/4)

Wall-clock time is a quite poor way of tracking system activity. There's little correlation between the two things.

Quoted 1 line

From a general design point of view it would be better to pace this

polling activity in a manner which correlates with the amount of system activity. For example, "once per 100,000 pages scanned" is much more adaptive than "once per 250 milliseconds".

mm/memcontrol.c mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) · line 2564

Quoted 7 lines

...

Quoted 1 line
(quoted diff) +0 -0
@@ -2459,6 +2561,7 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
mm/memcontrol.c +1 -0
 	if (cont->parent == NULL) {
 		enable_swap_cgroup();
 		parent = NULL;
+		mem_cgroup_soft_limit_tree = RB_ROOT;

This can be done at compile time?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw

Re: [PATCH 3/4] Memory controller soft limit organize cgroups (v5)

Quoted 44 lines · Andrew Morton
Quoted 32 lines · On Thu, 12 Mar 2009 23:26:25 +0530 Balbir Singh <[email protected]>…

Feature: Organize cgroups over soft limit in a RB-Tree

From: Balbir Singh <[email protected]>

Changelog v5...v4
1. res_counter_uncharge has an additional parameter to indicate if the counter was over its soft limit, before uncharge.

Changelog v4...v3
1. Optimizations to ensure we don't uncessarily get res_counter values
2. Fixed a bug in usage of time_after()

Changelog v3...v2
1. Add only the ancestor to the RB-Tree
2. Use css_tryget/css_put instead of mem_cgroup_get/mem_cgroup_put

Changelog v2...v1
1. Add support for hierarchies
2. The res_counter that is highest in the hierarchy is returned on soft limit being exceeded. Since we do hierarchical reclaim and add all groups exceeding their soft limits, this approach seems to work well in practice.

This patch introduces a RB-Tree for storing memory cgroups that are over their soft limit. The overall goal is to

1. Add a memory cgroup to the RB-Tree when the soft limit is exceeded. We are careful about updates, updates take place only after a particular time interval has passed
2. We remove the node from the RB-Tree when the usage goes below the soft limit

Quoted 8 lines

The next set of patches will exploit the RB-Tree to get the group that is over its soft limit by the largest amount and reclaim from it, when we face memory contention.

...

+#define MEM_CGROUP_TREE_UPDATE_INTERVAL (HZ/4)

Quoted 8 lines

Wall-clock time is a quite poor way of tracking system activity. There's little correlation between the two things.

Quoted 1 line

From a general design point of view it would be better to pace this

polling activity in a manner which correlates with the amount of system activity. For example, "once per 100,000 pages scanned" is much more adaptive than "once per 250 milliseconds".

Good suggestion, I want to keep the tree up-to-date before we hit scanning for reclaim. I can experiment with the idea and try.

Quoted 10 lines

mm/memcontrol.c mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) · line 2564

Quoted 7 lines

...

Quoted 1 line
(quoted diff) +0 -0
@@ -2459,6 +2561,7 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
mm/memcontrol.c +1 -0
 	if (cont->parent == NULL) {
 		enable_swap_cgroup();
 		parent = NULL;
+		mem_cgroup_soft_limit_tree = RB_ROOT;

This can be done at compile time?

As in declaring using RB_ROOT, sure can be done. I'll send a series of fixes with review comments incorporated.

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#8 lore raw

Re: [PATCH 3/4] Memory controller soft limit organize cgroups (v5)

In reply to Balbir Singh

mm/memcontrol.c struct mem_cgroup_lru_info { · line 138

Quoted 7 lines

/*
+ * Cgroups above their limits are maintained in a RB-Tree, independent of
+ * their hierarchy representation
+ */

mm/memcontrol.c +3 -0
+
+static struct rb_root mem_cgroup_soft_limit_tree;
+static DEFINE_SPINLOCK(memcg_soft_limit_tree_lock);

I have objection to this.
Please don't use global spin lock.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#9 lore raw

Re: [PATCH 3/4] Memory controller soft limit organize cgroups (v5)

Quoted 10 lines · KOSAKI Motohiro

mm/memcontrol.c struct mem_cgroup_lru_info { · line 138

Quoted 7 lines

/*
+ * Cgroups above their limits are maintained in a RB-Tree, independent of
+ * their hierarchy representation
+ */

mm/memcontrol.c +3 -0
+
+static struct rb_root mem_cgroup_soft_limit_tree;
+static DEFINE_SPINLOCK(memcg_soft_limit_tree_lock);

I have objection to this.
Please don't use global spin lock.

We need a global data structure, per node, per zone is no good, since the limits (soft limit in this case) is for the entire cgroup.

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#10 lore raw

Re: [PATCH 3/4] Memory controller soft limit organize cgroups (v5)

Quoted 11 lines
Quoted 10 lines

mm/memcontrol.c struct mem_cgroup_lru_info { · line 138

Quoted 7 lines

/*
+ * Cgroups above their limits are maintained in a RB-Tree, independent of
+ * their hierarchy representation
+ */

mm/memcontrol.c +3 -0
+
+static struct rb_root mem_cgroup_soft_limit_tree;
+static DEFINE_SPINLOCK(memcg_soft_limit_tree_lock);

I have objection to this.
Please don't use global spin lock.

Quoted 2 lines

We need a global data structure, per node, per zone is no good, since the limits (soft limit in this case) is for the entire cgroup.

this smell the data structure is wrong.

rb-tree soring is one of efficient reclaiming technique. but global lock bust due to this patch's good side.

if its updating is really rare, rcu is better?
or couldn't you select another data structure?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#11 lore raw

Re: [PATCH 3/4] Memory controller soft limit organize cgroups (v5)

Quoted 11 lines · KOSAKI Motohiro
Quoted 11 lines
Quoted 10 lines

mm/memcontrol.c struct mem_cgroup_lru_info { · line 138

Quoted 7 lines

/*
+ * Cgroups above their limits are maintained in a RB-Tree, independent of
+ * their hierarchy representation
+ */

mm/memcontrol.c +3 -0
+
+static struct rb_root mem_cgroup_soft_limit_tree;
+static DEFINE_SPINLOCK(memcg_soft_limit_tree_lock);

I have objection to this.
Please don't use global spin lock.

Quoted 8 lines
Quoted 2 lines

We need a global data structure, per node, per zone is no good, since the limits (soft limit in this case) is for the entire cgroup.

this smell the data structure is wrong.

rb-tree soring is one of efficient reclaiming technique. but global lock bust due to this patch's good side.

memory cgroup is a global data structure. Can we have the same mem cgorup in several RB-Trees?

Quoted 2 lines

if its updating is really rare, rcu is better?
or couldn't you select another data structure?

RCU for RB-Trees? We'll need to RCU'fy all the links and the core RB-Tree. RB-Trees are being used in the scheduler and for io-scheduling, hrtimers, etc. What is your concern with the data structure?

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#12 lore raw

Re: [PATCH 3/4] Memory controller soft limit organize cgroups (v5)

In reply to Balbir Singh
Quoted 110 lines · Balbir Singh

Feature: Organize cgroups over soft limit in a RB-Tree

From: Balbir Singh <[email protected]>

Changelog v5...v4
1. res_counter_uncharge has an additional parameter to indicate if the counter was over its soft limit, before uncharge.

Changelog v4...v3
1. Optimizations to ensure we don't uncessarily get res_counter values
2. Fixed a bug in usage of time_after()

Changelog v3...v2
1. Add only the ancestor to the RB-Tree
2. Use css_tryget/css_put instead of mem_cgroup_get/mem_cgroup_put

Changelog v2...v1
1. Add support for hierarchies
2. The res_counter that is highest in the hierarchy is returned on soft limit being exceeded. Since we do hierarchical reclaim and add all groups exceeding their soft limits, this approach seems to work well in practice.

This patch introduces a RB-Tree for storing memory cgroups that are over their
soft limit. The overall goal is to

1. Add a memory cgroup to the RB-Tree when the soft limit is exceeded. We are careful about updates, updates take place only after a
particular
time interval has passed
2. We remove the node from the RB-Tree when the usage goes below the soft limit

The next set of patches will exploit the RB-Tree to get the group that is over its soft limit by the largest amount and reclaim from it, when we face memory contention.

---

 include/linux/res_counter.h |    6 +-
 kernel/res_counter.c        |   18 +++++
 mm/memcontrol.c             |  141
++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 143 insertions(+), 22 deletions(-)
include/linux/res_counter.h +2 -1
index 5c821fd..5bbf8b1 100644
@@ -112,7 +112,8 @@ void res_counter_init(struct res_counter *counter,
 struct res_counter *parent);
 int __must_check res_counter_charge_locked(struct res_counter *counter,
 		unsigned long val);
 int __must_check res_counter_charge(struct res_counter *counter,
-		unsigned long val, struct res_counter **limit_fail_at);
+		unsigned long val, struct res_counter **limit_fail_at,
+		struct res_counter **soft_limit_at);
 
 /*

* uncharge - tell that some portion of the resource is released

include/linux/res_counter.h +2 -1
@@ -125,7 +126,8 @@ int __must_check res_counter_charge(struct res_counter
 *counter,
  */
 
 void res_counter_uncharge_locked(struct res_counter *counter, unsigned
 long val);
-void res_counter_uncharge(struct res_counter *counter, unsigned long
 val);
+void res_counter_uncharge(struct res_counter *counter, unsigned long val,
+				bool *was_soft_limit_excess);

static inline bool res_counter_limit_check_locked(struct res_counter
*cnt)
{

kernel/res_counter.c +11 -1
index 4e6dafe..51ec438 100644
@@ -37,17 +37,27 @@ int res_counter_charge_locked(struct res_counter
 *counter, unsigned long val)
 }
 
 int res_counter_charge(struct res_counter *counter, unsigned long val,
-			struct res_counter **limit_fail_at)
+			struct res_counter **limit_fail_at,
+			struct res_counter **soft_limit_fail_at)
 {
 	int ret;
 	unsigned long flags;
 	struct res_counter *c, *u;
 
 	*limit_fail_at = NULL;
+	if (soft_limit_fail_at)
+		*soft_limit_fail_at = NULL;
 	local_irq_save(flags);
 	for (c = counter; c != NULL; c = c->parent) {
 		spin_lock(&c->lock);
 		ret = res_counter_charge_locked(c, val);
+		/*
+		 * With soft limits, we return the highest ancestor
+		 * that exceeds its soft limit
+		 */
+		if (soft_limit_fail_at &&
+			!res_counter_soft_limit_check_locked(c))
+			*soft_limit_fail_at = c;
 		spin_unlock(&c->lock);
 		if (ret < 0) {
Quoted 1 line

*limit_fail_at = c;

Do we need these all check at every call ?
If you just check tree update once per HZ/?? , please check this onece per HZ/??. And please help people who doesn't use softlimit i.e. who doesn't mount cgroup but have to use configured kernel.

kernel/res_counter.c

Quoted 3 lines
kernel/res_counter.c +3 -0
+static struct rb_root mem_cgroup_soft_limit_tree;
+static DEFINE_SPINLOCK(memcg_soft_limit_tree_lock);
+

Can't we breakd down this lock to per node or per cpu or...?

Quoted 14 lines

+/*
* The memory controller data structure. The memory controller controls
both
* page cache and RSS per cgroup. We would eventually like to provide
* statistics based on the statistics developed by Rik Van Riel for
clock-pro,

kernel/res_counter.c +4 -0
@@ -176,12 +185,20 @@ struct mem_cgroup {
 
 	unsigned int	swappiness;
 
+	struct rb_node mem_cgroup_node;		/* RB tree node */
+	unsigned long long usage_in_excess;	/* Set to the value by which */
+						/* the soft limit is exceeded*/
+	unsigned long last_tree_update;		/* Last time the tree was */

kernel/res_counter.c struct mem_cgroup { · line 201

Quoted 10 lines
kernel/res_counter.c +4 -0
+						/* updated in jiffies     */
+
 	/*
 	 * statistics. This must be placed at the end of memcg.
 	 */
 	struct mem_cgroup_stat stat;
 };
 
+#define	MEM_CGROUP_TREE_UPDATE_INTERVAL		(HZ/4)
+

Why HZ/4 again.

Quoted 73 lines
kernel/res_counter.c +59 -0
 enum charge_type {
 	MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
 	MEM_CGROUP_CHARGE_TYPE_MAPPED,
@@ -214,6 +231,41 @@ static void mem_cgroup_get(struct mem_cgroup *mem);
 static void mem_cgroup_put(struct mem_cgroup *mem);
 static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem);
 
+static void mem_cgroup_insert_exceeded(struct mem_cgroup *mem)
+{
+	struct rb_node **p = &mem_cgroup_soft_limit_tree.rb_node;
+	struct rb_node *parent = NULL;
+	struct mem_cgroup *mem_node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&memcg_soft_limit_tree_lock, flags);
+	while (*p) {
+		parent = *p;
+		mem_node = rb_entry(parent, struct mem_cgroup, mem_cgroup_node);
+		if (mem->usage_in_excess < mem_node->usage_in_excess)
+			p = &(*p)->rb_left;
+		/*
+		 * We can't avoid mem cgroups that are over their soft
+		 * limit by the same amount
+		 */
+		else if (mem->usage_in_excess >= mem_node->usage_in_excess)
+			p = &(*p)->rb_right;
+	}
+	rb_link_node(&mem->mem_cgroup_node, parent, p);
+	rb_insert_color(&mem->mem_cgroup_node,
+			&mem_cgroup_soft_limit_tree);
+	mem->last_tree_update = jiffies;
+	spin_unlock_irqrestore(&memcg_soft_limit_tree_lock, flags);
+}
+
+static void mem_cgroup_remove_exceeded(struct mem_cgroup *mem)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&memcg_soft_limit_tree_lock, flags);
+	rb_erase(&mem->mem_cgroup_node, &mem_cgroup_soft_limit_tree);
+	spin_unlock_irqrestore(&memcg_soft_limit_tree_lock, flags);
+}
+
 static void mem_cgroup_charge_statistics(struct mem_cgroup *mem,
 					 struct page_cgroup *pc,
 					 bool charge)
@@ -897,6 +949,40 @@ static void record_last_oom(struct mem_cgroup *mem)
 	mem_cgroup_walk_tree(mem, NULL, record_last_oom_cb);
 }
 
+static void mem_cgroup_check_and_update_tree(struct mem_cgroup *mem,
+						bool time_check)
+{
+	unsigned long long prev_usage_in_excess, new_usage_in_excess;
+	bool updated_tree = false;
+	unsigned long next_update = 0;
+	unsigned long flags;
+
+	prev_usage_in_excess = mem->usage_in_excess;
+
+	if (time_check)
+		next_update = mem->last_tree_update +
+				MEM_CGROUP_TREE_UPDATE_INTERVAL;
+
+	if (!time_check || time_after(jiffies, next_update)) {
+		new_usage_in_excess = res_counter_soft_limit_excess(&mem->res);
+		if (prev_usage_in_excess) {
+			mem_cgroup_remove_exceeded(mem);
+			updated_tree = true;
+		}
+		if (!new_usage_in_excess)
+			goto done;
+		mem_cgroup_insert_exceeded(mem);
+		updated_tree = true;

kernel/res_counter.c static void record_last_oom(struct mem_cgroup *mem) · line 985

Quoted 10 lines
kernel/res_counter.c +10 -0
+	}
+
+done:
+	if (updated_tree) {
+		spin_lock_irqsave(&memcg_soft_limit_tree_lock, flags);
+		mem->last_tree_update = jiffies;
+		mem->usage_in_excess = new_usage_in_excess;
+		spin_unlock_irqrestore(&memcg_soft_limit_tree_lock, flags);
+	}
+}

Why update key parameter after inserting tree ? Is this bug ? Maybe RB-tree will be not sorted.

Bye,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#13 lore raw

Re: [PATCH 3/4] Memory controller soft limit organize cgroups (v5)

Quoted 120 lines · KAMEZAWA Hiroyuki
Quoted 110 lines · Balbir Singh

Feature: Organize cgroups over soft limit in a RB-Tree

From: Balbir Singh <[email protected]>

Changelog v5...v4
1. res_counter_uncharge has an additional parameter to indicate if the counter was over its soft limit, before uncharge.

Changelog v4...v3
1. Optimizations to ensure we don't uncessarily get res_counter values
2. Fixed a bug in usage of time_after()

Changelog v3...v2
1. Add only the ancestor to the RB-Tree
2. Use css_tryget/css_put instead of mem_cgroup_get/mem_cgroup_put

Changelog v2...v1
1. Add support for hierarchies
2. The res_counter that is highest in the hierarchy is returned on soft limit being exceeded. Since we do hierarchical reclaim and add all groups exceeding their soft limits, this approach seems to work well in practice.

This patch introduces a RB-Tree for storing memory cgroups that are over their
soft limit. The overall goal is to

1. Add a memory cgroup to the RB-Tree when the soft limit is exceeded. We are careful about updates, updates take place only after a
particular
time interval has passed
2. We remove the node from the RB-Tree when the usage goes below the soft limit

The next set of patches will exploit the RB-Tree to get the group that is over its soft limit by the largest amount and reclaim from it, when we face memory contention.

---

 include/linux/res_counter.h |    6 +-
 kernel/res_counter.c        |   18 +++++
 mm/memcontrol.c             |  141
++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 143 insertions(+), 22 deletions(-)
include/linux/res_counter.h +2 -1
index 5c821fd..5bbf8b1 100644
@@ -112,7 +112,8 @@ void res_counter_init(struct res_counter *counter,
 struct res_counter *parent);
 int __must_check res_counter_charge_locked(struct res_counter *counter,
 		unsigned long val);
 int __must_check res_counter_charge(struct res_counter *counter,
-		unsigned long val, struct res_counter **limit_fail_at);
+		unsigned long val, struct res_counter **limit_fail_at,
+		struct res_counter **soft_limit_at);
 
 /*

* uncharge - tell that some portion of the resource is released

include/linux/res_counter.h +2 -1
@@ -125,7 +126,8 @@ int __must_check res_counter_charge(struct res_counter
 *counter,
  */
 
 void res_counter_uncharge_locked(struct res_counter *counter, unsigned
 long val);
-void res_counter_uncharge(struct res_counter *counter, unsigned long
 val);
+void res_counter_uncharge(struct res_counter *counter, unsigned long val,
+				bool *was_soft_limit_excess);

static inline bool res_counter_limit_check_locked(struct res_counter
*cnt)
{

kernel/res_counter.c +11 -1
index 4e6dafe..51ec438 100644
@@ -37,17 +37,27 @@ int res_counter_charge_locked(struct res_counter
 *counter, unsigned long val)
 }
 
 int res_counter_charge(struct res_counter *counter, unsigned long val,
-			struct res_counter **limit_fail_at)
+			struct res_counter **limit_fail_at,
+			struct res_counter **soft_limit_fail_at)
 {
 	int ret;
 	unsigned long flags;
 	struct res_counter *c, *u;
 
 	*limit_fail_at = NULL;
+	if (soft_limit_fail_at)
+		*soft_limit_fail_at = NULL;
 	local_irq_save(flags);
 	for (c = counter; c != NULL; c = c->parent) {
 		spin_lock(&c->lock);
 		ret = res_counter_charge_locked(c, val);
+		/*
+		 * With soft limits, we return the highest ancestor
+		 * that exceeds its soft limit
+		 */
+		if (soft_limit_fail_at &&
+			!res_counter_soft_limit_check_locked(c))
+			*soft_limit_fail_at = c;
 		spin_unlock(&c->lock);
 		if (ret < 0) {
Quoted 1 line

*limit_fail_at = c;

Do we need these all check at every call ?
If you just check tree update once per HZ/?? , please check this onece per HZ/??. And please help people who doesn't use softlimit i.e. who doesn't mount cgroup but have to use configured kernel.

Quoted 5 lines

kernel/res_counter.c

Quoted 3 lines
kernel/res_counter.c +3 -0
+static struct rb_root mem_cgroup_soft_limit_tree;
+static DEFINE_SPINLOCK(memcg_soft_limit_tree_lock);
+

Can't we breakd down this lock to per node or per cpu or...?

I responded to the same comment by Kosaki.

Quoted 22 lines
Quoted 22 lines

+/*
* The memory controller data structure. The memory controller controls
both
* page cache and RSS per cgroup. We would eventually like to provide
* statistics based on the statistics developed by Rik Van Riel for
clock-pro,

kernel/res_counter.c +6 -0
@@ -176,12 +185,20 @@ struct mem_cgroup {
 
 	unsigned int	swappiness;
 
+	struct rb_node mem_cgroup_node;		/* RB tree node */
+	unsigned long long usage_in_excess;	/* Set to the value by which */
+						/* the soft limit is exceeded*/
+	unsigned long last_tree_update;		/* Last time the tree was */
+						/* updated in jiffies     */
+
 	/*
 	 * statistics. This must be placed at the end of memcg.
 	 */
 	struct mem_cgroup_stat stat;
 };
 
Quoted 5 lines

kernel/res_counter.c struct mem_cgroup { · line 201

Quoted 2 lines
kernel/res_counter.c +2 -0
+#define	MEM_CGROUP_TREE_UPDATE_INTERVAL		(HZ/4)
+

Why HZ/4 again.

Good question. HZ/4 is not too aggressive or not to lax. The value is empirical.

Quoted 77 lines
Quoted 77 lines
kernel/res_counter.c +63 -0
 enum charge_type {
 	MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
 	MEM_CGROUP_CHARGE_TYPE_MAPPED,
@@ -214,6 +231,41 @@ static void mem_cgroup_get(struct mem_cgroup *mem);
 static void mem_cgroup_put(struct mem_cgroup *mem);
 static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem);
 
+static void mem_cgroup_insert_exceeded(struct mem_cgroup *mem)
+{
+	struct rb_node **p = &mem_cgroup_soft_limit_tree.rb_node;
+	struct rb_node *parent = NULL;
+	struct mem_cgroup *mem_node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&memcg_soft_limit_tree_lock, flags);
+	while (*p) {
+		parent = *p;
+		mem_node = rb_entry(parent, struct mem_cgroup, mem_cgroup_node);
+		if (mem->usage_in_excess < mem_node->usage_in_excess)
+			p = &(*p)->rb_left;
+		/*
+		 * We can't avoid mem cgroups that are over their soft
+		 * limit by the same amount
+		 */
+		else if (mem->usage_in_excess >= mem_node->usage_in_excess)
+			p = &(*p)->rb_right;
+	}
+	rb_link_node(&mem->mem_cgroup_node, parent, p);
+	rb_insert_color(&mem->mem_cgroup_node,
+			&mem_cgroup_soft_limit_tree);
+	mem->last_tree_update = jiffies;
+	spin_unlock_irqrestore(&memcg_soft_limit_tree_lock, flags);
+}
+
+static void mem_cgroup_remove_exceeded(struct mem_cgroup *mem)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&memcg_soft_limit_tree_lock, flags);
+	rb_erase(&mem->mem_cgroup_node, &mem_cgroup_soft_limit_tree);
+	spin_unlock_irqrestore(&memcg_soft_limit_tree_lock, flags);
+}
+
 static void mem_cgroup_charge_statistics(struct mem_cgroup *mem,
 					 struct page_cgroup *pc,
 					 bool charge)
@@ -897,6 +949,40 @@ static void record_last_oom(struct mem_cgroup *mem)
 	mem_cgroup_walk_tree(mem, NULL, record_last_oom_cb);
 }
 
+static void mem_cgroup_check_and_update_tree(struct mem_cgroup *mem,
+						bool time_check)
+{
+	unsigned long long prev_usage_in_excess, new_usage_in_excess;
+	bool updated_tree = false;
+	unsigned long next_update = 0;
+	unsigned long flags;
+
+	prev_usage_in_excess = mem->usage_in_excess;
+
+	if (time_check)
+		next_update = mem->last_tree_update +
+				MEM_CGROUP_TREE_UPDATE_INTERVAL;
+
+	if (!time_check || time_after(jiffies, next_update)) {
+		new_usage_in_excess = res_counter_soft_limit_excess(&mem->res);
+		if (prev_usage_in_excess) {
+			mem_cgroup_remove_exceeded(mem);
+			updated_tree = true;
+		}
+		if (!new_usage_in_excess)
+			goto done;
+		mem_cgroup_insert_exceeded(mem);
+		updated_tree = true;
+	}
+
+done:
+	if (updated_tree) {
Quoted 9 lines

kernel/res_counter.c static void record_last_oom(struct mem_cgroup *mem) · line 985

Quoted 6 lines
kernel/res_counter.c +6 -0
+		spin_lock_irqsave(&memcg_soft_limit_tree_lock, flags);
+		mem->last_tree_update = jiffies;
+		mem->usage_in_excess = new_usage_in_excess;
+		spin_unlock_irqrestore(&memcg_soft_limit_tree_lock, flags);
+	}
+}

Why update key parameter after inserting tree ? Is this bug ? Maybe RB-tree will be not sorted.

Hmm.. I'll revisit. Thanks!

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#14 lore raw

PATCH 4/4 Memory controller soft limit reclaim on contention (v5)

In reply to Balbir Singh

Feature: Implement reclaim from groups over their soft limit

From: Balbir Singh <[email protected]>

Changelog v5...v4

1. Throttling is removed, earlier we throttled tasks over their soft limit
2. Reclaim has been moved back to __alloc_pages_internal, several experiments and tests showed that it was the best place to reclaim memory. kswapd has a different goal, that does not work with a single soft limit for the memory cgroup.
3. Soft limit reclaim is more targetted and the pages reclaim depend on the amount by which the soft limit is exceeded.

Changelog v4...v3
1. soft_reclaim is now called from balance_pgdat
2. soft_reclaim is aware of nodes and zones
3. A mem_cgroup will be throttled if it is undergoing soft limit reclaim and at the same time trying to allocate pages and exceed its soft limit.
4. A new mem_cgroup_shrink_zone() routine has been added to shrink zones particular to a mem cgroup.

Changelog v3...v2
1. Convert several arguments to hierarchical reclaim to flags, thereby consolidating them
2. The reclaim for soft limits is now triggered from kswapd
3. try_to_free_mem_cgroup_pages() now accepts an optional zonelist argument

Changelog v2...v1
1. Added support for hierarchical soft limits

This patch allows reclaim from memory cgroups on contention (via the kswapd() path) only if the order is 0.

memory cgroup soft limit reclaim finds the group that exceeds its soft limit by the largest amount and reclaims pages from it and then reinserts the cgroup into its correct place in the rbtree.

---

 include/linux/memcontrol.h |    7 +-
 include/linux/swap.h       |    1 
 mm/memcontrol.c            |  180 +++++++++++++++++++++++++++++++++++++++-----
 mm/page_alloc.c            |    9 ++
 mm/vmscan.c                |    5 +
 5 files changed, 179 insertions(+), 23 deletions(-)
include/linux/memcontrol.h +6 -1
index 18146c9..c0aeab9 100644
@@ -116,7 +116,8 @@ static inline bool mem_cgroup_disabled(void)
 }
 
 extern bool mem_cgroup_oom_called(struct task_struct *task);
-
+unsigned long mem_cgroup_soft_limit_reclaim(struct zonelist *zl,
+						gfp_t gfp_mask);
 #else /* CONFIG_CGROUP_MEM_RES_CTLR */
 struct mem_cgroup;
 
@@ -264,6 +265,10 @@ mem_cgroup_print_oom_info(struct mem_cgroup *memcg, struct task_struct *p)
 {
 }
 
+unsigned long mem_cgroup_soft_limit_reclaim(struct zonelist *zl, gfp_t gfp_mask)
+{
+	return 0;
+}
 #endif /* CONFIG_CGROUP_MEM_CONT */
 
 #endif /* _LINUX_MEMCONTROL_H */
include/linux/swap.h +1 -0
index 989eb53..c128337 100644
@@ -215,6 +215,7 @@ static inline void lru_cache_add_active_file(struct page *page)
 extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 					gfp_t gfp_mask);
 extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem,
+						  struct zonelist *zl,
 						  gfp_t gfp_mask, bool noswap,
 						  unsigned int swappiness);
 extern int __isolate_lru_page(struct page *page, int mode, int file);
mm/memcontrol.c +161 -19

298 lines not on this page · raw message

mm/page_alloc.c +8 -1
index 46bd24c..b49c90f 100644
@@ -1583,7 +1583,14 @@ nofail_alloc:
 	reclaim_state.reclaimed_slab = 0;
 	p->reclaim_state = &reclaim_state;
 
-	did_some_progress = try_to_free_pages(zonelist, order, gfp_mask);
+	/*
+	 * Try to free up some pages from the memory controllers soft
+	 * limit queue.
+	 */
+	did_some_progress = mem_cgroup_soft_limit_reclaim(zonelist, gfp_mask);
+	if (!order || !did_some_progress)
+		did_some_progress += try_to_free_pages(zonelist, order,
+							gfp_mask);
 
 	p->reclaim_state = NULL;
 	lockdep_clear_current_reclaim_state();
mm/vmscan.c +3 -2
index bfd853b..f212b30 100644
@@ -1708,6 +1708,7 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 
 unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
+					   struct zonelist *zonelist,
 					   gfp_t gfp_mask,
 					   bool noswap,
 					   unsigned int swappiness)
@@ -1721,14 +1722,14 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
 		.mem_cgroup = mem_cont,
 		.isolate_pages = mem_cgroup_isolate_pages,
 	};
-	struct zonelist *zonelist;
 
 	if (noswap)
 		sc.may_unmap = 0;
 
 	sc.gfp_mask = (gfp_mask & GFP_RECLAIM_MASK) |
 			(GFP_HIGHUSER_MOVABLE & ~GFP_RECLAIM_MASK);
-	zonelist = NODE_DATA(numa_node_id())->node_zonelists;
+	if (!zonelist)
+		zonelist = NODE_DATA(numa_node_id())->node_zonelists;
 	return do_try_to_free_pages(zonelist, &sc);
 }
 #endif
Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#15 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 29 lines · On Thu, 12 Mar 2009 23:26:31 +0530 Balbir Singh <[email protected]>…

Feature: Implement reclaim from groups over their soft limit

From: Balbir Singh <[email protected]>

Changelog v5...v4

1. Throttling is removed, earlier we throttled tasks over their soft limit
2. Reclaim has been moved back to __alloc_pages_internal, several experiments and tests showed that it was the best place to reclaim memory. kswapd has a different goal, that does not work with a single soft limit for the memory cgroup.
3. Soft limit reclaim is more targetted and the pages reclaim depend on the amount by which the soft limit is exceeded.

Changelog v4...v3
1. soft_reclaim is now called from balance_pgdat
2. soft_reclaim is aware of nodes and zones
3. A mem_cgroup will be throttled if it is undergoing soft limit reclaim and at the same time trying to allocate pages and exceed its soft limit.
4. A new mem_cgroup_shrink_zone() routine has been added to shrink zones particular to a mem cgroup.

Changelog v3...v2
1. Convert several arguments to hierarchical reclaim to flags, thereby consolidating them
2. The reclaim for soft limits is now triggered from kswapd
3. try_to_free_mem_cgroup_pages() now accepts an optional zonelist argument

Quoted 5 lines

Changelog v2...v1
1. Added support for hierarchical soft limits

This patch allows reclaim from memory cgroups on contention (via the kswapd() path) only if the order is 0.

Why for order-0 only?

What are the implications of not handling higher-order pages?

Why kswapd only?

What are the implications of omitting this from direct reclaim?

Quoted 3 lines

memory cgroup soft limit reclaim finds the group that exceeds its soft limit by the largest amount and reclaims pages from it and then reinserts the cgroup into its correct place in the rbtree.

Why trim the single worst-case group rather than (say) trimming all groups by a common proportion? Or other things.

When you say "by the largest amount", is that the "by largest number of pages" or "by the largest percentage"?

What are the implications of <whichever you chose>?

Quoted 5 lines

...

static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,

mm/memcontrol.c +0 -1
-				   gfp_t gfp_mask, bool noswap, bool shrink)

mm/memcontrol.c mem_cgroup_select_victim(struct mem_cgroup *root_mem) · line 975

Quoted 10 lines
mm/memcontrol.c +6 -0
+						struct zonelist *zl,
+						gfp_t gfp_mask,
+						unsigned long flags)
 {
 	struct mem_cgroup *victim;
 	int ret, total = 0;
 	int loop = 0;
+	bool noswap = flags & MEM_CGROUP_RECLAIM_NOSWAP;
+	bool shrink = flags & MEM_CGROUP_RECLAIM_SHRINK;
+	bool check_soft = flags & MEM_CGROUP_RECLAIM_SOFT;

`flags' wasn't a great choice of identifier. It's a bit misleading, and you'll be in a pickle if you later try to add a spin_lock_irqsave(lock, flags) to this function. Maybe choose a more specific name?

mm/memcontrol.c mem_cgroup_select_victim(struct mem_cgroup *root_mem) · line 986

Quoted 12 lines
mm/memcontrol.c +10 -1
+	unsigned long excess = mem_cgroup_get_excess(root_mem);
 
-	while (loop < 2) {
+	while (1) {
+		if (loop >= 2) {
+			/*
+			 * With soft limits, do more targetted reclaim
+			 */
+			if (check_soft && (total >= (excess >> 4)))
+				break;
+			else if (!check_soft)
+				break;

maybe..

			if (!check_soft)
				break;
			if (total >= (excess >> 4))
				break;

dunno.

The ">> 4" magic number would benefit from an explanatory comment. Why not ">> 3"???

Quoted 28 lines
mm/memcontrol.c +24 -0
+		}
 		victim = mem_cgroup_select_victim(root_mem);
+		/*
+		 * In the first loop, don't reclaim from victims below
+		 * their soft limit
+		 */
 
...
 
+unsigned long mem_cgroup_soft_limit_reclaim(struct zonelist *zl, gfp_t gfp_mask)
+{
+	unsigned long nr_reclaimed = 0;
+	struct mem_cgroup *mem;
+	unsigned long flags;
+	unsigned long reclaimed;
+
+	/*
+	 * This loop can run a while, specially if mem_cgroup's continuously
+	 * keep exceeding their soft limit and putting the system under
+	 * pressure
+	 */
+	do {
+		mem = mem_cgroup_largest_soft_limit_node();
+		if (!mem)
+			break;
+
+		reclaimed = mem_cgroup_hierarchical_reclaim(mem, zl,
+						gfp_mask,

mm/memcontrol.c int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, · line 1994

Quoted 10 lines
mm/memcontrol.c +10 -0
+						MEM_CGROUP_RECLAIM_SOFT);
+		nr_reclaimed += reclaimed;
+		spin_lock_irqsave(&memcg_soft_limit_tree_lock, flags);
+		mem->usage_in_excess = res_counter_soft_limit_excess(&mem->res);
+		__mem_cgroup_remove_exceeded(mem);
+		if (mem->usage_in_excess)
+			__mem_cgroup_insert_exceeded(mem);
+		spin_unlock_irqrestore(&memcg_soft_limit_tree_lock, flags);
+		css_put(&mem->css);
+		cond_resched();

spin_lock_irq() would suffice here. Or the cond_resched() is a bug.

There's a decent argument that spin_lock_irq() is dangerous, and its saving is so small that it's better to use the more robust spin_lock_irqsave() all the time. But was that the intent here?

mm/memcontrol.c int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, · line 1997

Quoted 3 lines
mm/memcontrol.c +3 -0
+	} while (!nr_reclaimed);
+	return nr_reclaimed;
+}

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#16 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 32 lines · Andrew Morton
Quoted 29 lines · On Thu, 12 Mar 2009 23:26:31 +0530 Balbir Singh <[email protected]>…

Feature: Implement reclaim from groups over their soft limit

From: Balbir Singh <[email protected]>

Changelog v5...v4

1. Throttling is removed, earlier we throttled tasks over their soft limit
2. Reclaim has been moved back to __alloc_pages_internal, several experiments and tests showed that it was the best place to reclaim memory. kswapd has a different goal, that does not work with a single soft limit for the memory cgroup.
3. Soft limit reclaim is more targetted and the pages reclaim depend on the amount by which the soft limit is exceeded.

Changelog v4...v3
1. soft_reclaim is now called from balance_pgdat
2. soft_reclaim is aware of nodes and zones
3. A mem_cgroup will be throttled if it is undergoing soft limit reclaim and at the same time trying to allocate pages and exceed its soft limit.
4. A new mem_cgroup_shrink_zone() routine has been added to shrink zones particular to a mem cgroup.

Changelog v3...v2
1. Convert several arguments to hierarchical reclaim to flags, thereby consolidating them
2. The reclaim for soft limits is now triggered from kswapd
3. try_to_free_mem_cgroup_pages() now accepts an optional zonelist argument

Quoted 8 lines
Quoted 5 lines

Changelog v2...v1
1. Added support for hierarchical soft limits

This patch allows reclaim from memory cgroups on contention (via the kswapd() path) only if the order is 0.

Why for order-0 only?

Mem cgroup does not allocate order > 1 pages.

Quoted 10 lines

What are the implications of not handling higher-order pages?

Why kswapd only?

What are the implications of omitting this from direct reclaim?

Quoted 3 lines

memory cgroup soft limit reclaim finds the group that exceeds its soft limit by the largest amount and reclaims pages from it and then reinserts the cgroup into its correct place in the rbtree.

Quoted 9 lines

Why trim the single worst-case group rather than (say) trimming all groups by a common proportion? Or other things.

When you say "by the largest amount", is that the "by largest number of pages" or "by the largest percentage"?

What are the implications of <whichever you chose>?

I'll update the changelog in the next post.

Quoted 12 lines
Quoted 12 lines

...

static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,

mm/memcontrol.c +3 -1
-				   gfp_t gfp_mask, bool noswap, bool shrink)
+						struct zonelist *zl,
+						gfp_t gfp_mask,
+						unsigned long flags)
 {
 	struct mem_cgroup *victim;
 	int ret, total = 0;
 	int loop = 0;
Quoted 8 lines

mm/memcontrol.c mem_cgroup_select_victim(struct mem_cgroup *root_mem) · line 975

Quoted 3 lines
mm/memcontrol.c +3 -0
+	bool noswap = flags & MEM_CGROUP_RECLAIM_NOSWAP;
+	bool shrink = flags & MEM_CGROUP_RECLAIM_SHRINK;
+	bool check_soft = flags & MEM_CGROUP_RECLAIM_SOFT;

`flags' wasn't a great choice of identifier. It's a bit misleading, and you'll be in a pickle if you later try to add a spin_lock_irqsave(lock, flags) to this function. Maybe choose a more specific name?

Yes.. good point, I should call it reclaim_options

Quoted 21 lines

mm/memcontrol.c mem_cgroup_select_victim(struct mem_cgroup *root_mem) · line 986

Quoted 13 lines
mm/memcontrol.c +10 -1
+	unsigned long excess = mem_cgroup_get_excess(root_mem);
 
-	while (loop < 2) {
+	while (1) {
+		if (loop >= 2) {
+			/*
+			 * With soft limits, do more targetted reclaim
+			 */
+			if (check_soft && (total >= (excess >> 4)))
+				break;
+			else if (!check_soft)
+				break;

maybe..

			if (!check_soft)
				break;
			if (total >= (excess >> 4))
				break;
Quoted 5 lines

dunno.

The ">> 4" magic number would benefit from an explanatory comment. Why not ">> 3"???

Done.. will fix it.

Quoted 42 lines
Quoted 29 lines
mm/memcontrol.c +24 -0
+		}
 		victim = mem_cgroup_select_victim(root_mem);
+		/*
+		 * In the first loop, don't reclaim from victims below
+		 * their soft limit
+		 */
 
...
 
+unsigned long mem_cgroup_soft_limit_reclaim(struct zonelist *zl, gfp_t gfp_mask)
+{
+	unsigned long nr_reclaimed = 0;
+	struct mem_cgroup *mem;
+	unsigned long flags;
+	unsigned long reclaimed;
+
+	/*
+	 * This loop can run a while, specially if mem_cgroup's continuously
+	 * keep exceeding their soft limit and putting the system under
+	 * pressure
+	 */
+	do {
+		mem = mem_cgroup_largest_soft_limit_node();
+		if (!mem)
+			break;
+
+		reclaimed = mem_cgroup_hierarchical_reclaim(mem, zl,
+						gfp_mask,

mm/memcontrol.c int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, · line 1994

Quoted 10 lines
mm/memcontrol.c +10 -0
+						MEM_CGROUP_RECLAIM_SOFT);
+		nr_reclaimed += reclaimed;
+		spin_lock_irqsave(&memcg_soft_limit_tree_lock, flags);
+		mem->usage_in_excess = res_counter_soft_limit_excess(&mem->res);
+		__mem_cgroup_remove_exceeded(mem);
+		if (mem->usage_in_excess)
+			__mem_cgroup_insert_exceeded(mem);
+		spin_unlock_irqrestore(&memcg_soft_limit_tree_lock, flags);
+		css_put(&mem->css);
+		cond_resched();

spin_lock_irq() would suffice here. Or the cond_resched() is a bug.

Quoted 4 lines

There's a decent argument that spin_lock_irq() is dangerous, and its saving is so small that it's better to use the more robust spin_lock_irqsave() all the time. But was that the intent here?

spin_lock_irqsave allows more control over where the routine can be called fromi (that does not matter right now, since we have just one call path(. I could just use spin_lock_irq and that would be fine for now. Like you said the benefits are really small.

cond_resched() can go away, I'll remove it.

Quoted 6 lines
Quoted 4 lines
mm/memcontrol.c +3 -0
+	} while (!nr_reclaimed);
+	return nr_reclaimed;
+}
Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#17 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

In reply to Balbir Singh

Hi

Quoted 7 lines
mm/page_alloc.c +0 -0
index 46bd24c..b49c90f 100644
@@ -1583,7 +1583,14 @@ nofail_alloc:
 	reclaim_state.reclaimed_slab = 0;
 	p->reclaim_state = &reclaim_state;

mm/page_alloc.c nofail_alloc: · line 1593

Quoted 10 lines
mm/page_alloc.c +8 -1
 
-	did_some_progress = try_to_free_pages(zonelist, order, gfp_mask);
+	/*
+	 * Try to free up some pages from the memory controllers soft
+	 * limit queue.
+	 */
+	did_some_progress = mem_cgroup_soft_limit_reclaim(zonelist, gfp_mask);
+	if (!order || !did_some_progress)
+		did_some_progress += try_to_free_pages(zonelist, order,
+							gfp_mask);

I have two objection to this.

- "if (!order || !did_some_progress)" mean no call try_to_free_pages() in order>0 and did_some_progress>0 case.
but mem_cgroup_soft_limit_reclaim() don't have lumpy reclaim. then, it break high order reclaim.
- in global reclaim view, foreground reclaim and background reclaim's reclaim rate is about 1:9 typically.
then, kswapd reclaim the pages by global lru order before proceccing this logic.
IOW, this soft limit is not SOFT.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#18 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 22 lines · KOSAKI Motohiro

Hi

Quoted 7 lines
mm/page_alloc.c +0 -0
index 46bd24c..b49c90f 100644
@@ -1583,7 +1583,14 @@ nofail_alloc:
 	reclaim_state.reclaimed_slab = 0;
 	p->reclaim_state = &reclaim_state;

mm/page_alloc.c nofail_alloc: · line 1593

Quoted 10 lines
mm/page_alloc.c +8 -1
 
-	did_some_progress = try_to_free_pages(zonelist, order, gfp_mask);
+	/*
+	 * Try to free up some pages from the memory controllers soft
+	 * limit queue.
+	 */
+	did_some_progress = mem_cgroup_soft_limit_reclaim(zonelist, gfp_mask);
+	if (!order || !did_some_progress)
+		did_some_progress += try_to_free_pages(zonelist, order,
+							gfp_mask);

I have two objection to this.

Quoted 4 lines

- "if (!order || !did_some_progress)" mean no call try_to_free_pages() in order>0 and did_some_progress>0 case.
but mem_cgroup_soft_limit_reclaim() don't have lumpy reclaim. then, it break high order reclaim.

I am sending a fix for this right away. Thanks, the check should be if (order || !did_some_progress)

Quoted 5 lines

- in global reclaim view, foreground reclaim and background reclaim's reclaim rate is about 1:9 typically.
then, kswapd reclaim the pages by global lru order before proceccing this logic.
IOW, this soft limit is not SOFT.

It depends on what you mean by soft. I call them soft since they are imposed only when there is contention. If you mean kswapd runs more often than direct reclaim, that is true, but it does not impact this code extensively since the high water mark is a very small compared to the pages present on the system.

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#19 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 12 lines
Quoted 12 lines

mm/page_alloc.c nofail_alloc: · line 1593

Quoted 9 lines
mm/page_alloc.c +8 -1
-	did_some_progress = try_to_free_pages(zonelist, order, gfp_mask);
+	/*
+	 * Try to free up some pages from the memory controllers soft
+	 * limit queue.
+	 */
+	did_some_progress = mem_cgroup_soft_limit_reclaim(zonelist, gfp_mask);
+	if (!order || !did_some_progress)
+		did_some_progress += try_to_free_pages(zonelist, order,
+							gfp_mask);

I have two objection to this.

Quoted 7 lines
Quoted 4 lines

- "if (!order || !did_some_progress)" mean no call try_to_free_pages() in order>0 and did_some_progress>0 case.
but mem_cgroup_soft_limit_reclaim() don't have lumpy reclaim. then, it break high order reclaim.

I am sending a fix for this right away. Thanks, the check should be if (order || !did_some_progress)

No.

it isn't enough.
after is does, order-1 allocation case twrice reclaim (soft limit shrinking and normal try_to_free_pages()).
then, order-1 reclaim makes slower about 2 times.

unfortunately, order-1 allocation is very frequent. it is used for kernel stack.

Quoted 11 lines
Quoted 5 lines

- in global reclaim view, foreground reclaim and background reclaim's reclaim rate is about 1:9 typically.
then, kswapd reclaim the pages by global lru order before proceccing this logic.
IOW, this soft limit is not SOFT.

It depends on what you mean by soft. I call them soft since they are imposed only when there is contention. If you mean kswapd runs more often than direct reclaim, that is true, but it does not impact this code extensively since the high water mark is a very small compared to the pages present on the system.

No.

My point is, contention case kswapd wakeup. and kswapd reclaim by global lru order before soft limit shrinking.
Therefore, In typical usage, mem_cgroup_soft_limit_reclaim() almost don't call properly.

soft limit shrinking should run before processing global reclaim.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#20 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 12 lines
Quoted 9 lines
Quoted 6 lines

I have two objection to this.

- "if (!order || !did_some_progress)" mean no call try_to_free_pages() in order>0 and did_some_progress>0 case.
but mem_cgroup_soft_limit_reclaim() don't have lumpy reclaim. then, it break high order reclaim.

I am sending a fix for this right away. Thanks, the check should be if (order || !did_some_progress)

No.

Quoted 7 lines

it isn't enough.
after is does, order-1 allocation case twrice reclaim (soft limit shrinking and normal try_to_free_pages()).
then, order-1 reclaim makes slower about 2 times.

unfortunately, order-1 allocation is very frequent. it is used for kernel stack.

in normal order-1 reclaim is:

1. try_to_free_pages()
2. get_page_from_freelist()
3. retry if order-1 page don't exist

Coundn't you use the same logic?

Quoted 12 lines
Quoted 11 lines
Quoted 5 lines

- in global reclaim view, foreground reclaim and background reclaim's reclaim rate is about 1:9 typically.
then, kswapd reclaim the pages by global lru order before proceccing this logic.
IOW, this soft limit is not SOFT.

It depends on what you mean by soft. I call them soft since they are imposed only when there is contention. If you mean kswapd runs more often than direct reclaim, that is true, but it does not impact this code extensively since the high water mark is a very small compared to the pages present on the system.

Quoted 8 lines

No.

My point is, contention case kswapd wakeup. and kswapd reclaim by global lru order before soft limit shrinking.
Therefore, In typical usage, mem_cgroup_soft_limit_reclaim() almost don't call properly.

soft limit shrinking should run before processing global reclaim.

Do you have the reason of disliking call from kswapd ?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#21 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 42 lines · KOSAKI Motohiro
Quoted 12 lines
Quoted 9 lines
Quoted 6 lines

I have two objection to this.

- "if (!order || !did_some_progress)" mean no call try_to_free_pages() in order>0 and did_some_progress>0 case.
but mem_cgroup_soft_limit_reclaim() don't have lumpy reclaim. then, it break high order reclaim.

I am sending a fix for this right away. Thanks, the check should be if (order || !did_some_progress)

No.

Quoted 7 lines

it isn't enough.
after is does, order-1 allocation case twrice reclaim (soft limit shrinking and normal try_to_free_pages()).
then, order-1 reclaim makes slower about 2 times.

unfortunately, order-1 allocation is very frequent. it is used for kernel stack.

in normal order-1 reclaim is:

1. try_to_free_pages()
2. get_page_from_freelist()
3. retry if order-1 page don't exist

Coundn't you use the same logic?

Quoted 14 lines
Quoted 11 lines
Quoted 5 lines

- in global reclaim view, foreground reclaim and background reclaim's reclaim rate is about 1:9 typically.
then, kswapd reclaim the pages by global lru order before proceccing this logic.
IOW, this soft limit is not SOFT.

It depends on what you mean by soft. I call them soft since they are imposed only when there is contention. If you mean kswapd runs more often than direct reclaim, that is true, but it does not impact this code extensively since the high water mark is a very small compared to the pages present on the system.

No.

Quoted 9 lines
Quoted 6 lines

My point is, contention case kswapd wakeup. and kswapd reclaim by global lru order before soft limit shrinking.
Therefore, In typical usage, mem_cgroup_soft_limit_reclaim() almost don't call properly.

soft limit shrinking should run before processing global reclaim.

Do you have the reason of disliking call from kswapd ?

Yes, I sent that reason out as comments to Kame's patches. kswapd or balance_pgdat controls the zones, priority and in effect how many pages we scan while doing reclaim. I did lots of experiments and found that if soft limit reclaim occurred from kswapd, soft_limit_reclaim would almost always fail and shrink_zone() would succeed, since it looks at the whole zone and is always able to find some pages at all priority levels. It also does not allow for targetted reclaim based on how much we exceed the soft limit by.

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#22 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 10 lines
Quoted 9 lines
Quoted 6 lines

My point is, contention case kswapd wakeup. and kswapd reclaim by global lru order before soft limit shrinking.
Therefore, In typical usage, mem_cgroup_soft_limit_reclaim() almost don't call properly.

soft limit shrinking should run before processing global reclaim.

Do you have the reason of disliking call from kswapd ?

Quoted 8 lines

Yes, I sent that reason out as comments to Kame's patches. kswapd or balance_pgdat controls the zones, priority and in effect how many pages we scan while doing reclaim. I did lots of experiments and found that if soft limit reclaim occurred from kswapd, soft_limit_reclaim would almost always fail and shrink_zone() would succeed, since it looks at the whole zone and is always able to find some pages at all priority levels. It also does not allow for targetted reclaim based on how much we exceed the soft limit by.

hm
I read past discussion. so, I think we discuss many aspect at once. So, my current thinking is below,

(1) if the group don't have any soft limit shrinking page, mem_cgroup_soft_limit_reclaim() spent time unnecessary. -> right.
actually, past global reclaim had similar problem. then zone_is_all_unreclaimable() was introduced. maybe we can use similar technique to memcg.

(2) mem_cgroup_soft_limit_reclaim() should be called from? -> under discussion.
we should solve (1) at first for proper constructive discussion.

(3) What's "fairness" of soft limit?

    -> perfectly another aspect.

So, I'd like to discuss (1) at first. Although we don't kswapd shrinking, (1) is problem.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#23 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 19 lines · KOSAKI Motohiro
Quoted 10 lines
Quoted 9 lines
Quoted 6 lines

My point is, contention case kswapd wakeup. and kswapd reclaim by global lru order before soft limit shrinking.
Therefore, In typical usage, mem_cgroup_soft_limit_reclaim() almost don't call properly.

soft limit shrinking should run before processing global reclaim.

Do you have the reason of disliking call from kswapd ?

Quoted 8 lines

Yes, I sent that reason out as comments to Kame's patches. kswapd or balance_pgdat controls the zones, priority and in effect how many pages we scan while doing reclaim. I did lots of experiments and found that if soft limit reclaim occurred from kswapd, soft_limit_reclaim would almost always fail and shrink_zone() would succeed, since it looks at the whole zone and is always able to find some pages at all priority levels. It also does not allow for targetted reclaim based on how much we exceed the soft limit by.

Quoted 7 lines

hm
I read past discussion. so, I think we discuss many aspect at once. So, my current thinking is below,

(1) if the group don't have any soft limit shrinking page, mem_cgroup_soft_limit_reclaim() spent time unnecessary. -> right.

If the soft limit RB tree is empty, we don't spend any time at all. Are you referring to something else? Am I missing something? The tree will be empty if no group is over the soft limit.

Quoted 15 lines

actually, past global reclaim had similar problem. then zone_is_all_unreclaimable() was introduced. maybe we can use similar technique to memcg.

(2) mem_cgroup_soft_limit_reclaim() should be called from? -> under discussion.
we should solve (1) at first for proper constructive discussion.

(3) What's "fairness" of soft limit?

    -> perfectly another aspect.

So, I'd like to discuss (1) at first. Although we don't kswapd shrinking, (1) is problem.

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#24 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 11 lines
Quoted 7 lines

hm
I read past discussion. so, I think we discuss many aspect at once. So, my current thinking is below,

(1) if the group don't have any soft limit shrinking page, mem_cgroup_soft_limit_reclaim() spent time unnecessary. -> right.

If the soft limit RB tree is empty, we don't spend any time at all. Are you referring to something else? Am I missing something? The tree will be empty if no group is over the soft limit.

maybe, I am missing anything.
May I ask your following paragraph meaning?

Quoted 8 lines

I experimented a *lot* with zone reclaim and found it to be not so effective. Here is why

1. We have no control over priority or how much to scan, that is controlled by balance_pgdat(). If we find that we are unable to scan anything, we continue scanning with the scan > 0 check, but we scan the same pages and the same number, because shrink_zone does scan >> priority.

I thought this sentense mean soft-limit-shrinking spent a lot of time. if not, could you please tell me what makes so slower?

Quoted 9 lines · you

Yes, I sent that reason out as comments to Kame's patches. kswapd or balance_pgdat controls the zones, priority and in effect how many pages we scan while doing reclaim. I did lots of experiments and found that if soft limit reclaim occurred from kswapd, soft_limit_reclaim would almost always fail and shrink_zone() would succeed, since it looks at the whole zone and is always able to find some pages at all priority levels. It also does not allow for targetted reclaim based on how much we exceed the soft limit by.

but, if "soft_limit_reclaim fail and shrink_zone() succeed" don't cause any performance degression, I don't find why kswapd is wrong.

I guess you and kamezawa-san know it detail. but my understanding don't reach it. Could you please tell me what so slowness.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#25 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 19 lines · KOSAKI Motohiro
Quoted 11 lines
Quoted 7 lines

hm
I read past discussion. so, I think we discuss many aspect at once. So, my current thinking is below,

(1) if the group don't have any soft limit shrinking page, mem_cgroup_soft_limit_reclaim() spent time unnecessary. -> right.

If the soft limit RB tree is empty, we don't spend any time at all. Are you referring to something else? Am I missing something? The tree will be empty if no group is over the soft limit.

maybe, I am missing anything.
May I ask your following paragraph meaning?

Quoted 3 lines

I experimented a *lot* with zone reclaim and found it to be not so effective. Here is why

Quoted 9 lines
Quoted 5 lines

1. We have no control over priority or how much to scan, that is controlled by balance_pgdat(). If we find that we are unable to scan anything, we continue scanning with the scan > 0 check, but we scan the same pages and the same number, because shrink_zone does scan >> priority.

I thought this sentense mean soft-limit-shrinking spent a lot of time. if not, could you please tell me what makes so slower?

Let me summarize below

Quoted 12 lines
Quoted 9 lines · you

Yes, I sent that reason out as comments to Kame's patches. kswapd or balance_pgdat controls the zones, priority and in effect how many pages we scan while doing reclaim. I did lots of experiments and found that if soft limit reclaim occurred from kswapd, soft_limit_reclaim would almost always fail and shrink_zone() would succeed, since it looks at the whole zone and is always able to find some pages at all priority levels. It also does not allow for targetted reclaim based on how much we exceed the soft limit by.

Quoted 5 lines

but, if "soft_limit_reclaim fail and shrink_zone() succeed" don't cause any performance degression, I don't find why kswapd is wrong.

I guess you and kamezawa-san know it detail. but my understanding don't reach it. Could you please tell me what so slowness.

Here is what I saw in my experiments

1. Kame's scan logic, selects shrink_zone for the mem cgroup, but the pages scanned and reclaimed from depend on priority and watermarks of the zone and *not* at all on the soft limit parameters.
2. Because soft limit reclaim fails to reclaim anythoing (due to 1), shrink_zone which is called, does reclaiming indepedent of any knowledge of soft limits, which does not work as expected.

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#26 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 5 lines · Balbir Singh

* KOSAKI Motohiro <[email protected]> [2009-03-13 16:17:25]:

1. Kame's scan logic, selects shrink_zone for the mem cgroup, but the pages scanned and reclaimed from depend on priority and watermarks of the zone and *not* at all on the soft limit parameters.

What means "not at all" ? My test result was illusion ?
My routine reclaims memory from memcg which over soft limit.... What modification is necessary ?
(Anyway, I'll remove priority and introduce something more intellegent here.)

Quoted 4 lines

2. Because soft limit reclaim fails to reclaim anythoing (due to 1), shrink_zone which is called, does reclaiming indepedent of any knowledge of soft limits, which does not work as expected.

I agree that we need some hook to loop in of shrink_zone to taking care of softlimit.

Thanks,
-Kame

Quoted 10 lines

--
Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#27 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

In reply to KOSAKI Motohiro
Quoted 20 lines · KOSAKI Motohiro
Quoted 12 lines
Quoted 9 lines
Quoted 6 lines

I have two objection to this.

- "if (!order || !did_some_progress)" mean no call try_to_free_pages() in order>0 and did_some_progress>0 case.
but mem_cgroup_soft_limit_reclaim() don't have lumpy reclaim. then, it break high order reclaim.

I am sending a fix for this right away. Thanks, the check should be if (order || !did_some_progress)

No.

Quoted 7 lines

it isn't enough.
after is does, order-1 allocation case twrice reclaim (soft limit shrinking and normal try_to_free_pages()).
then, order-1 reclaim makes slower about 2 times.

unfortunately, order-1 allocation is very frequent. it is used for kernel stack.

Quoted 7 lines

in normal order-1 reclaim is:

1. try_to_free_pages()
2. get_page_from_freelist()
3. retry if order-1 page don't exist

Coundn't you use the same logic?

Sorry, forgot to answer this question earlier.

I assume that by order-1 you mean 2 pages (2^1).

Are you suggesting that if soft limit reclaim fails, we retry? Not sure if I understand your suggestion completely.

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#28 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 28 lines · KOSAKI Motohiro
Quoted 27 lines
Quoted 13 lines
Quoted 10 lines
Quoted 7 lines

I have two objection to this.

- "if (!order || !did_some_progress)" mean no call try_to_free_pages() in order>0 and did_some_progress>0 case.
but mem_cgroup_soft_limit_reclaim() don't have lumpy reclaim. then, it break high order reclaim.

I am sending a fix for this right away. Thanks, the check should be if (order || !did_some_progress)

No.

Quoted 7 lines

it isn't enough.
after is does, order-1 allocation case twrice reclaim (soft limit shrinking and normal try_to_free_pages()).
then, order-1 reclaim makes slower about 2 times.

unfortunately, order-1 allocation is very frequent. it is used for kernel stack.

in normal order-1 reclaim is:

1. try_to_free_pages()
2. get_page_from_freelist()
3. retry if order-1 page don't exist

Quoted 5 lines
Quoted 1 line

Coundn't you use the same logic?

Sorry, forgot to answer this question earlier.

I assume that by order-1 you mean 2 pages (2^1).

Yes, almost architecutre's kernel stack use 2 pages.

Quoted 2 lines

Are you suggesting that if soft limit reclaim fails, we retry? Not sure if I understand your suggestion completely.

sorry. my last explanation is too poor.

if we need only 2pages, soft_limit_shrink() typically success reclaim it.
then

1. mem_cgroup_soft_limit_reclaim()
2. get_page_from_freelist() if mem_cgroup_soft_limit_reclaim() return >0.
3. goto got_pg if if get_page_from_freelist() is successed.
4. try_to_free_pages()
5. get_page_from_freelist() if try_to_free_pages() return >0.
6. goto 1 if order-1 page don't exist

obiously, this logic make slower more higher order because
(2) is often fail in higher order.
but that's ok. higher order reclaim is very slow. additional overhead don't observe (maybe).

What do you think?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#29 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

In reply to KOSAKI Motohiro
Quoted 20 lines · KOSAKI Motohiro
Quoted 12 lines
Quoted 12 lines

mm/page_alloc.c nofail_alloc: · line 1593

Quoted 9 lines
mm/page_alloc.c +8 -1
-	did_some_progress = try_to_free_pages(zonelist, order, gfp_mask);
+	/*
+	 * Try to free up some pages from the memory controllers soft
+	 * limit queue.
+	 */
+	did_some_progress = mem_cgroup_soft_limit_reclaim(zonelist, gfp_mask);
+	if (!order || !did_some_progress)
+		did_some_progress += try_to_free_pages(zonelist, order,
+							gfp_mask);

I have two objection to this.

Quoted 7 lines
Quoted 4 lines

- "if (!order || !did_some_progress)" mean no call try_to_free_pages() in order>0 and did_some_progress>0 case.
but mem_cgroup_soft_limit_reclaim() don't have lumpy reclaim. then, it break high order reclaim.

I am sending a fix for this right away. Thanks, the check should be if (order || !did_some_progress)

Quoted 6 lines

No.

it isn't enough.
after is does, order-1 allocation case twrice reclaim (soft limit shrinking and normal try_to_free_pages()).
then, order-1 reclaim makes slower about 2 times.

My benchmarks don't show any degredation... this slowdown will occur *iff* soft limits are enabled and groups are over their soft limit. Even if soft limit reclaim were to be initiated through kswapd (which is through my experimentation, a bad place to do it), you'd have delays incurred since you would have increased contention on zone lru lock.

Anyway, lets boil it down your comment to

The issue you claim occurs when the cgroups are over their soft limit and there is memory contention.

Quoted 17 lines

unfortunately, order-1 allocation is very frequent. it is used for kernel stack.

Quoted 11 lines
Quoted 5 lines

- in global reclaim view, foreground reclaim and background reclaim's reclaim rate is about 1:9 typically.
then, kswapd reclaim the pages by global lru order before proceccing this logic.
IOW, this soft limit is not SOFT.

It depends on what you mean by soft. I call them soft since they are imposed only when there is contention. If you mean kswapd runs more often than direct reclaim, that is true, but it does not impact this code extensively since the high water mark is a very small compared to the pages present on the system.

Quoted 4 lines

No.

My point is, contention case kswapd wakeup. and kswapd reclaim by global lru order before soft limit shrinking.

I've seen the same even if kswapd is used for reclaim, since we have no control over priority and the length to scan. shrink_zone() does more work than soft limit reclaim.

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#30 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

In reply to Balbir Singh
Quoted 28 lines · Balbir Singh

Feature: Implement reclaim from groups over their soft limit

From: Balbir Singh <[email protected]>

+unsigned long mem_cgroup_soft_limit_reclaim(struct zonelist *zl, gfp_t gfp_mask)

mm/memcontrol.c +22 -0
+{
+	unsigned long nr_reclaimed = 0;
+	struct mem_cgroup *mem;
+	unsigned long flags;
+	unsigned long reclaimed;
+
+	/*
+	 * This loop can run a while, specially if mem_cgroup's continuously
+	 * keep exceeding their soft limit and putting the system under
+	 * pressure
+	 */
+	do {
+		mem = mem_cgroup_largest_soft_limit_node();
+		if (!mem)
+			break;
+
+		reclaimed = mem_cgroup_hierarchical_reclaim(mem, zl,
+						gfp_mask,
+						MEM_CGROUP_RECLAIM_SOFT);
+		nr_reclaimed += reclaimed;
+		spin_lock_irqsave(&memcg_soft_limit_tree_lock, flags);
+		mem->usage_in_excess = res_counter_soft_limit_excess(&mem->res);

mm/memcontrol.c int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, · line 1998

Quoted 10 lines
mm/memcontrol.c +10 -0
+		__mem_cgroup_remove_exceeded(mem);
+		if (mem->usage_in_excess)
+			__mem_cgroup_insert_exceeded(mem);
+		spin_unlock_irqrestore(&memcg_soft_limit_tree_lock, flags);
+		css_put(&mem->css);
+		cond_resched();
+	} while (!nr_reclaimed);
+	return nr_reclaimed;
+}
+

Why do you never consider bad corner case....
As I wrote many times, "order of global usage" doesn't mean the biggest user of memcg containes memory in zones which we want. So, please don't pust "mem" back to RB-tree if reclaimed is 0.

This routine seems toooo bad as v4.
Nack again.

Regards,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#31 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 44 lines · KAMEZAWA Hiroyuki
Quoted 28 lines · Balbir Singh

Feature: Implement reclaim from groups over their soft limit

From: Balbir Singh <[email protected]>

+unsigned long mem_cgroup_soft_limit_reclaim(struct zonelist *zl, gfp_t gfp_mask)

mm/memcontrol.c +22 -0
+{
+	unsigned long nr_reclaimed = 0;
+	struct mem_cgroup *mem;
+	unsigned long flags;
+	unsigned long reclaimed;
+
+	/*
+	 * This loop can run a while, specially if mem_cgroup's continuously
+	 * keep exceeding their soft limit and putting the system under
+	 * pressure
+	 */
+	do {
+		mem = mem_cgroup_largest_soft_limit_node();
+		if (!mem)
+			break;
+
+		reclaimed = mem_cgroup_hierarchical_reclaim(mem, zl,
+						gfp_mask,
+						MEM_CGROUP_RECLAIM_SOFT);
+		nr_reclaimed += reclaimed;
+		spin_lock_irqsave(&memcg_soft_limit_tree_lock, flags);
+		mem->usage_in_excess = res_counter_soft_limit_excess(&mem->res);

mm/memcontrol.c int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, · line 1998

Quoted 10 lines
mm/memcontrol.c +10 -0
+		__mem_cgroup_remove_exceeded(mem);
+		if (mem->usage_in_excess)
+			__mem_cgroup_insert_exceeded(mem);
+		spin_unlock_irqrestore(&memcg_soft_limit_tree_lock, flags);
+		css_put(&mem->css);
+		cond_resched();
+	} while (!nr_reclaimed);
+	return nr_reclaimed;
+}
+

Why do you never consider bad corner case....
As I wrote many times, "order of global usage" doesn't mean the biggest user of memcg containes memory in zones which we want. So, please don't pust "mem" back to RB-tree if reclaimed is 0.

Quoted 1 line

This routine seems toooo bad as v4.

Are you talking about cases where a particular mem cgroup never allocated from a node? Thanks.. let me take a look at it

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#32 lore raw

Re: [PATCH 4/4] Memory controller soft limit reclaim on contention (v5)

Quoted 48 lines · Balbir Singh

* KAMEZAWA Hiroyuki <[email protected]> [2009-03-13 15:51:25]:

Quoted 45 lines
Quoted 5 lines · Balbir Singh

Feature: Implement reclaim from groups over their soft limit

From: Balbir Singh <[email protected]>

+unsigned long mem_cgroup_soft_limit_reclaim(struct zonelist *zl,

gfp_t

Quoted 23 lines

gfp_mask)

mm/memcontrol.c +22 -0
+{
+	unsigned long nr_reclaimed = 0;
+	struct mem_cgroup *mem;
+	unsigned long flags;
+	unsigned long reclaimed;
+
+	/*
+	 * This loop can run a while, specially if mem_cgroup's continuously
+	 * keep exceeding their soft limit and putting the system under
+	 * pressure
+	 */
+	do {
+		mem = mem_cgroup_largest_soft_limit_node();
+		if (!mem)
+			break;
+
+		reclaimed = mem_cgroup_hierarchical_reclaim(mem, zl,
+						gfp_mask,
+						MEM_CGROUP_RECLAIM_SOFT);
+		nr_reclaimed += reclaimed;
+		spin_lock_irqsave(&memcg_soft_limit_tree_lock, flags);
+		mem->usage_in_excess = res_counter_soft_limit_excess(&mem->res);

mm/memcontrol.c int mem_cgroup_resize_memsw_limit(struct mem_cgroup *memcg, · line 1998

Quoted 10 lines
mm/memcontrol.c +10 -0
+		__mem_cgroup_remove_exceeded(mem);
+		if (mem->usage_in_excess)
+			__mem_cgroup_insert_exceeded(mem);
+		spin_unlock_irqrestore(&memcg_soft_limit_tree_lock, flags);
+		css_put(&mem->css);
+		cond_resched();
+	} while (!nr_reclaimed);
+	return nr_reclaimed;
+}
+

Why do you never consider bad corner case....
As I wrote many times, "order of global usage" doesn't mean the biggest user of memcg containes memory in zones which we want. So, please don't pust "mem" back to RB-tree if reclaimed is 0.

Quoted 5 lines
Quoted 1 line

This routine seems toooo bad as v4.

Are you talking about cases where a particular mem cgroup never allocated from a node? Thanks.. let me take a look at it

Using cpuset to test and limiting nodes for memory is an easy way,

Thanks,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#33 lore raw
In reply to Balbir Singh

Balbir Singh さんは書きました:

Quoted 5 lines

From: Balbir Singh <[email protected]>

New Feature: Soft limits for memory resource controller.

Quoted 11 lines

Changelog v5...v4
1. Several changes to the reclaim logic, please see the patch 4 (reclaim on
contention). I've experimented with several possibilities for reclaim and chose to come back to this due to the excellent behaviour seen
while
testing the patchset.
2. Reduced the overhead of soft limits on resource counters very significantly.
Reaim benchmark now shows almost no drop in performance.

It seems there are no changes to answer my last comments.

Nack again. I'll update my own version again.

Thanks,
-Kame

-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#34 lore raw

KAMEZAWA Hiroyuki さんは書きました:

Quoted 17 lines

Balbir Singh さんは書きました:

Quoted 5 lines

From: Balbir Singh <[email protected]>

New Feature: Soft limits for memory resource controller.

Quoted 11 lines

Changelog v5...v4
1. Several changes to the reclaim logic, please see the patch 4 (reclaim on
contention). I've experimented with several possibilities for reclaim and chose to come back to this due to the excellent behaviour seen
while
testing the patchset.
2. Reduced the overhead of soft limits on resource counters very significantly.
Reaim benchmark now shows almost no drop in performance.

Quoted 4 lines

It seems there are no changes to answer my last comments.

Nack again. I'll update my own version again.

Sigh, this is in -mm ? okay...I'll update onto -mm as much as I can. Very heavy work, maybe.
Thanks,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#35 lore raw
Quoted 18 lines · KAMEZAWA Hiroyuki

KAMEZAWA Hiroyuki ?$B$5$s$O=q$-$^$7$?!'

Quoted 17 lines

Balbir Singh ?$B$5$s$O=q$-$^$7$?!'

Quoted 16 lines

From: Balbir Singh <[email protected]>

New Feature: Soft limits for memory resource controller.

Changelog v5...v4
1. Several changes to the reclaim logic, please see the patch 4 (reclaim on
contention). I've experimented with several possibilities for reclaim and chose to come back to this due to the excellent behaviour seen
while
testing the patchset.
2. Reduced the overhead of soft limits on resource counters very significantly.
Reaim benchmark now shows almost no drop in performance.

Quoted 6 lines
Quoted 4 lines

It seems there are no changes to answer my last comments.

Nack again. I'll update my own version again.

Sigh, this is in -mm ? okay...I'll update onto -mm as much as I can. Very heavy work, maybe.

Andrew just dropped it from -mm, so don't rush on updating. I was about to send fixes to address review comments, but I'll just merge that in -v6.

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#36 lore raw
In reply to KAMEZAWA Hiroyuki
Quoted 4 lines · On Fri, 13 Mar 2009 16:07:35 +0900 (JST) "KAMEZAWA Hiroyuki"…
Quoted 2 lines

Nack again. I'll update my own version again.

Sigh, this is in -mm ? okay...I'll update onto -mm as much as I can. Very heavy work, maybe.

I dropped them all again. it appears that quite a few changes are needed and I don't think we want these patches interfering with other cgroup and general MM development.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#37 lore raw
Quoted 11 lines · Andrew Morton
Quoted 4 lines · On Fri, 13 Mar 2009 16:07:35 +0900 (JST) "KAMEZAWA Hiroyuki"…
Quoted 2 lines

Nack again. I'll update my own version again.

Sigh, this is in -mm ? okay...I'll update onto -mm as much as I can. Very heavy work, maybe.

I dropped them all again. it appears that quite a few changes are needed and I don't think we want these patches interfering with other cgroup and general MM development.

Thanks Andrew and I'll send an updated patchset later. I'll fix most review comments and post v6. Hopefully, Kame's and my thought processes would merge and we'll be ready for inclusion soon again.

I don't think v6 will be ready for inclusion yet.

Signature · 7 lines
	Balbir

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>