Hi,
i attach 1 patch which can improve the performance (patch for the scheduler).
Please take a look for detailed information. Please let me know, whether it 
helps in your case (if you use it).

Best regards,
Robert

Last thing: the patch is for ns-2.30 (ns-allinone-2.30).

On Donnerstag, 12. November 2009, Jonathan Kirchhoff wrote:
> Hi,
>
> I'm doing simulations of wireless ad-hoc routing protocols using
> nsclick. Everything appears to be working just fine, but in comparison
> to native NS-2 simulations, the ones using nsclick seem to be taking
> ages to finish. Here's an example:
>
> Native :  02:14min
> Nsclick:  12:34min
>
> Same protocol, scenario and simulated time.
>
> Is this something to be expected, or is the reason more likely to be
> found in my protocol implementation or simulation setup?
>
> Thanks!
>
> Regards
> Jonathan
> _______________________________________________
> click mailing list
> [email protected]
> https://amsterdam.lcs.mit.edu/mailman/listinfo/click


diff -urN ns-2.31/common/scheduler.cc ns-2.31-scheduler-doc/common/scheduler.cc
--- ns-2.31/common/scheduler.cc	2006-02-21 07:20:18.000000000 -0800
+++ ns-2.31-scheduler-doc/common/scheduler.cc	2007-11-11 22:39:02.000000000 -0800
@@ -581,6 +581,17 @@
 } class_calendar_sched;
 
 CalendarScheduler::CalendarScheduler() : cal_clock_(clock_) {
+	bind("adjust_new_width_interval_", &adjust_new_width_interval_);
+	bind("min_bin_width_", &min_bin_width_);
+	if (adjust_new_width_interval_) {
+		avg_gap_ = -2;
+		last_time_ = -2;
+		gap_num_ = 0;
+		head_search_ = 0;
+		insert_search_ = 0; 
+		round_num_ = 0; 
+		time_to_newwidth = adjust_new_width_interval_;
+	}
 	reinit(4, 1.0, cal_clock_);
 }
 
@@ -595,47 +606,46 @@
 CalendarScheduler::insert(Event* e)
 {
 	int i;
-	if (cal_clock_ > e->time_) {
+	double newtime = e->time_;
+	if (cal_clock_ > newtime) {
 		// may happen in RT scheduler
-		cal_clock_ = e->time_;
+		cal_clock_ = newtime;
 		i = lastbucket_ = CALENDAR_HASH(cal_clock_);
 	} else
-		i = CALENDAR_HASH(e->time_);
+		i = CALENDAR_HASH(newtime);
 
-	Event *head = buckets_[i].list_;
-	Event *before=0;
+	Bucket* current=(&buckets_[i]);
+	Event *head = current->list_;
+	Event *after=0;
 
 	if (!head) {
-		buckets_[i].list_ = e;
+		current->list_ = e;
 		e->next_ = e->prev_ = e;
 		++stat_qsize_; 
-		++buckets_[i].count_;
+		++(current->count_);
 	} else {
-		bool newhead;
-		if (e->time_ >= head->prev_->time_) {
-			// insert at the tail
-			before = head;
-			newhead = false;
+		insert_search_++;
+		if (newtime < head->time_) {
+			//  e-> head -> ...
+			e->next_ = head;
+			e->prev_ = head->prev_;
+			e->prev_->next_ = e;
+			head->prev_ = e;
+			current->list_ = e;
+                        ++stat_qsize_;
+                        ++(current->count_);
 		} else {
-			// insert event in time sorted order, FIFO for sim-time events
-			for (before = head; e->time_ >= before->time_; before = before->next_)
-				;
-			newhead = (before == head);
-		}
-
-		e->next_ = before;
-		e->prev_ = before->prev_;
-		before->prev_ = e;
-		e->prev_->next_ = e;
-		if (newhead) {
-			buckets_[i].list_ = e;
-			//assert(e->time_ <= e->next_->time_);
-		}
-		//assert(e->prev_ != e);
-		if (e->prev_->time_ != e->time_) {
-			// unique timing
-			++stat_qsize_; 
-			++buckets_[i].count_;
+                        for (after = head->prev_; newtime < after->time_; after = after->prev_) { insert_search_++; };
+			//...-> after -> e -> ...
+			e->next_ = after->next_;
+			e->prev_ = after;
+			e->next_->prev_ = e;
+			after->next_ = e;
+			if (after->time_ < newtime) {
+				//unique timing
+				++stat_qsize_; 
+				++(current->count_);
+			}
 		}
 	}
 	++qsize_;
@@ -710,6 +720,7 @@
 	Event *e, *min_e = NULL;
 #define CAL_DEQUEUE(x) 						\
 do { 								\
+	head_search_++;						\
 	if ((e = buckets_[i].list_) != NULL) {			\
 		diff = e->time_ - cal_clock_;			\
 		if (diff < diff##x##_)	{			\
@@ -769,6 +780,34 @@
 	if (!e)
 		return 0;
 
+	if (adjust_new_width_interval_) {
+		if (last_time_< 0) last_time_ = e->time_;
+		else 
+		{
+			gap_num_ ++;
+			if (gap_num_ >= qsize_ ) {
+	                	double tt_gap_ = e->time_ - last_time_;
+				avg_gap_ = tt_gap_ / gap_num_;
+        	                gap_num_ = 0;
+                	        last_time_ = e->time_;
+				round_num_ ++;
+				if ((round_num_ > 20) &&
+					   (( head_search_> (insert_search_<<1))
+					  ||( insert_search_> (head_search_<<1)) )) 
+				{
+					resize(nbuckets_, cal_clock_);
+					round_num_ = 0;
+				} else {
+                        	        if (round_num_ > 100) {
+                                	        round_num_ = 0;
+                                        	head_search_ = 0;
+	                                        insert_search_ = 0;
+        	                        }
+				}
+			}
+		}
+	};
+
 	int l = lastbucket_;
 
 	// update stats and unlink
@@ -828,10 +867,32 @@
 void 
 CalendarScheduler::resize(int newsize, double start)
 {
-	double bwidth = newwidth(newsize);
-
-	if (newsize < 4)
-		newsize = 4;
+	double bwidth;
+	if (newsize == nbuckets_) {
+		/* we resize for bwidth*/
+		if (head_search_) bwidth = head_search_; else bwidth = 1;
+		if (insert_search_) bwidth = bwidth / insert_search_;
+		bwidth = sqrt (bwidth) * width_;
+ 		if (bwidth < min_bin_width_) {
+ 			if (time_to_newwidth>0) {
+ 				time_to_newwidth --;
+ 			        head_search_ = 0;
+ 			        insert_search_ = 0;
+ 				round_num_ = 0;
+ 				return; //failed to adjust bwidth
+ 			} else {
+				// We have many (adjust_new_width_interval_) times failure in adjusting bwidth.
+				// should do a reshuffle with newwidth 
+ 				bwidth = newwidth(newsize);
+ 			}
+ 		};
+		//snoopy queue calculation
+	} else {
+		/* we resize for size */
+		bwidth = newwidth(newsize);
+		if (newsize < 4)
+			newsize = 4;
+	}
 
 	Bucket *oldb = buckets_;
 	int oldn = nbuckets_;
@@ -856,13 +917,20 @@
 			} while (e != tail);
 		}
 	}
-	delete [] oldb;
+        head_search_ = 0;
+        insert_search_ = 0;
+	round_num_ = 0;
+        delete [] oldb;
 }
 
 // take samples from the most populated bucket.
 double
 CalendarScheduler::newwidth(int newsize)
 {
+	if (adjust_new_width_interval_) {
+		time_to_newwidth = adjust_new_width_interval_;
+		if (avg_gap_ > 0) return avg_gap_*4.0;
+	}
 	int i;
 	int max_bucket = 0; // index of the fullest bucket
 	for (i = 1; i < nbuckets_; ++i) {
diff -urN ns-2.31/common/scheduler.h ns-2.31-scheduler-doc/common/scheduler.h
--- ns-2.31/common/scheduler.h	2005-07-26 18:13:42.000000000 -0700
+++ ns-2.31-scheduler-doc/common/scheduler.h	2007-11-11 22:39:02.000000000 -0800
@@ -154,6 +154,16 @@
 	const Event* head();
 
 protected:
+	double min_bin_width_;		// minimum bin width for Calendar Queue
+	unsigned int adjust_new_width_interval_; // The interval (in unit of resize time) for adjustment of bin width. A zero value disables automatic bin width adjustment
+	unsigned time_to_newwidth;	// how many time we failed to adjust the width based on snoopy-queue
+	long unsigned head_search_;
+	long unsigned insert_search_;
+	int round_num_;
+	long int gap_num_;		//the number of gap samples in this window (in process of calculation)
+	double last_time_;		//the departure time of first event in this window
+	double avg_gap_;		//the average gap in last window (finished calculation)
+
 	double width_;
 	double diff0_, diff1_, diff2_; /* wrap-around checks */
 
diff -urN ns-2.31/doc/ns.bib ns-2.31-scheduler-doc/doc/ns.bib
--- ns-2.31/doc/ns.bib	2003-12-13 22:52:40.000000000 -0800
+++ ns-2.31-scheduler-doc/doc/ns.bib	2007-11-11 22:40:56.000000000 -0800
@@ -998,6 +998,25 @@
   crossref =	 "McCaXX:wb"
 }
 
+...@inproceedings{tan00snoopyqueue,
+  author = 	"Kah Leong Tan and Li-Jin Thng", 
+  title = 	"SNOOPy Calendar Queue",
+  booktitle =	"Proceedings of the 32nd conference on Winter simulation Orlando, Florida",
+  pages =        {487-495},
+  year =         2000
+}
+
+...@inproceedings{weicao06nslinuxtcp,
+  author = "Xiaoliang (David) Wei and Pei Cao",
+  title = "{NS-2 TCP-Linux: an NS-2 TCP implementation with congestion control algorithms from Linux}",
+  booktitle = "{WNS2 '06: Proceeding from the 2006 workshop on ns-2: the IP network simulator}",
+  year = {2006},
+  pages = {9},
+  publisher = {ACM Press},
+  address = {New York, NY, USA},
+}
+
+
 @string{usc = "University of Southern California"}
 @string{usc-isi = "USC/Information Sciences Institute"}
 @string{ieee-computer = "{IEEE} Computer"};
diff -urN ns-2.31/doc/sim.tex ns-2.31-scheduler-doc/doc/sim.tex
--- ns-2.31/doc/sim.tex	2003-04-03 12:36:52.000000000 -0800
+++ ns-2.31-scheduler-doc/doc/sim.tex	2007-11-11 22:39:02.000000000 -0800
@@ -151,6 +151,38 @@
 The implementation of Calendar queues in \ns~v2
 was contributed by David Wetherall (presently at MIT/LCS).
 
+The calendar queue scheduler since \ns~v2.33 is improved by the following
+three algorithms:
+\begin{itemize}
+	\item A heuristic improvement that changes the linear search direction
+in enqueue operations. The original implementation searches the events in
+a bucket in \emph{chronological order} to find the in-order spot for the event
+that is being inserted.
+The new implementation searches the bucket in \emph{reverse chronological order}
+because the event being inserted is usually later than most of the events that are
+already in the bucket.
+	\item A new bucket width estimation that uses the average interval of
+\emph{dequeued events} as the estimation of bucket width. It is stated in
+\cite{Brow88:Calendar} that the optimal bucket width should be the \emph{average inverval of all events in the future}.
+The original implementation uses the average interval of \emph{future events currently in the most crowded bucket}
+as the estimation. This estimation is unstable because it is very likely
+that many future events will be inserted into the bucket after this estimation, significantly changing the
+averaged event interval in the bucket. The new implementation uses the observed event interval 
+in the past, which will not change, to estimate the event interval in future.
+	\item SNOOPy Calendar Queue: a Calendar queue variant that dynamically
+tunes the bucket width according to the cost trade-off between enqueue
+operation and dequeue operation.
+The SNOOPy queue improvement is described in \cite{Tan00SNOOPyQueue}.
+In this implementation, there is one tcl parameter {\tt adjust\_new\_width\_interval\_ }
+specifying the interval with which the SNOOPy queue should re-calculate the bucket width.
+Setting this parameter to 0 turns off the SNOOPy queue algorithm and degrades the scheduler
+back to the original Calendar Queue. In general, normal simulation users are
+not expected to change this parameter.
+\end{itemize}
+The details of these improvements are described in \cite{WeiCao06NSLinuxTCP}.
+
+The implementation of these three improvements was contributed by Xiaoliang (David) Wei at Caltech/NetLab.
+
 \subsection{The Real-Time Scheduler}
 \label{sec:rtsched}
 
diff -urN ns-2.31/tcl/lib/ns-default.tcl ns-2.31-scheduler-doc/tcl/lib/ns-default.tcl
--- ns-2.31/tcl/lib/ns-default.tcl	2006-10-22 22:33:16.000000000 -0700
+++ ns-2.31-scheduler-doc/tcl/lib/ns-default.tcl	2007-11-11 22:39:35.000000000 -0800
@@ -72,6 +72,9 @@
 
 Scheduler/RealTime set maxslop_ 0.010; # max allowed slop b4 error (sec)
 
+Scheduler/Calendar set adjust_new_width_interval_ 10;	# the interval (in unit of resize times) we recalculate bin width. 0 means disable dynamic adjustment
+Scheduler/Calendar set min_bin_width_ 1e-18;		# the lower bound for the bin_width
+
 #
 # Queues and associated
 #
_______________________________________________
click mailing list
[email protected]
https://amsterdam.lcs.mit.edu/mailman/listinfo/click

Reply via email to