Skip to content

Commit

Permalink
Disable garbage collector when reading sensors to improve timing
Browse files Browse the repository at this point in the history
  • Loading branch information
amotl committed Jul 21, 2019
1 parent aaa4a01 commit a62b193
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 5 deletions.
3 changes: 2 additions & 1 deletion CHANGES.rst
Expand Up @@ -57,8 +57,9 @@ Development
- Prettify logging
- Optionally start modeserver, defaulting to true
- Add basic HTTP API subsystem. Thanks `@vkuhlen`_ and `@DieDiren`_.
- Add ``make wifi-ap`` command for starting the access point interactively
- Add ``make provide-wifi`` command for starting the access point interactively
- Start WiFi in STA_AP mode by default
- Disable garbage collector when reading sensors to improve timing


2019-06-22 0.5.1
Expand Down
15 changes: 11 additions & 4 deletions terkin/datalogger.py
Expand Up @@ -13,7 +13,7 @@
from terkin.network import SystemWiFiMetrics
from terkin.sensor import SensorManager, AbstractSensor
from terkin.sensor.system import SystemMemoryFree, SystemTemperature, SystemBatteryLevel, SystemUptime
from terkin.util import dformat
from terkin.util import dformat, gc_disabled

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -274,14 +274,21 @@ def read_sensors(self):
sensorname = sensor.__class__.__name__
log.info('Reading sensor port "%s"', sensorname)

# Read sensor port.
try:
reading = sensor.read()

# Disable garbage collector to guarantee reasonable
# realtime behavior before invoking sensor reading.
with gc_disabled():
reading = sensor.read()
if reading is None or reading is AbstractSensor.SENSOR_NOT_INITIALIZED:
continue
data.update(reading)

except:
log.exception('Reading sensor "%s" failed', sensorname)
except Exception as ex:
# Because of the ``gc_disabled`` context manager used above,
# the propagation of exceptions has to be tweaked like that.
log.exc(ex, 'Reading sensor "%s" failed', sensorname)

self.device.watchdog.feed()

Expand Down
32 changes: 32 additions & 0 deletions terkin/util.py
Expand Up @@ -144,3 +144,35 @@ def flatten(input_object, separator='_'):
https://github.com/evamayerova/python-flatten/blob/master/flatten_to_dict/flatten_to_dict.py
"""
return _flatten(input_object, key_prefix="", separator=separator)


class gc_disabled:
"""
Context manager to temporarily disable the garbage collector.
Please be aware this piece does not account for thread safety in any way.
https://community.hiveeyes.org/t/timing-things-on-micropython-for-esp32/2329
https://bugs.python.org/issue31356
Synopsis::
with gc_disabled():
# Do something that needs realtime guarantees
# such as a pair trade, robotic braking, etc.
run_some_timing_critical_stuff()
"""

def __enter__(self):
import gc
gc.disable()
return self

def __exit__(self, *exc_details):
# exc_info: (<class 'NameError'>, NameError("name 'asdf' is not defined",), None)
received_exc = exc_details[0] is not None
import gc
gc.enable()
if received_exc:
raise exc_details[1]

0 comments on commit a62b193

Please sign in to comment.