From 00c67fa6a093def32ed951a0f974572cbd2e1ee8 Mon Sep 17 00:00:00 2001
From: Marcus Müller <mmueller@gnuradio.org>
Date: Sun, 21 Jun 2020 00:57:01 +0200
Subject: blocks: use posix_fadvise to tell OS about sequential access and
 prefetch

---
 gr-blocks/lib/file_source_impl.cc | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

(limited to 'gr-blocks/lib/file_source_impl.cc')

diff --git a/gr-blocks/lib/file_source_impl.cc b/gr-blocks/lib/file_source_impl.cc
index ee8e30f8a9..92f1d8220f 100644
--- a/gr-blocks/lib/file_source_impl.cc
+++ b/gr-blocks/lib/file_source_impl.cc
@@ -188,7 +188,34 @@ void file_source_impl::open(const char* filename,
 
     // Rewind to start offset
     if (d_seekable) {
-        if (GR_FSEEK(d_new_fp, start_offset_items * d_itemsize, SEEK_SET) == -1) {
+        auto start_offset = start_offset_items * d_itemsize;
+#ifdef _POSIX_C_SOURCE
+#if _POSIX_C_SOURCE >= 200112L
+        // If supported, tell the OS that we'll be accessing the file sequentially
+        // and that it would be a good idea to start prefetching it
+        auto fd = fileno(d_new_fp);
+        static const std::map<int, const std::string> fadv_errstrings = {
+            { EBADF, "bad file descriptor" },
+            { EINVAL, "invalid advise" },
+            { ESPIPE, "tried to act as if a pipe or similar was a file" }
+        };
+        if (file_size && file_size != INT64_MAX) {
+            if (auto ret = posix_fadvise(
+                    fd, start_offset, file_size - start_offset, POSIX_FADV_SEQUENTIAL)) {
+                GR_LOG_WARN(d_logger,
+                            "failed to advise to read sequentially, " +
+                                fadv_errstrings.at(ret));
+            }
+            if (auto ret = posix_fadvise(
+                    fd, start_offset, file_size - start_offset, POSIX_FADV_WILLNEED)) {
+                GR_LOG_WARN(d_logger,
+                            "failed to advise we'll need file contents soon, " +
+                                fadv_errstrings.at(ret));
+            }
+        }
+#endif
+#endif
+        if (GR_FSEEK(d_new_fp, start_offset, SEEK_SET) == -1) {
             throw std::runtime_error("can't fseek()");
         }
     }
-- 
cgit v1.2.3