Frequent callbacks cause slowdowns and eventual AD crash

My Config:
Home Assistant 0.113
AD: 4.0.5
Both installed in their own Python Virtual Env under Ubuntu 19.10

I’m trying to use some counters on my HA Floorplan. I basically want a nicely formatted ‘how long ago’ indicator for each home zone to help me visualise presence and various other things. I found a nice time library - Arrow (https://arrow.readthedocs.io) - which helps alot with time formatting with a nice ‘humanize’ function to show ‘just now’, ‘x seconds ago’, ‘about an hour ago’, etc.
So I setup AD to fire a callback every second in order to update a sensor like this:

import appdaemon.plugins.hass.hassapi as hass
import datetime
import arrow

class PresenceTimeSinceConfirm(hass.Hass):

  def initialize(self):
    now = self.datetime()
    self.timer_handle = self.run_every(self.timer_tick, now, 1)

  def timer_tick(self, kwargs):
    last_changed_time = arrow.get(self.get_state("sensor.zone_presence_last_confirm_{}".format(self.args["zone"])))
    self.set_state("sensor.zone_presence_time_since_confirm_{}".format(self.args["zone"]), state=last_changed_time.humanize())

It works exactly as I want it to. So I next added another app to do a similar job but a countdown this time:

import appdaemon.plugins.hass.hassapi as hass
import datetime
import arrow

class PresenceNextExpireCountdown(hass.Hass):

  def initialize(self):
    now = self.datetime()
    self.handle = self.run_every(self.timer_tick, now, 1)

  def timer_tick(self, kwargs):
    self.set_next_expire_time()

  def set_next_expire_time(self):
    next_expire_time = arrow.get(self.get_state("sensor.zone_presence_next_expire_{}".format(self.args["zone"])))
    diff = next_expire_time - arrow.now()
    if diff.total_seconds() < 0:
      countdown = 0
    else:
      countdown = round(diff.total_seconds())
    self.set_state("sensor.zone_presence_next_expire_countdown_{}".format(self.args["zone"]), state=countdown)

Again does exactly what I want it to. I then rolled them out to multiple zones which then soon leads to a problem:

WARNING AppDaemon: Excessive time spent in utility loop: 2128.0ms, 2125.0ms in check_app_updates(), 3.0ms in other

These will start to come up occasionally but after a while they get more frequent, automations get slower and slower until things like this show:
presence_next_expire_countdown_bedroom: Coroutine () took too long (10 seconds), cancelling the task...

Then if I don’t restart AD memory usage will shoot up and the whole server will need a reboot. I’ve stablised my home automation by reducing the callback frequency to every ten seconds. Much less crashing (although it still happens eventually, perhaps after 48 hours) but it’s now not doing what I want it to.
This issue (https://github.com/AppDaemon/appdaemon/issues/1007) is causing callbacks to stack up endlessly so perhaps it’s related to this issue?
Or is there a fundamental issue in my approach here? I get that a callback should take as little time as possible to execute - to be a quick moment in time thing. And that’s how I thought I’d done this. Originally I had put all zones in one app which of course fell over much quicker with thread starvation quickly a problem. With my current approach I get no thread starvation but just the above issues. I don’t get what is taking so long to execute. 1 second is a long time to basically format a datetime object so what’s going on?