]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
timeshift: add 'Fit to RAM' option' to reduce disk I/O
authorJaroslav Kysela <perex@perex.cz>
Mon, 4 Jan 2016 16:09:45 +0000 (17:09 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 4 Jan 2016 16:09:45 +0000 (17:09 +0100)
src/timeshift.c
src/timeshift.h
src/timeshift/private.h
src/timeshift/timeshift_filemgr.c

index 37fac3bd5661e9db47224c1f6e787ba6b8d175b1..bbc2eebe4a732a4fce94d642a3e9e34b95eb666f 100644 (file)
@@ -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);
index baa2e932f0082c96cbf97b5be9832d5127a11f9d..49b2afb206b885fabc3c111cdea3ce674cacfb8a 100644 (file)
@@ -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;
index bcd301213baaa9e4a6e6dfb1720d31a31db0965b..2f8fb13be508e6249a3bd380d2cc077ffc38528c 100644 (file)
@@ -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;
index a65cda768bc1f3e649a8307b6626602d68a40ef4..2f0236bb666a69962a1bb545def73c6d4270a2dc 100644 (file)
@@ -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(&timeshift_total_size, tsf->size);
   if (tsf->ram)
     atomic_dec_u64(&timeshift_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(&timeshift_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(&timeshift_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(&timeshift_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++;
         }
       }