Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 14 Dec 2012 21:22:23 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r244225 - projects/calloutng/sys/kern
Message-ID:  <201212142122.qBELMNJV048723@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Fri Dec 14 21:22:23 2012
New Revision: 244225
URL: http://svnweb.freebsd.org/changeset/base/244225

Log:
  Add some simple adaptiveness to the maximal next even lookup depth.
  
  If callout_process() was called two times within the same millisecond,
  limit lookup by 1/16s instead of default 1/2s.  On the amd64 test system
  it reduces usleep(1) time from 8us to 6us, handling about 180K callouts
  and thread wakeups per second in one stream with not full CPU load.
  
  That is the only price of staying with the callwheel data structure.
  Unless at some point we want to sleep/lookup for minutes, it doesn't
  look high.

Modified:
  projects/calloutng/sys/kern/kern_timeout.c

Modified: projects/calloutng/sys/kern/kern_timeout.c
==============================================================================
--- projects/calloutng/sys/kern/kern_timeout.c	Fri Dec 14 18:30:01 2012	(r244224)
+++ projects/calloutng/sys/kern/kern_timeout.c	Fri Dec 14 21:22:23 2012	(r244225)
@@ -387,7 +387,8 @@ callout_process(struct bintime *now)
 	struct callout *tmp;
 	struct callout_cpu *cc;
 	struct callout_tailq *sc;
-	int cpu, depth_dir, firstb, mpcalls_dir, lastb, nowb, lockcalls_dir,
+	uint64_t lookahead;
+	int depth_dir, firstb, mpcalls_dir, lastb, nowb, lockcalls_dir,
 	    need_softclock, exit_allowed, exit_wanted;
 
 	need_softclock = 0;
@@ -396,16 +397,21 @@ callout_process(struct bintime *now)
 	lockcalls_dir = 0;
 	cc = CC_SELF();
 	mtx_lock_spin_flags(&cc->cc_lock, MTX_QUIET);
-	cpu = curcpu;
 
 	/* Compute the buckets of the last scan and present times. */
 	firstb = callout_hash(&cc->cc_lastscan);
 	nowb = callout_hash(now);
 
 	/* Compute the last bucket and minimum time of the bucket after it. */
+	if (nowb == firstb)
+		lookahead = 1LLU << 60;		/* 1/16s */
+	else if (nowb - firstb == 1)
+		lookahead = 1LLU << 61;		/* 1/8s */
+	else
+		lookahead = 1LLU << 63;		/* 1/2s */
 	first = last = *now;
-	bintime_addx(&first, (uint64_t)3 << (64 - 3));		/* 0.37s */
-	bintime_addx(&last, (uint64_t)3 << (64 - 2));		/* 0.75s */
+	bintime_addx(&first, lookahead / 2);
+	bintime_addx(&last, lookahead);
 	last.frac &= (0xffffffffffffffffLLU << (64 - CC_HASH_SHIFT));
 	lastb = callout_hash(&last) - 1;
 	max = last;
@@ -429,9 +435,6 @@ callout_process(struct bintime *now)
 		sc = &cc->cc_callwheel[firstb];
 		tmp = TAILQ_FIRST(sc);
 		while (tmp != NULL) {
-			/* Compute allowed time range for the event */
-			tmp_max = tmp->c_time;
-			bintime_add(&tmp_max, &tmp->c_precision);
 			/* Run the callout if present time within allowed. */
 			if (bintime_cmp(&tmp->c_time, now, <=)) {
 				/*
@@ -471,6 +474,8 @@ callout_process(struct bintime *now)
 			/* Update first and last time, respecting this event. */
 			if (bintime_cmp(&tmp->c_time, &first, <))
 				first = tmp->c_time;
+			tmp_max = tmp->c_time;
+			bintime_add(&tmp_max, &tmp->c_precision);
 			if (bintime_cmp(&tmp_max, &last, <))
 				last = tmp_max;
 next:
@@ -492,7 +497,7 @@ next:
 	}
 	cc->cc_exec_next_dir = NULL;
 	if (callout_new_inserted != NULL)
-		(*callout_new_inserted)(cpu, last, first);
+		(*callout_new_inserted)(curcpu, last, first);
 	cc->cc_firstevent = last;
 	cc->cc_lastscan = *now;
 #ifdef CALLOUT_PROFILING



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