mpd/src/notify.hxx

54 lines
1.3 KiB
C++
Raw Normal View History

/*
2013-01-10 10:44:04 +01:00
* Copyright (C) 2003-2013 The Music Player Daemon Project
* http://www.musicpd.org
notify the decoder instead of polling 100hz When the decoder process is faster than the player process, all decodedd buffers are full at some point in time. The decoder has to wait for buffers to become free (finished playing). It used to do this by polling the buffer status 100 times a second. This generates a lot of unnecessary CPU wakeups. This patch adds a way for the player process to notify the decoder process that it may continue its work. We could use pthread_cond for that, unfortunately inter-process mutexes/conds are not supported by some kernels (Linux), so we cannot use this light-weight method until mpd moves to using threads instead of processes. The other method would be semaphores, which historically are global resources with a unique name; this historic API is cumbersome, and I wanted to avoid it. I came up with a quite naive solution for now: I create an anonymous pipe with pipe(), and the decoder process reads on that pipe. Until the player process sends data on it as a signal, the decoder process blocks. This can be optimized in a number of ways: - if the decoder process is still working (instead of waiting for buffers), we could save the write() system call, since there is nobody waiting for the notification. [ew: I tried this using a counter in shared memory, didn't help] - the pipe buffer will be full at some point, when the decoder thread is too slow. For this reason, the writer side of the pipe is non-blocking, and mpd can ignore the resulting EWOULDBLOCK. - since we have shared memory, we could check whether somebody is actually waiting without a context switch, and we could just not write the notification byte. [ew: tried same method/result as first point above] - if there is already a notification in the pipe, we could also not write another one. [ew: tried same method/result as first/third points above] - the decoder will only consume 64 bytes at a time. If the pipe buffer is full, this will result in a lot of read() invocations. This does not hurt badly, but on a heavily loaded system, this might add a little bit more load. The preceding optimizations however are able eliminate the this. - finally, we should use another method for inter process notifications - maybe kill() or just make mpd use threads, finally. In spite of all these possibilities to optimize this code further, this pipe notification trick is faster than the 100 Hz poll. On my machine, it reduced the number of wakeups to less than 30%. git-svn-id: https://svn.musicpd.org/mpd/trunk@7215 09075e82-0dd4-0310-85a5-a0d7c8717e4f
2008-03-26 11:38:54 +01:00
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
notify the decoder instead of polling 100hz When the decoder process is faster than the player process, all decodedd buffers are full at some point in time. The decoder has to wait for buffers to become free (finished playing). It used to do this by polling the buffer status 100 times a second. This generates a lot of unnecessary CPU wakeups. This patch adds a way for the player process to notify the decoder process that it may continue its work. We could use pthread_cond for that, unfortunately inter-process mutexes/conds are not supported by some kernels (Linux), so we cannot use this light-weight method until mpd moves to using threads instead of processes. The other method would be semaphores, which historically are global resources with a unique name; this historic API is cumbersome, and I wanted to avoid it. I came up with a quite naive solution for now: I create an anonymous pipe with pipe(), and the decoder process reads on that pipe. Until the player process sends data on it as a signal, the decoder process blocks. This can be optimized in a number of ways: - if the decoder process is still working (instead of waiting for buffers), we could save the write() system call, since there is nobody waiting for the notification. [ew: I tried this using a counter in shared memory, didn't help] - the pipe buffer will be full at some point, when the decoder thread is too slow. For this reason, the writer side of the pipe is non-blocking, and mpd can ignore the resulting EWOULDBLOCK. - since we have shared memory, we could check whether somebody is actually waiting without a context switch, and we could just not write the notification byte. [ew: tried same method/result as first point above] - if there is already a notification in the pipe, we could also not write another one. [ew: tried same method/result as first/third points above] - the decoder will only consume 64 bytes at a time. If the pipe buffer is full, this will result in a lot of read() invocations. This does not hurt badly, but on a heavily loaded system, this might add a little bit more load. The preceding optimizations however are able eliminate the this. - finally, we should use another method for inter process notifications - maybe kill() or just make mpd use threads, finally. In spite of all these possibilities to optimize this code further, this pipe notification trick is faster than the 100 Hz poll. On my machine, it reduced the number of wakeups to less than 30%. git-svn-id: https://svn.musicpd.org/mpd/trunk@7215 09075e82-0dd4-0310-85a5-a0d7c8717e4f
2008-03-26 11:38:54 +01:00
*/
2013-01-10 10:44:04 +01:00
#ifndef MPD_NOTIFY_HXX
#define MPD_NOTIFY_HXX
notify the decoder instead of polling 100hz When the decoder process is faster than the player process, all decodedd buffers are full at some point in time. The decoder has to wait for buffers to become free (finished playing). It used to do this by polling the buffer status 100 times a second. This generates a lot of unnecessary CPU wakeups. This patch adds a way for the player process to notify the decoder process that it may continue its work. We could use pthread_cond for that, unfortunately inter-process mutexes/conds are not supported by some kernels (Linux), so we cannot use this light-weight method until mpd moves to using threads instead of processes. The other method would be semaphores, which historically are global resources with a unique name; this historic API is cumbersome, and I wanted to avoid it. I came up with a quite naive solution for now: I create an anonymous pipe with pipe(), and the decoder process reads on that pipe. Until the player process sends data on it as a signal, the decoder process blocks. This can be optimized in a number of ways: - if the decoder process is still working (instead of waiting for buffers), we could save the write() system call, since there is nobody waiting for the notification. [ew: I tried this using a counter in shared memory, didn't help] - the pipe buffer will be full at some point, when the decoder thread is too slow. For this reason, the writer side of the pipe is non-blocking, and mpd can ignore the resulting EWOULDBLOCK. - since we have shared memory, we could check whether somebody is actually waiting without a context switch, and we could just not write the notification byte. [ew: tried same method/result as first point above] - if there is already a notification in the pipe, we could also not write another one. [ew: tried same method/result as first/third points above] - the decoder will only consume 64 bytes at a time. If the pipe buffer is full, this will result in a lot of read() invocations. This does not hurt badly, but on a heavily loaded system, this might add a little bit more load. The preceding optimizations however are able eliminate the this. - finally, we should use another method for inter process notifications - maybe kill() or just make mpd use threads, finally. In spite of all these possibilities to optimize this code further, this pipe notification trick is faster than the 100 Hz poll. On my machine, it reduced the number of wakeups to less than 30%. git-svn-id: https://svn.musicpd.org/mpd/trunk@7215 09075e82-0dd4-0310-85a5-a0d7c8717e4f
2008-03-26 11:38:54 +01:00
2013-01-10 10:44:04 +01:00
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
notify the decoder instead of polling 100hz When the decoder process is faster than the player process, all decodedd buffers are full at some point in time. The decoder has to wait for buffers to become free (finished playing). It used to do this by polling the buffer status 100 times a second. This generates a lot of unnecessary CPU wakeups. This patch adds a way for the player process to notify the decoder process that it may continue its work. We could use pthread_cond for that, unfortunately inter-process mutexes/conds are not supported by some kernels (Linux), so we cannot use this light-weight method until mpd moves to using threads instead of processes. The other method would be semaphores, which historically are global resources with a unique name; this historic API is cumbersome, and I wanted to avoid it. I came up with a quite naive solution for now: I create an anonymous pipe with pipe(), and the decoder process reads on that pipe. Until the player process sends data on it as a signal, the decoder process blocks. This can be optimized in a number of ways: - if the decoder process is still working (instead of waiting for buffers), we could save the write() system call, since there is nobody waiting for the notification. [ew: I tried this using a counter in shared memory, didn't help] - the pipe buffer will be full at some point, when the decoder thread is too slow. For this reason, the writer side of the pipe is non-blocking, and mpd can ignore the resulting EWOULDBLOCK. - since we have shared memory, we could check whether somebody is actually waiting without a context switch, and we could just not write the notification byte. [ew: tried same method/result as first point above] - if there is already a notification in the pipe, we could also not write another one. [ew: tried same method/result as first/third points above] - the decoder will only consume 64 bytes at a time. If the pipe buffer is full, this will result in a lot of read() invocations. This does not hurt badly, but on a heavily loaded system, this might add a little bit more load. The preceding optimizations however are able eliminate the this. - finally, we should use another method for inter process notifications - maybe kill() or just make mpd use threads, finally. In spite of all these possibilities to optimize this code further, this pipe notification trick is faster than the 100 Hz poll. On my machine, it reduced the number of wakeups to less than 30%. git-svn-id: https://svn.musicpd.org/mpd/trunk@7215 09075e82-0dd4-0310-85a5-a0d7c8717e4f
2008-03-26 11:38:54 +01:00
struct notify {
2013-01-10 10:44:04 +01:00
Mutex mutex;
Cond cond;
bool pending;
notify the decoder instead of polling 100hz When the decoder process is faster than the player process, all decodedd buffers are full at some point in time. The decoder has to wait for buffers to become free (finished playing). It used to do this by polling the buffer status 100 times a second. This generates a lot of unnecessary CPU wakeups. This patch adds a way for the player process to notify the decoder process that it may continue its work. We could use pthread_cond for that, unfortunately inter-process mutexes/conds are not supported by some kernels (Linux), so we cannot use this light-weight method until mpd moves to using threads instead of processes. The other method would be semaphores, which historically are global resources with a unique name; this historic API is cumbersome, and I wanted to avoid it. I came up with a quite naive solution for now: I create an anonymous pipe with pipe(), and the decoder process reads on that pipe. Until the player process sends data on it as a signal, the decoder process blocks. This can be optimized in a number of ways: - if the decoder process is still working (instead of waiting for buffers), we could save the write() system call, since there is nobody waiting for the notification. [ew: I tried this using a counter in shared memory, didn't help] - the pipe buffer will be full at some point, when the decoder thread is too slow. For this reason, the writer side of the pipe is non-blocking, and mpd can ignore the resulting EWOULDBLOCK. - since we have shared memory, we could check whether somebody is actually waiting without a context switch, and we could just not write the notification byte. [ew: tried same method/result as first point above] - if there is already a notification in the pipe, we could also not write another one. [ew: tried same method/result as first/third points above] - the decoder will only consume 64 bytes at a time. If the pipe buffer is full, this will result in a lot of read() invocations. This does not hurt badly, but on a heavily loaded system, this might add a little bit more load. The preceding optimizations however are able eliminate the this. - finally, we should use another method for inter process notifications - maybe kill() or just make mpd use threads, finally. In spite of all these possibilities to optimize this code further, this pipe notification trick is faster than the 100 Hz poll. On my machine, it reduced the number of wakeups to less than 30%. git-svn-id: https://svn.musicpd.org/mpd/trunk@7215 09075e82-0dd4-0310-85a5-a0d7c8717e4f
2008-03-26 11:38:54 +01:00
#if !defined(WIN32) && !defined(__NetBSD__)
2013-01-10 10:44:04 +01:00
constexpr
#endif
notify():pending(false) {}
/**
* Wait for a notification. Return immediately if we have already
* been notified since we last returned from notify_wait().
*/
void Wait();
/**
* Notify the thread. This function never blocks.
*/
void Signal();
/**
* Clears a pending notification.
*/
void Clear();
};
2010-08-19 11:03:53 +02:00
notify the decoder instead of polling 100hz When the decoder process is faster than the player process, all decodedd buffers are full at some point in time. The decoder has to wait for buffers to become free (finished playing). It used to do this by polling the buffer status 100 times a second. This generates a lot of unnecessary CPU wakeups. This patch adds a way for the player process to notify the decoder process that it may continue its work. We could use pthread_cond for that, unfortunately inter-process mutexes/conds are not supported by some kernels (Linux), so we cannot use this light-weight method until mpd moves to using threads instead of processes. The other method would be semaphores, which historically are global resources with a unique name; this historic API is cumbersome, and I wanted to avoid it. I came up with a quite naive solution for now: I create an anonymous pipe with pipe(), and the decoder process reads on that pipe. Until the player process sends data on it as a signal, the decoder process blocks. This can be optimized in a number of ways: - if the decoder process is still working (instead of waiting for buffers), we could save the write() system call, since there is nobody waiting for the notification. [ew: I tried this using a counter in shared memory, didn't help] - the pipe buffer will be full at some point, when the decoder thread is too slow. For this reason, the writer side of the pipe is non-blocking, and mpd can ignore the resulting EWOULDBLOCK. - since we have shared memory, we could check whether somebody is actually waiting without a context switch, and we could just not write the notification byte. [ew: tried same method/result as first point above] - if there is already a notification in the pipe, we could also not write another one. [ew: tried same method/result as first/third points above] - the decoder will only consume 64 bytes at a time. If the pipe buffer is full, this will result in a lot of read() invocations. This does not hurt badly, but on a heavily loaded system, this might add a little bit more load. The preceding optimizations however are able eliminate the this. - finally, we should use another method for inter process notifications - maybe kill() or just make mpd use threads, finally. In spite of all these possibilities to optimize this code further, this pipe notification trick is faster than the 100 Hz poll. On my machine, it reduced the number of wakeups to less than 30%. git-svn-id: https://svn.musicpd.org/mpd/trunk@7215 09075e82-0dd4-0310-85a5-a0d7c8717e4f
2008-03-26 11:38:54 +01:00
#endif