Add periodic CPython garbage collector statistics logging to aid in
tracking down a memory leak and as a general health beacon for the long
running process.

The interval at which stats are logged is configurable.

Signed-off-by: Gregory Smith <gps@google.com>


git-svn-id: http://test.kernel.org/svn/autotest/trunk@4021 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/scheduler/monitor_db_unittest.py b/scheduler/monitor_db_unittest.py
index da0c2a2..446df33 100755
--- a/scheduler/monitor_db_unittest.py
+++ b/scheduler/monitor_db_unittest.py
@@ -1,18 +1,19 @@
 #!/usr/bin/python
 
-import unittest, time, subprocess, os, StringIO, tempfile, datetime, shutil
-import logging
+import time, subprocess, os, StringIO, tempfile, datetime, shutil
+import gc, logging
 import common
 import MySQLdb
 from autotest_lib.frontend import setup_django_environment
 from autotest_lib.frontend.afe import frontend_test_utils
 from autotest_lib.client.common_lib import global_config, host_protections
 from autotest_lib.client.common_lib.test_utils import mock
+from autotest_lib.client.common_lib.test_utils import unittest
 from autotest_lib.database import database_connection, migrate
 from autotest_lib.frontend import thread_local
 from autotest_lib.frontend.afe import models
 from autotest_lib.scheduler import monitor_db, drone_manager, email_manager
-from autotest_lib.scheduler import scheduler_config
+from autotest_lib.scheduler import scheduler_config, gc_stats
 
 _DEBUG = False
 
@@ -769,6 +770,22 @@
         self._check_for_extra_schedulings()
 
 
+    def test_garbage_collection(self):
+        self.god.stub_with(self._dispatcher, '_seconds_between_garbage_stats',
+                           999999)
+        self.god.stub_function(gc, 'collect')
+        self.god.stub_function(gc_stats, '_log_garbage_collector_stats')
+        gc.collect.expect_call().and_return(0)
+        gc_stats._log_garbage_collector_stats.expect_call()
+        # Force a garbage collection run
+        self._dispatcher._last_garbage_stats_time = 0
+        self._dispatcher._garbage_collection()
+        # The previous call should have reset the time, it won't do anything
+        # the second time.  If it does, we'll get an unexpected call.
+        self._dispatcher._garbage_collection()
+
+
+
 class DispatcherThrottlingTest(BaseSchedulerTest):
     """
     Test that the dispatcher throttles: