From 1af4a4ae9f72b9e4e4055ebddc9947ce51d8a02a Mon Sep 17 00:00:00 2001
From: Kevin O'Connor <kevin@koconnor.net>
Date: Thu, 17 Sep 2020 01:59:18 -0400
Subject: [PATCH] reactor: Record time of recent gc collection sweeps

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
---
 klippy/klippy.py  | 10 ++++++----
 klippy/reactor.py | 16 ++++++++++------
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/klippy/klippy.py b/klippy/klippy.py
index 325d6fa35..0204cef7f 100644
--- a/klippy/klippy.py
+++ b/klippy/klippy.py
@@ -165,8 +165,8 @@ class Printer:
             return
         except Exception as e:
             logging.exception("Unhandled exception during connect")
-            self._set_state("Internal error during connect: %s\n%s" % (
-                str(e), message_restart,))
+            self._set_state("Internal error during connect: %s\n%s"
+                            % (str(e), message_restart,))
             return
         try:
             self._set_state(message_ready)
@@ -176,8 +176,8 @@ class Printer:
                 cb()
         except Exception as e:
             logging.exception("Unhandled exception during ready callback")
-            self.invoke_shutdown("Internal error during ready callback: %s" % (
-                str(e),))
+            self.invoke_shutdown("Internal error during ready callback: %s"
+                                 % (str(e),))
     def run(self):
         systime = time.time()
         monotime = self.reactor.monotonic()
@@ -224,6 +224,8 @@ class Printer:
                 cb()
             except:
                 logging.exception("Exception during shutdown handler")
+        logging.info("Reactor garbage collection: %s",
+                     self.reactor.get_gc_stats())
     def invoke_async_shutdown(self, msg):
         self.reactor.register_async_callback(
             (lambda e: self.invoke_shutdown(msg)))
diff --git a/klippy/reactor.py b/klippy/reactor.py
index 0c24b801e..7e41176e8 100644
--- a/klippy/reactor.py
+++ b/klippy/reactor.py
@@ -96,8 +96,10 @@ class SelectReactor:
     def __init__(self, gc_checking=False):
         # Main code
         self._process = False
-        self._check_gc = gc_checking
         self.monotonic = chelper.get_ffi()[1].get_monotonic
+        # Python garbage collection
+        self._check_gc = gc_checking
+        self._last_gc_times = [0., 0., 0.]
         # Timers
         self._timers = []
         self._next_timer = self.NEVER
@@ -110,6 +112,8 @@ class SelectReactor:
         self._g_dispatch = None
         self._greenlets = []
         self._all_greenlets = []
+    def get_gc_stats(self):
+        return tuple(self._last_gc_times)
     # Timers
     def update_timer(self, timer_handler, waketime):
         timer_handler.waketime = waketime
@@ -134,13 +138,13 @@ class SelectReactor:
                 gi = gc.get_count()
                 if gi[0] >= 700:
                     # Reactor looks idle and gc is due - run it
+                    gc_level = 0
                     if gi[1] >= 10:
+                        gc_level = 1
                         if gi[2] >= 10:
-                            gc.collect(2)
-                        else:
-                            gc.collect(1)
-                    else:
-                        gc.collect(0)
+                            gc_level = 2
+                    self._last_gc_times[gc_level] = eventtime
+                    gc.collect(gc_level)
                     return 0.
             return min(1., max(.001, self._next_timer - eventtime))
         self._next_timer = self.NEVER