Hi,

TL;DR: setting QT_NO_GLIB may make QT event delivery more efficient which could
help reduce latencies.

        -

I'm using mixxx master on Debian 8.6. While checking for possible underrun
causes, I noticed that an strace of the portaudio callback thread shows many
writes which appear unnecessary:

poll([{fd=56, events=POLLOUT|POLLERR|POLLNVAL}], 1, 11) = 1 ([{fd=56,
revents=POLLOUT}])
ioctl(56, SNDRV_PCM_IOCTL_STATUS, 0x7fd3153d4b20) = 0
write(3, "\1\0\0\0\0\0\0\0", 8)         = 8
write(3, "\1\0\0\0\0\0\0\0", 8)         = 8
ioctl(56, SNDRV_PCM_IOCTL_STATUS, 0x7fd3153d4b20) = 0
poll([{fd=56, events=POLLOUT|POLLERR|POLLNVAL}], 1, 11) = 1 ([{fd=56,
revents=POLLOUT}])
ioctl(56, SNDRV_PCM_IOCTL_STATUS, 0x7fd3153d4b20) = 0
write(3, "\1\0\0\0\0\0\0\0", 8)         = 8
write(3, "\1\0\0\0\0\0\0\0", 8)         = 8
ioctl(56, SNDRV_PCM_IOCTL_STATUS, 0x7fd3153d4b20) = 0
poll([{fd=56, events=POLLOUT|POLLERR|POLLNVAL}], 1, 11) = 1 ([{fd=56,
revents=POLLOUT}])
ioctl(56, SNDRV_PCM_IOCTL_STATUS, 0x7fd3153d4b20) = 0
write(3, "\1\0\0\0\0\0\0\0", 8)         = 8
write(3, "\1\0\0\0\0\0\0\0", 8)         = 8
write(3, "\1\0\0\0\0\0\0\0", 8)         = 8
write(3, "\1\0\0\0\0\0\0\0", 8)         = 8
futex(0x2d9f4dc, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, 0x2d9f4b0, 2230) = 1
futex(0x2d9f4b0, FUTEX_WAKE_PRIVATE, 1) = 1
ioctl(56, SNDRV_PCM_IOCTL_STATUS, 0x7fd3153d4b20) = 0

turns out that these are caused by glib g_wakeup_signal() writes to the glib
eventfd caused by postEvent()s because QT defaults to QEventDispatcherGlib. See
bottom of the email for some exemplary stack traces.

Also, the receiving side (main thread) needs to read all these off the eventfd
(ultimately happening in g_wakeup_acknowledge()).

I _think_ that glib could do better and avoid notifications altogether unless
the receiving thread is actually polling and reducing the eventfd notifications
to just one, but nevertheless there seems to be an easy way out: Instruct QT not
to use the glib event loop by setting

        QT_NO_GLIB=whatever

This instructs QT to fall back to QEventDispatcherUNIX which should be less
efficient for a large number of file descriptors, but appears to be
significantly more efficient in handling QT events: Only one event write is
generated to wake up poll as can be seen in the strace of the portaudio callback
thread:

poll([{fd=73, events=POLLOUT|POLLERR|POLLNVAL}], 1, 11) = 1 ([{fd=73,
revents=POLLOUT}])
ioctl(73, SNDRV_PCM_IOCTL_STATUS, 0x7f72abd81b30) = 0
ioctl(73, SNDRV_PCM_IOCTL_STATUS, 0x7f72abd81b30) = 0
poll([{fd=73, events=POLLOUT|POLLERR|POLLNVAL}], 1, 11) = 1 ([{fd=73,
revents=POLLOUT}])
ioctl(73, SNDRV_PCM_IOCTL_STATUS, 0x7f72abd81b30) = 0
write(4, "\0", 1)                       = 1
ioctl(73, SNDRV_PCM_IOCTL_STATUS, 0x7f72abd81b30) = 0
poll([{fd=73, events=POLLOUT|POLLERR|POLLNVAL}], 1, 11) = 1 ([{fd=73,
revents=POLLOUT}])
ioctl(73, SNDRV_PCM_IOCTL_STATUS, 0x7f72abd81b30) = 0
futex(0x19315ec, FUTEX_CMP_REQUEUE_PRIVATE, 1, 2147483647, 0x19315c0, 730) = 1
futex(0x19315c0, FUTEX_WAKE_PRIVATE, 1) = 1
ioctl(73, SNDRV_PCM_IOCTL_STATUS, 0x7f72abd81b30) = 0


This won't make that much of a difference, but reducing the number of syscalls
is always a good idea, so I wonder if setting QT_NO_GLIB should be recommended?

Cheers, Nils

        -




(gdb) break write
Breakpoint 1 at 0x7ffb7a767bf0: write. (2 locations)
(gdb) cont
Continuing.

Breakpoint 1, write () at ../sysdeps/unix/syscall-template.S:81
81      ../sysdeps/unix/syscall-template.S: No such file or directory.
(gdb) bt
#0  write () at ../sysdeps/unix/syscall-template.S:81
#1  0x00007ffb7b2e5ef2 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#2  0x00007ffb7ef0b81e in QCoreApplication::postEvent(QObject*, QEvent*, int) ()
   from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#3  0x00007ffb7ef1ca44 in QMetaObject::activate(QObject*, QMetaObject const*,
int, void**) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#4  0x00000000004fb547 in ControlDoublePrivate::valueChanged (
    this=this@entry=0x31e38e0, _t1=_t1@entry=3, _t2=_t2@entry=0x39ce2d0)
    at lin64_build/control/moc_control.cc:101
#5  0x00000000004ea565 in setInner (pSender=0x39ce2d0, value=3, this=0x31e38e0)
    at src/control/control.cpp:203
#6  ControlDoublePrivate::set (this=0x31e38e0, value=3, pSender=0x39ce2d0)
    at src/control/control.cpp:190
#7  0x0000000000b07be2 in set (v=<optimized out>, this=<optimized out>)
    at src/control/controlproxy.h:78
#8  SoundDevicePortAudio::callbackProcessClkRef (this=0x39ce190,
framesPerBuffer=1024,
    out=0x3c3952f0, in=0x0, timeInfo=<optimized out>, statusFlags=<optimized 
out>)
    at src/soundio/sounddeviceportaudio.cpp:916
#9  0x00007ffb82094f04 in NonAdaptingProcess (bp=bp@entry=0x3bba98e8,
    streamCallbackResult=streamCallbackResult@entry=0x7ffb0f971d08,
    hostInputChannels=0x0, hostOutputChannels=0x2bf24b80,
    framesToProcess=<optimized out>) at src/common/pa_process.c:873
#10 0x00007ffb82096ec0 in PaUtil_EndBufferProcessing (bp=bp@entry=0x3bba98e8,
    streamCallbackResult=streamCallbackResult@entry=0x7ffb0f971d08)
    at src/common/pa_process.c:1585
#11 0x00007ffb8209e37e in CallbackThreadFunc (userData=0x3bba9880)
    at src/hostapi/alsa/pa_linux_alsa.c:4346
#12 0x00007ffb7cb2b0a4 in start_thread (arg=0x7ffb0f972700) at 
pthread_create.c:309
#13 0x00007ffb7a77462d in clone () at 
../sysdeps/unix/sysv/linux/x86_64/clone.S:111
(gdb) cont
Continuing.

Breakpoint 1, write () at ../sysdeps/unix/syscall-template.S:81
81      in ../sysdeps/unix/syscall-template.S
(gdb) bt
#0  write () at ../sysdeps/unix/syscall-template.S:81
#1  0x00007ffb7b2e5ef2 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#2  0x00007ffb7ef0b81e in QCoreApplication::postEvent(QObject*, QEvent*, int) ()
   from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#3  0x00007ffb7ef1ca44 in QMetaObject::activate(QObject*, QMetaObject const*,
int, void**) () from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#4  0x00000000004fb547 in ControlDoublePrivate::valueChanged (
    this=this@entry=0x3228840, _t1=_t1@entry=0.82023751735687256,
    _t2=_t2@entry=0x3228740) at lin64_build/control/moc_control.cc:101
#5  0x00000000004ea565 in setInner (pSender=0x3228740, 
value=0.82023751735687256,
    this=0x3228840) at src/control/control.cpp:203
#6  ControlDoublePrivate::set (this=0x3228840,
value=value@entry=0.82023751735687256,
    pSender=0x3228740) at src/control/control.cpp:190
#7  0x00000000007f6b09 in set (value=0.82023751735687256, this=<optimized out>)
    at src/control/controlobject.h:94
#8  EngineVuMeter::process (this=0x3224a90, pIn=<optimized out>, 
iBufferSize=2048)
    at src/engine/enginevumeter.cpp:86
#9  0x00000000007f0a03 in EngineMaster::process (this=0x325ecb0,
    iBufferSize=iBufferSize@entry=2048) at src/engine/enginemaster.cpp:523
#10 0x0000000000b0a2eb in SoundManager::onDeviceOutputCallback (this=<optimized
out>,
    iFramesPerBuffer=iFramesPerBuffer@entry=1024) at
src/soundio/soundmanager.cpp:547
#11 0x0000000000b07c76 in SoundDevicePortAudio::callbackProcessClkRef
(this=0x39ce190,
    framesPerBuffer=1024, out=0x3c3952f0, in=<optimized out>,
timeInfo=<optimized out>,
    statusFlags=<optimized out>) at src/soundio/sounddeviceportaudio.cpp:947
#12 0x00007ffb82094f04 in NonAdaptingProcess (bp=bp@entry=0x3bba98e8,
    streamCallbackResult=streamCallbackResult@entry=0x7ffb0f971d08,
    hostInputChannels=0x0, hostOutputChannels=0x2bf24b80,
    framesToProcess=<optimized out>) at src/common/pa_process.c:873
#13 0x00007ffb82096ec0 in PaUtil_EndBufferProcessing (bp=bp@entry=0x3bba98e8,
    streamCallbackResult=streamCallbackResult@entry=0x7ffb0f971d08)
    at src/common/pa_process.c:1585
#14 0x00007ffb8209e37e in CallbackThreadFunc (userData=0x3bba9880)
    at src/hostapi/alsa/pa_linux_alsa.c:4346
#15 0x00007ffb7cb2b0a4 in start_thread (arg=0x7ffb0f972700) at 
pthread_create.c:309
#16 0x00007ffb7a77462d in clone () at 
../sysdeps/unix/sysv/linux/x86_64/clone.S:111

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Get Mixxx, the #1 Free MP3 DJ Mixing software Today
http://mixxx.org


Mixxx-devel mailing list
Mixxx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mixxx-devel

Reply via email to