Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 05 Aug 2012 21:32:52 +0000
From:      rudot@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r240116 - in soc2012/rudot/sys: kern sys
Message-ID:  <20120805213252.55BE5106564A@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rudot
Date: Sun Aug  5 21:32:51 2012
New Revision: 240116
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=240116

Log:
  when limiting %cpu, we act sooner than the limits are exceeded already. This makes exceeding %cpu limits less likely

Modified:
  soc2012/rudot/sys/kern/kern_racct.c
  soc2012/rudot/sys/kern/kern_rctl.c
  soc2012/rudot/sys/sys/rctl.h

Modified: soc2012/rudot/sys/kern/kern_racct.c
==============================================================================
--- soc2012/rudot/sys/kern/kern_racct.c	Sun Aug  5 20:19:27 2012	(r240115)
+++ soc2012/rudot/sys/kern/kern_racct.c	Sun Aug  5 21:32:51 2012	(r240116)
@@ -66,8 +66,19 @@
 
 FEATURE(racct, "Resource Accounting");
 
+/*
+ * Do not block processes that have their %cpu usage <= RACCT_PCTCPU_IGNORE
+ */
 #define	RACCT_PCTCPU_IGNORE	1
 
+/*
+ * How many seconds it takes to use the scheduler %cpu calculations. When a
+ * process starts, we compute its %cpu usage by dividing its runtime by the
+ * process wall clock time. After RACCT_PCPU_SECS pass, we use the value
+ * provided by the scheduler.
+ */
+#define RACCT_PCPU_SECS		3
+
 struct mtx racct_lock;
 MTX_SYSINIT(racct_lock, &racct_lock, "racct lock", MTX_DEF);
 
@@ -298,7 +309,7 @@
 	swtime = (ticks - p->p_swtick) / hz;
 	if ((swtime == 0) || ((p->p_flag & P_INMEM) == 0))
 		return (0);
-	if (swtime < 20) {
+	if (swtime < RACCT_PCPU_SECS) {
 		/*
 		 * For short-lived processes, the sched_pctcpu() returns small
 		 * values even for cpu intensive processes. Therefore we use
@@ -568,8 +579,7 @@
 static int
 racct_set_check_locked(struct proc *p, int resource, uint64_t amount)
 {
-	int64_t diff;
-	int over_limit;
+	int64_t diff, available;
 
 	SDT_PROBE(racct, kernel, rusage, set, p, resource, amount, 0, 0);
 
@@ -587,9 +597,9 @@
 	    ("racct_set: usage of non-reclaimable resource %d dropping",
 	     resource));
 #endif
-	over_limit = 0;
+	available = INT64_MAX;
 #ifdef RCTL
-	over_limit = rctl_over_limit(p, resource, diff);
+	available = rctl_pcpu_available(p);
 #endif
 	racct_alloc_resource(p->p_racct, resource, diff);
 	if (diff > 0)
@@ -597,7 +607,7 @@
 	else if (diff < 0)
 		racct_sub_cred_locked(p->p_ucred, resource, -diff);
 
-	return (over_limit);
+	return (available <= diff);
 }
 
 static int
@@ -1052,7 +1062,8 @@
 			    wallclock.tv_usec);
 			pct = racct_getpcpu(p, pct_estimate);
 			mtx_lock(&racct_lock);
-			over_limits = racct_set_check_locked(p, RACCT_PCTCPU, pct);
+			over_limits = racct_set_check_locked(p, RACCT_PCTCPU,
+			    pct);
 			if (over_limits) {
 				racct_proc_disable(p);
 			} else if (racct_proc_disabled(p)) {

Modified: soc2012/rudot/sys/kern/kern_rctl.c
==============================================================================
--- soc2012/rudot/sys/kern/kern_rctl.c	Sun Aug  5 20:19:27 2012	(r240115)
+++ soc2012/rudot/sys/kern/kern_rctl.c	Sun Aug  5 21:32:51 2012	(r240116)
@@ -76,6 +76,8 @@
 #define	RCTL_MAX_INBUFLEN	4096
 #define	RCTL_LOG_BUFSIZE	128
 
+#define	RCTL_PCPU_SHIFT		10
+
 /*
  * 'rctl_rule_link' connects a rule with every racct it's related to.
  * For example, rule 'user:X:openfiles:deny=N/process' is linked
@@ -272,31 +274,48 @@
 }
 
 /*
- * Return non-zero if allocating 'amount' by proc 'p' would exceed
- * 'resource' limit specified by any rule applicable to the process 'p'.
- * The 'amount' can be negative.
+ * Special version of rctl_available() function for the %cpu resource.
+ * We slightly cheat here and return less than we normally would.
  */
-int
-rctl_over_limit(const struct proc *p, int resource, int64_t amount) {
+int64_t
+rctl_pcpu_available(const struct proc *p) {
 	struct rctl_rule *rule;
 	struct rctl_rule_link *link;
-	int over_limit;
+	int64_t available, minavailable, limit;
+
+	minavailable = INT64_MAX;
+	limit = 0;
 
-	over_limit = 0;
 	rw_rlock(&rctl_lock);
 
 	LIST_FOREACH(link, &p->p_racct->r_rule_links, rrl_next) {
 		rule = link->rrl_rule;
-		if (rule->rr_resource != resource)
+		if (rule->rr_resource != RACCT_PCTCPU)
 			continue;
-		if (rctl_would_exceed(p, rule, amount)) {
-			over_limit = 1;
-			break;
+		if (rule->rr_action != RCTL_ACTION_DENY)
+			continue;
+		available = rctl_available_resource(p, rule);
+		if (available < minavailable) {
+			minavailable = available;
+			limit = rule->rr_amount;
 		}
 	}
 
 	rw_runlock(&rctl_lock);
-	return (over_limit);
+
+	/*
+	 * Return slightly less than actual value of the available
+	 * %cpu resource. This makes %cpu throttling more agressive
+	 * and lets us act sooner than the limits are already exceeded.
+	 */
+	if (limit != 0) {
+		if (limit > 2 * RCTL_PCPU_SHIFT)
+			minavailable -= RCTL_PCPU_SHIFT;
+		else
+			minavailable -= (limit / 2);
+	}
+
+	return (minavailable);
 }
 
 /*

Modified: soc2012/rudot/sys/sys/rctl.h
==============================================================================
--- soc2012/rudot/sys/sys/rctl.h	Sun Aug  5 20:19:27 2012	(r240115)
+++ soc2012/rudot/sys/sys/rctl.h	Sun Aug  5 21:32:51 2012	(r240116)
@@ -140,7 +140,7 @@
 int	rctl_rule_add(struct rctl_rule *rule);
 int	rctl_rule_remove(struct rctl_rule *filter);
 int	rctl_enforce(struct proc *p, int resource, uint64_t amount);
-int	rctl_over_limit(const struct proc *p, int resource, int64_t amount);
+int64_t	rctl_pcpu_available(const struct proc *p);
 uint64_t rctl_get_limit(struct proc *p, int resource);
 uint64_t rctl_get_available(struct proc *p, int resource);
 const char *rctl_resource_name(int resource);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120805213252.55BE5106564A>