aboutsummaryrefslogtreecommitdiff
path: root/rpkid/rpki/async.py
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2010-01-04 22:28:34 +0000
committerRob Austein <sra@hactrn.net>2010-01-04 22:28:34 +0000
commit54f4de8a9cc2da82eda5a2f675cbe498fd873dde (patch)
treec099aefca3d4bd09297392a53ba87c52b0c9704f /rpkid/rpki/async.py
parent7520493f7dcb721638aef731bcd69b76e5b73d65 (diff)
Still seeing unexplained memory bloat, try a different approach to
tracking this down. svn path=/rpkid/rpki/async.py; revision=2926
Diffstat (limited to 'rpkid/rpki/async.py')
-rw-r--r--rpkid/rpki/async.py45
1 files changed, 35 insertions, 10 deletions
diff --git a/rpkid/rpki/async.py b/rpkid/rpki/async.py
index 79bfbcf2..21ff0f40 100644
--- a/rpkid/rpki/async.py
+++ b/rpkid/rpki/async.py
@@ -18,7 +18,7 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
"""
-import asyncore, signal, traceback
+import asyncore, signal, traceback, gc
import rpki.log, rpki.sundial
ExitNow = asyncore.ExitNow
@@ -123,15 +123,10 @@ class timer(object):
def set(self, when):
"""
Set a timer. Argument can be a datetime, to specify an absolute
- time, a timedelta, to specify an offset time, or None, to indicate
- that the timer should expire immediately, which can be useful in
- avoiding an excessively deep call stack.
+ time, or a timedelta, to specify an offset time.
"""
self.trace("Setting %r to %r" % (self, when))
- if when is None:
- rpki.log.warn("Obsolete timer usage: convert this to use rpki.async.defer() instead: %r" % self)
- self.when = rpki.sundial.now()
- elif isinstance(when, rpki.sundial.timedelta):
+ if isinstance(when, rpki.sundial.timedelta):
self.when = rpki.sundial.now() + when
else:
self.when = when
@@ -279,8 +274,6 @@ def event_loop(catch_signals = (signal.SIGINT, signal.SIGTERM)):
try:
for sig in catch_signals:
old_signal_handlers[sig] = signal.signal(sig, _raiseExitNow)
- if timer.gc_debug:
- import gc
while asyncore.socket_map or deferred_queue or timer.queue:
run_deferred()
asyncore.poll(timer.seconds_until_wakeup(), asyncore.socket_map)
@@ -350,3 +343,35 @@ class sync_wrapper(object):
def exit_event_loop():
"""Force exit from event_loop()."""
raise ExitNow
+
+class gc_summary(object):
+ """
+ Periodic summary of GC state, for tracking down memory bloat.
+ """
+
+ def __init__(self, interval):
+ if isinstance(interval, (int, long)):
+ interval = rpki.sundial.timedelta(seconds = interval)
+ self.interval = interval
+ self.timer = timer(handler = self.handler)
+ self.timer.set(self.interval)
+
+ def handler(self):
+ rpki.log.debug("gc_summary: Running gc.collect()")
+ gc.collect()
+ rpki.log.debug("gc_summary: Summarizing")
+ total = {}
+ for g in gc.get_objects():
+ t = type(g).__name__
+ if t in total:
+ total[t] += 1
+ else:
+ total[t] = 1
+ rpki.log.debug("gc_summary: Sorting result")
+ total = total.items()
+ total.sort(reverse = True, key = lambda x: x[1])
+ rpki.log.debug("gc_summary: Object type counts in descending order")
+ for name, count in total:
+ rpki.log.debug("gc_summary: %8d %s" % (count, name))
+ rpki.log.debug("gc_summary: Scheduling next cycle")
+ self.timer.set(self.interval)