commit fef41d030545862c9cb2018f72297e33018c791b
parent 98e0b77a1a543252307dffb4a32abb2f852c8618
Author: Hans Petter Selasky <hps@selasky.org>
Date: Thu, 3 Oct 2019 20:15:05 +0200
Reduce number of system calls for ALSA MIDI by implementing proper polling.
Use polling with a timeout instead of polling for MIDI events thousands of
times per second with no timeout. This reduces the CPU usage for ZynAddSubFX.
Signed-off-by: Hans Petter Selasky <hps@selasky.org>
Diffstat:
1 file changed, 21 insertions(+), 7 deletions(-)
diff --git a/src/Nio/AlsaEngine.cpp b/src/Nio/AlsaEngine.cpp
@@ -14,6 +14,7 @@
#include <stdlib.h>
#include <iostream>
#include <cmath>
+#include <poll.h>
#include "../Misc/Util.h"
#include "../Misc/Config.h"
@@ -105,17 +106,29 @@ void *AlsaEngine::_MidiThread(void *arg)
void *AlsaEngine::MidiThread(void)
{
snd_seq_event_t *event;
- MidiEvent ev;
+ MidiEvent ev = {};
+ struct pollfd pfd[4 /* XXX 1 should be enough */];
+ int error;
+
set_realtime();
while(1) {
if(midi.exiting)
break;
- if(snd_seq_event_input_pending(midi.handle, 1) <= 0) {
- usleep(10);
- continue;
- }
- if(snd_seq_event_input(midi.handle, &event) < 0)
+ error = snd_seq_poll_descriptors(midi.handle, pfd, 4, POLLIN);
+ if(error <= 0)
break;
+ error = poll(pfd, error, 1000 /* ms */);
+ if(error < 0) {
+ if(errno == EAGAIN || errno == EINTR)
+ continue;
+ break;
+ }
+ error = snd_seq_event_input(midi.handle, &event);
+ if (error < 0) {
+ if(error == -EAGAIN || error == -EINTR)
+ continue;
+ break;
+ }
//ensure ev is empty
ev.channel = 0;
ev.num = 0;
@@ -228,7 +241,8 @@ bool AlsaEngine::openMidi()
int alsaport;
midi.handle = NULL;
- if(snd_seq_open(&midi.handle, "default", SND_SEQ_OPEN_INPUT, 0) != 0)
+ if(snd_seq_open(&midi.handle, "default",
+ SND_SEQ_OPEN_INPUT, SND_SEQ_NONBLOCK) != 0)
return false;
string clientname = "ZynAddSubFX";