Pi zero - high CPU usage even without any service running

Hi all,

I’m currently setting up a master+satellite rhasspy configuration. The master runs in a proxmox VM with docker container.
For the satellite, I have setup a new PI zero W + Jabra 410 and I have installed rhasspy-satellite.

Even after removing ~/.config/rhasspy directory and starting bin/rhasspy-satellite --profile fr I notice a high CPU usage of the rhasspyserver_hermes (around 50% in average) despite it’s doing nothing (nothing configured at this stage).

Did you notice the same behaviour? Any clue on the way to trace what is being done?

fx

Hi again,

Let me share additional inputs…

I’m running 2.5.0pre and I notice the high CPU usage with both docker container and rhasspy-satellite venv setups.
I’m wondering if there is any way to trace what’s happening in the server to explain this high load.

I also experience ramdom responsiveness of snowboy wakeword and I’m wordering if this could be related. Maybe I have to use personal wake words to improve the speed. I’ll see that later.

Otherwise (and it’s worth writing it), I’m quite happy with the environment (as a former snips user), the configuration flexibility and the ASR results with kaldi :slight_smile:

fx

My Pi Zeros tend to be the same way - about 60-70% CPU usage with only record/play and and snowboy configured. It’s only a single core CPU, so I can understand some more usage (at least compared to my Pi 3B+, which is really responsive and uses only ~5% CPU). But I was surprised at how much CPU it utilized just sitting idle as well.

Maybe @synesthesiam can explain more?

I experience the same issue with my pi zero satellite (tried docker and venv). I don’t have this kind of problems with my pi 3A+ satellite.

I also suspect snowboy to be the origin of the problem. Depending on the wakeword I use, the behavior is different. If I use jarvis.umdl, I have something like 10s latency to get the bip allowing me to say my command. With snowboy or my custom wakeword, it is quick and usable.

Nevertheless, after some time, snowboy doesn’t answer anymore and I need to restart rhasppy.

I am not sure why this is a surprise the difference between a zero and 3 is approx x10? Think that is on a single core.

Not sure why its high with supposedly nothing running but always presumed enough of its level that never even bothered on the zero.
Maybe try just a RTP audio satelite?

Even MagicMirror which is just a webserver really doesn’t run all that well on a zero.

Apparently there are some issues over at Snowboy about this aswell

Going deeper in the investigation with my limited skills…

The high CPU load clearly comes from the web server itself. If I comment out the following (in rhasspyserver_hermes/main.py)
app.run(
host=_ARGS.host,
port=_ARGS.port,
certfile=_ARGS.certfile,
keyfile=_ARGS.keyfile,
loop=_LOOP,
)

Then the load becomes almost neglictible (keep in mind that I have no service running so far)… Obviously, I can no more configure the satellite but as soon as the config is good, I don’t need to have it running all the time :slight_smile:

Any clue why the webserver is taking so much even if there is no client connected?

fx

4 Likes

I have used Snowboy on a Pi Zero with my own code before and had very low resource usage. Additionally, Rhasspy still uses a ton of CPU on the Zero even with different wakeword engines.

Maybe @tuxedo78 is on to something?

Looks very like he has found where the load is and well tracked down.

I can confirm that commenting the same lines on one of my Pi Zeros has reduced CPU usage significantly. My Snowboy wakeword and audio record/play still works great and all seems more responsive as a result.

Going 1 step further…

With the webserver not running (as explained above), I now have my CPU fully eaten by snowboy… Following the advice of @3issa, I move to snowboy wakeword instead of jarvis… and it makes a BIG difference :slight_smile: Faster and more responsive while I have random responsiveness with jarvis.umdl. Thanks for the good tip :slight_smile:

Now I’ll move to using custom wake word in order to try optimizing further…

By the way I don’t observe relevant performance difference between docker and venv, only some difference in Pyaudio config for my Jabra 410. Therefore, I’ll start using only the docker container as I find it easier to manage for auto-start when the Pi zero starts up.

fx

Interesting. I am using a custom wakeword with snowboy (.pmdl) instead of one of their universal models and I have low CPU usage (~10% when the Rhasspy webserver is disabled). Maybe that makes a difference?

There certainly is a difference between pmdl and umdl wakeword. Jarvis.umdl size is 3.5MB, my personnal wakeword size is about 10kB. Jarvis has multiple embedded hotwords that makes it heavier.

Thanks to @tuxedo78 for his useful workaround, that makes a big difference. With 2 personnal wakewords my rpi zero now runs with about 25 % CPU load.

@synesthesiam is it possible to have a way to enable/disable the webserver through commandline for future versions? That would really help for Pi-zero… And by leaving more CPU cycles to wakeword (especially for snowboy), I really think that it should improve wakeword detection performance.

fx

1 Like

+1 for this for 2.5, if possible @synesthesiam. Even an environment variable or command line argument or something that could be included in my docker-compose.yaml to disable the webserver would be amazing. Once I have everything on my Pi Zero satellite configured (using external MQTT), there’s no need for me to be running the web server.

Hello,
Yes, I do not understand this saturation, when:
mosquitto_sub -v -h “localhost” -p 12183 -t “#”

2.5 on Odroid xu4

@synesthesiam do you have any clue on this? should I fill a github issue?

I’ll add an option to rhasspy-voltron to disable the web server. Let’s see if that helps. I’ve also noticed supervisord sometimes leaves behind running Rhasspy processes. Do you see anything after exiting with ps -ef | grep rhasspy?

All my sites (Pi0, Pi3B+ and VM/master) run in Docker and I have never observed processes still running after stop.

Regarding this option, please could you elaborate the exact impacts of disabling the web server? Is it pure configuration stuff (need to change profile.json manually which is quite OK) or does it impact binding with external programs like Jeedom?

Well I checked and disabling web server will completly break Jeedom interface so not an option for me :frowning:

Oh, yeah. Jeedom uses the HTTP and websocket APIs extensively.

Can you tell if the CPU usage is coming specifically from the web server’s Python process?

Yes this is definitely coming from the webserver because even with an install from scratch (deleted .config/rhasspy directory), the load is high (25% on Pi-zero without anything is really unexpected) despite there is no running service.

If you have any clue how to dig into the Quart webserver server, I can give it a try…

Not really. Anyone know a good Python profiler?

well the webserver could be disabled only for sattelites ( but it would be nice to have a way to manage/config the sattelites from the server )

Can confirm that there are no supervisord “left-behind” processes for me either. On my Pi Zero, the CPU usage is coming from a python process, not a rhasspy-* process. So when I comment out the app.run() lines in rhasspyserver_hermes/__main__.py and restart the container, the CPU usage is much more manageable. I don’t use Jeedom and have a purely external MQTT setup, so it has made my satellites much more responsive.

The web server shouldn’t be burning so much CPU, so this may be a bug. I’m worried it’s processing a lot of unnecessary MQTT messages.

Are you using UDP for you wake word audio, or MQTT (the default)?

I’m using UDP on my satellites.

1 Like

Pulled the latest Docker image and the new switch --noweb-server is working great. Thanks @synesthesiam!

Hi @synesthesiam

I confirm that the load comes fro mthe web server. Again, the issue is observed even on a “debugging” PI with no “applicative” service running (everything disabled) : only mqtt and webserver.

I gave a try to cProfile. Here are the ouputs after sorting on tottime

ncalls tottime percall cumtime percall filename:lineno(function)
13598 14.656 0.001 14.656 0.001 {method ‘poll’ of ‘select.epoll’ objects}
12956 3.006 0 5.776 0 pathlib.py:62(parse_parts)
23041 2.755 0 4.726 0 {built-in method posix.stat}
8126 2.301 0 6.399 0.001 :1356(find_spec)
13598 2.241 0 43.216 0.003 base_events.py:1679(_run_once)
13533 2.063 0 15.471 0.001 utils.py:102(observe_changes)
14972 1.77 0 24.293 0.002 {method ‘run’ of ‘Context’ objects}
106918 1.313 0 1.313 0 {built-in method sys.intern}
1273 1.133 0.001 1.133 0.001 {built-in method builtins.compile}
814 1.12 0.001 1.12 0.001 {built-in method marshal.loads}
41464 1.054 0 2.602 0 :56(_path_join)
12952 0.984 0 7.127 0.001 pathlib.py:633(_parse_args)
41464 0.966 0 1.279 0 :58()
12959 0.894 0 1.599 0 pathlib.py:693(str)
14619 0.732 0 1.404 0 base_events.py:707(_call_soon)

I applied the Quickstart/Hello-world guide from Quart website… and this is eating 30% of my CPU. Like my “empty” Rhasspy webserver…

So there is clearly an issue coming from Quart itelf (and not even the way it’s used by Rhasspy). If you are in touch with the Quart dev team, can you report them this issue?

That’s weird.

I also use Jeedom and have no problem except for TTS. I think that @KiboOst 's plugin Jeerhasspy uses HTTP API for the TTS command.
So, I use MQTT in Jeedom for TTS and everything works like a charm.

I have also tried to do TTS with squeezelite and LMS plugin as I use my rhasspy satellite as a squeezebox but that isn’t so elegant…

@synesthesiam I have opened a Github issue against Quart.

From the answer and Quart’s documentation I understand that it’s not recommended (for performance reasons because it’s permanently montoring files for reload) to use app.run() which appears to be used by Rhasspy.

Just my 2 cents but maybe there is area for improvement here?

@synesthesiam

1 step further…

When running Quart hello world I have significantly (divided by 2) my CPU load when upgrading Hypercorn 0.9.5 to 0.10.2 (see my comment in Quart github issue above)
I have built Rhasspy from venv with hypercorn 0.10.2 and I get reduced load :slight_smile:
And when checking in Docker container I see that it’s built with Hypercorn 0.9.5. I tried to pip install --upgrade hypercorn in the Docker container but then it fails when Rhasspy starts up. Is it possible to rebuild Docker images with Hypercorn 0.10.2 instead?

Sorry for polluting the thread again :slight_smile:

Thanks to Quart’s developer, there could be an even better solution by adding the following argument

use_reloader=False

to app.run. I did the modification in my Docker container and the load of my Rhasspy servers completly disappeared. I will report later if I observe any impact on Rhasspy behaviour…

2 Likes

There is already good improvement on this with the last Docker images using Hypercorn 0.10.1. And a dedicated Github issue is opened to follow-up. Therefore I close this topic…

hi,

i experience the same problem with docker build 2.5.1.
May i ask what your load on you pi zero is?

Mine is around 2.00.

I’m running my zero as a sattelite: