From: Jaroslav Kysela Date: Mon, 4 Jan 2016 16:09:45 +0000 (+0100) Subject: timeshift: add 'Fit to RAM' option' to reduce disk I/O X-Git-Tag: v4.2.1~1231 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3b59d92534edf7ddaca34d0d2ebdefa9ae8ecaee;p=thirdparty%2Ftvheadend.git timeshift: add 'Fit to RAM' option' to reduce disk I/O --- diff --git a/src/timeshift.c b/src/timeshift.c index 37fac3bd5..bbc2eebe4 100644 --- a/src/timeshift.c +++ b/src/timeshift.c @@ -224,6 +224,14 @@ const idclass_t timeshift_conf_class = { .name = N_("RAM only"), .off = offsetof(timeshift_conf_t, ram_only), }, + { + .type = PT_BOOL, + .id = "ram_fit", + .name = N_("Fit to RAM (cut rewind)"), + .desc = N_("If possible, maintain the timeshift data in the server memory only. " + "This may reduce the amount of allowed rewind time."), + .off = offsetof(timeshift_conf_t, ram_fit), + }, {} } }; @@ -431,6 +439,8 @@ streaming_target_t *timeshift_create ts->ref_time = 0; ts->seek.file = NULL; ts->seek.frame = NULL; + ts->ram_segments = 0; + ts->file_segments = 0; for (i = 0; i < TIMESHIFT_BACKLOG_MAX; i++) TAILQ_INIT(&ts->backlog[i]); pthread_mutex_init(&ts->state_mutex, NULL); diff --git a/src/timeshift.h b/src/timeshift.h index baa2e932f..49b2afb20 100644 --- a/src/timeshift.h +++ b/src/timeshift.h @@ -35,6 +35,7 @@ typedef struct timeshift_conf { uint64_t ram_segment_size; uint64_t total_ram_size; int ram_only; + int ram_fit; } timeshift_conf_t; extern struct timeshift_conf timeshift_conf; diff --git a/src/timeshift/private.h b/src/timeshift/private.h index bcd301213..2f8fb13be 100644 --- a/src/timeshift/private.h +++ b/src/timeshift/private.h @@ -129,6 +129,9 @@ typedef struct timeshift { timeshift_file_list_t files; ///< List of files + int ram_segments; ///< Count of segments in RAM + int file_segments; ///< Count of segments in files + int vididx; ///< Index of (current) video stream } timeshift_t; diff --git a/src/timeshift/timeshift_filemgr.c b/src/timeshift/timeshift_filemgr.c index a65cda768..2f0236bb6 100644 --- a/src/timeshift/timeshift_filemgr.c +++ b/src/timeshift/timeshift_filemgr.c @@ -205,6 +205,13 @@ void timeshift_filemgr_remove ts->id, tsf->time, (int64_t)tsf->size, (int64_t)tsf->ram_size); } TAILQ_REMOVE(&ts->files, tsf, link); + if (tsf->path) { + assert(ts->file_segments > 0); + ts->file_segments--; + } else { + assert(ts->ram_segments > 0); + ts->ram_segments--; + } atomic_dec_u64(×hift_total_size, tsf->size); if (tsf->ram) atomic_dec_u64(×hift_total_ram_size, tsf->size); @@ -310,18 +317,31 @@ timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int64_t start_time ) tvhtrace("timeshift", "ts %d RAM total %"PRId64" requested %"PRId64" segment %"PRId64, ts->id, atomic_pre_add_u64(×hift_total_ram_size, 0), timeshift_conf.ram_size, timeshift_conf.ram_segment_size); - if (timeshift_conf.ram_size >= 8*1024*1024 && - atomic_pre_add_u64(×hift_total_ram_size, 0) < - timeshift_conf.ram_size + (timeshift_conf.ram_segment_size / 2)) { - tsf_tmp = timeshift_filemgr_file_init(ts, start_time); - tsf_tmp->ram_size = MIN(16*1024*1024, timeshift_conf.ram_segment_size); - tsf_tmp->ram = malloc(tsf_tmp->ram_size); - if (!tsf_tmp->ram) { - free(tsf_tmp); - tsf_tmp = NULL; + while (1) { + if (timeshift_conf.ram_size >= 8*1024*1024 && + atomic_pre_add_u64(×hift_total_ram_size, 0) < + timeshift_conf.ram_size + (timeshift_conf.ram_segment_size / 2)) { + tsf_tmp = timeshift_filemgr_file_init(ts, start_time); + tsf_tmp->ram_size = MIN(16*1024*1024, timeshift_conf.ram_segment_size); + tsf_tmp->ram = malloc(tsf_tmp->ram_size); + if (!tsf_tmp->ram) { + free(tsf_tmp); + tsf_tmp = NULL; + } else { + tvhtrace("timeshift", "ts %d create RAM segment with %"PRId64" bytes (time %"PRId64")", + ts->id, tsf_tmp->ram_size, start_time); + ts->ram_segments++; + } + break; } else { - tvhtrace("timeshift", "ts %d create RAM segment with %"PRId64" bytes (time %"PRId64")", - ts->id, tsf_tmp->ram_size, start_time); + tsf_hd = TAILQ_FIRST(&ts->files); + if (timeshift_conf.ram_fit && tsf_hd && !tsf_hd->refcount && + tsf_hd->ram && ts->file_segments == 0) { + tvhtrace("timeshift", "ts %d remove RAM segment %"PRId64" (fit)", ts->id, tsf_hd->time); + timeshift_filemgr_remove(ts, tsf_hd, 0); + } else { + break; + } } } @@ -340,6 +360,7 @@ timeshift_file_t *timeshift_filemgr_get ( timeshift_t *ts, int64_t start_time ) tsf_tmp = timeshift_filemgr_file_init(ts, start_time); tsf_tmp->wfd = fd; tsf_tmp->path = strdup(path); + ts->file_segments++; } }