summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-06-09 01:05:11 +0200
committerwm4 <wm4@nowhere>2013-06-16 22:05:10 +0200
commit48faa8c3a88e97f78f47131c3cc5a1707a2cec77 (patch)
tree93265ae8b9c3b6002e8fd2d5fc6dbece74e486da
parenta2212ed11e1dd31a1711b730c51cc42a3f51199e (diff)
downloadmpv-48faa8c3a88e97f78f47131c3cc5a1707a2cec77.tar.bz2
mpv-48faa8c3a88e97f78f47131c3cc5a1707a2cec77.tar.xz
cache: attempt to improve slow cache warning
Still sucks. The old cache behavior (before removing the fork code) wasn't great either, though.
-rw-r--r--stream/cache.c61
1 files changed, 35 insertions, 26 deletions
diff --git a/stream/cache.c b/stream/cache.c
index aeb4afe4bf..a3134b7c4a 100644
--- a/stream/cache.c
+++ b/stream/cache.c
@@ -21,14 +21,18 @@
// cache is being slow.
#define CACHE_WAIT_TIME 0.5
-// Time in seconds the cache updates "cached" controls, and retries reading if
-// stream EOF has reached (in case the stream is actually readable again, for
-// example if data has been appended to a file). Note that this timeout will
-// expire all the time if the player is paused.
+// The time the cache sleeps in idle mode. This controls how often the cache
+// retries reading from the stream after EOF has reached (in case the stream is
+// actually readable again, for example if data has been appended to a file).
+// Note that if this timeout is too low, the player will waste too much CPU
+// when player is paused.
#define CACHE_IDLE_SLEEP_TIME 1.0
-// Time in seconds when waiting for prefill
-#define CACHE_PREFILL_SLEEP_TIME 0.2
+// Time in seconds the cache updates "cached" controls. Note that idle mode
+// will block the cache from doing this, and this timeout is honored only if
+// the cache is active.
+#define CACHE_UPDATE_CONTROLS_TIME 0.1
+
#include <stdio.h>
#include <stdlib.h>
@@ -133,26 +137,26 @@ static int cond_timed_wait(pthread_cond_t *cond, pthread_mutex_t *mutex,
// Used by the main thread to wakeup the cache thread, and to wait for the
// cache thread. The cache mutex has to be locked when calling this function.
-// *time should be set to 0 on the first call.
+// *retries should be set to 0 on the first call.
// Returns CACHE_INTERRUPTED if the caller is supposed to abort.
-static int cache_wakeup_and_wait(struct priv *s, double *time)
+static int cache_wakeup_and_wait(struct priv *s, int *retries)
{
- double now = mp_time_sec();
-
- if (!*time)
- *time = now;
+ if (stream_check_interrupt(0))
+ return CACHE_INTERRUPTED;
- if (now - *time >= 0.1) {
+ // Print a "more severe" warning after waiting 1 second and no new data
+ // (time calculation assumes the number of spurious wakeups is very low)
+ if ((*retries) * CACHE_WAIT_TIME >= 1.0) {
+ mp_msg(MSGT_CACHE, MSGL_ERR, "Cache keeps not responding.\n");
+ } else if (*retries > 0) {
mp_msg(MSGT_CACHE, MSGL_WARN,
- "Cache not responding! [performance issue]\n");
- *time = now;
+ "Cache is not responding - slow/stuck network connection?\n");
}
-
- if (stream_check_interrupt(0))
- return CACHE_INTERRUPTED;
+ (*retries) += 1;
pthread_cond_signal(&s->wakeup);
cond_timed_wait(&s->wakeup, &s->mutex, CACHE_WAIT_TIME);
+
return 0;
}
@@ -167,17 +171,16 @@ static void cache_drop_contents(struct priv *s)
// mutex must be held, but is sometimes temporarily dropped
static int cache_read(struct priv *s, unsigned char *buf, int size)
{
- double time = 0;
-
if (size <= 0)
return 0;
+ int retry = 0;
while (s->read_filepos >= s->max_filepos ||
s->read_filepos < s->min_filepos)
{
if (s->eof && s->read_filepos >= s->max_filepos)
return 0;
- if (cache_wakeup_and_wait(s, &time) == CACHE_INTERRUPTED)
+ if (cache_wakeup_and_wait(s, &retry) == CACHE_INTERRUPTED)
return 0;
}
@@ -386,7 +389,7 @@ static void *cache_thread(void *arg)
update_cached_controls(s);
double last = mp_time_sec();
while (s->control != CACHE_CTRL_QUIT) {
- if (mp_time_sec() - last > 0.099) {
+ if (mp_time_sec() - last > CACHE_UPDATE_CONTROLS_TIME) {
update_cached_controls(s);
last = mp_time_sec();
}
@@ -448,7 +451,6 @@ static int cache_seek(stream_t *cache, int64_t pos)
static int cache_control(stream_t *cache, int cmd, void *arg)
{
struct priv *s = cache->priv;
- double time = 0;
int r = STREAM_ERROR;
assert(cmd > 0);
@@ -461,8 +463,9 @@ static int cache_control(stream_t *cache, int cmd, void *arg)
s->control = cmd;
s->control_arg = arg;
+ int retry = 0;
while (s->control != CACHE_CTRL_NONE) {
- if (cache_wakeup_and_wait(s, &time) == CACHE_INTERRUPTED) {
+ if (cache_wakeup_and_wait(s, &retry) == CACHE_INTERRUPTED) {
s->eof = 1;
r = STREAM_UNSUPPORTED;
goto done;
@@ -561,6 +564,8 @@ int stream_cache_init(stream_t *cache, stream_t *stream, int64_t size,
// wait until cache is filled at least prefill_init %
for (;;) {
+ if (stream_check_interrupt(0))
+ return 0;
int64_t fill;
int idle;
if (stream_control(s->cache, STREAM_CTRL_GET_CACHE_FILL, &fill) < 0)
@@ -573,8 +578,12 @@ int stream_cache_init(stream_t *cache, stream_t *stream, int64_t size,
break;
if (idle)
break; // file is smaller than prefill size
- if (stream_check_interrupt(CACHE_PREFILL_SLEEP_TIME * 1000))
- return 0;
+ // Wake up if the cache is done reading some data (or on timeout/abort)
+ pthread_mutex_lock(&s->mutex);
+ s->control = CACHE_CTRL_PING;
+ pthread_cond_signal(&s->wakeup);
+ cache_wakeup_and_wait(s, &(int){0});
+ pthread_mutex_unlock(&s->mutex);
}
mp_msg(MSGT_CACHE, MSGL_STATUS, "\n");
return 1;