beagle r4383 - trunk/beagle/beagled



Author: dbera
Date: Sat Jan 12 01:36:21 2008
New Revision: 4383
URL: http://svn.gnome.org/viewvc/beagle?rev=4383&view=rev

Log:
Add an environment variable BEAGLE_FORCE_GC to do a forceful collection after any client exits. There are two caveats in allowing GC do the collection on its own:
- If most of the threads are blocked (as would happen if initial indexing is over), then there is no thread to run the GC.
- If there is a sudden load and GC is forced to allocate more memory, letting it run on its own will take a long time for that extra memory to be returned.
Locking horns with the GC is bad, but based on the current allocation pattern of beagled, BEAGLE_FORCE_GC takes a proactive approach and when a client disconnects, wait 1 min and then do a forceful GC. Based on experiments, one collect is not enough, for the time being run 5 collection at 1 min interval. If there are more clients in the interval, then push back the collection appropriately.


Modified:
   trunk/beagle/beagled/Server.cs

Modified: trunk/beagle/beagled/Server.cs
==============================================================================
--- trunk/beagle/beagled/Server.cs	(original)
+++ trunk/beagle/beagled/Server.cs	Sat Jan 12 01:36:21 2008
@@ -427,7 +427,10 @@
 			if (this.executor != null) {
 				this.executor.Cleanup ();
 				this.executor.AsyncResponseEvent -= OnAsyncResponse;
+				this.executor = null;
 			}
+
+			Server.RunGC ();
 		}
 
 		public void WatchCallback (IAsyncResult ar)
@@ -632,10 +635,19 @@
 
 		public static Hashtable item_handlers = new Hashtable ();
 
+		private static System.Timers.Timer gc_timer = null;
+
 		static Server ()
 		{
 			foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies ())
 				ScanAssemblyForExecutors (assembly);
+
+			if (Environment.GetEnvironmentVariable ("BEAGLE_FORCE_GC") != null) {
+				gc_timer = new System.Timers.Timer ();
+				gc_timer.Interval = 60000; // GC Collect to run after xxx msecs of last client closing
+				gc_timer.Elapsed += new ElapsedEventHandler (GCTimerElapsed);
+				gc_timer.AutoReset = false;
+			}
 		}
 
 		public Server (string name, bool indexhelper, bool enable_network_svc)
@@ -676,6 +688,32 @@
 			}
 		}
 
+		static int gc_count = 0;
+
+		static internal void RunGC ()
+		{
+			if (gc_timer == null)
+				return;
+
+			gc_timer.Stop ();
+			gc_timer.AutoReset = true;
+			gc_count = 5;
+			gc_timer.Start ();
+		}
+
+		private static void GCTimerElapsed (object sender, ElapsedEventArgs e)
+    		{
+			Console.WriteLine("After GC collection: {0} (RSS {1})", GC.GetTotalMemory (false), SystemInformation.VmRss);
+
+			GC.Collect (2); // The argument is a no-op in mono
+			GC.WaitForPendingFinalizers();
+
+			if (--gc_count == 0) {
+				gc_timer.AutoReset = false;
+				gc_timer.Stop ();
+			}
+    		}
+
 		private static void OnShutdown ()
 		{
 			lock (live_handlers) {
@@ -729,7 +767,7 @@
 
 			Logger.Log.Debug ("Server '{0}' shut down", this.socket_path);
 		}
-		
+
 		private void HttpRun ()
 		{
 			http_listener = new HttpListener ();
@@ -899,6 +937,9 @@
 
 		public void Stop ()
 		{
+			if (gc_timer != null)
+				gc_timer.Stop ();
+
 			if (this.running) {
 				this.running = false;
 				this.unix_listener.Stop ();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]