changeset 25658:0812413a0bb7

Improve fread speed by a further 40% when SKIP parameter used (bug #54100). * oct-stream.cc (stream::fread): Check stream_ok immediately and return from function if it is not. Reformat comments to 80 character width. Declare new variable cur_pos to hold current position within file. Remove call to tellg, and use arithmetic based on cur_pos and number of iems read to determine position in file. Eliminate unneccesary test on stream is after seekg as it will be done as part of the while loop.
author Rik <rik@octave.org>
date Sun, 22 Jul 2018 21:52:34 -0700
parents db326f3aacf4
children e6d3f4f9473c
files libinterp/corefcn/oct-stream.cc
diffstat 1 files changed, 24 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/oct-stream.cc	Sun Jul 22 20:40:02 2018 -0700
+++ b/libinterp/corefcn/oct-stream.cc	Sun Jul 22 21:52:34 2018 -0700
@@ -6511,19 +6511,19 @@
   {
     octave_value retval;
 
+    if (! stream_ok ())
+      return retval;
+
     octave_idx_type nr = -1;
     octave_idx_type nc = -1;
 
     bool one_elt_size_spec = false;
 
-    if (! stream_ok ())
-      return retval;
-
-    // FIXME: we may eventually want to make this extensible.
-
-    // FIXME: we need a better way to ensure that this
-    // numbering stays consistent with the order of the elements in the
-    // data_type enum in the oct_data_conv class.
+    // FIXME: We may eventually want to make this extensible.
+
+    // FIXME: We need a better way to ensure that this numbering stays
+    // consistent with the order of the elements in the data_type enum in the
+    // oct_data_conv class.
 
     // Expose this in a future version?
     size_t char_count = 0;
@@ -6595,8 +6595,7 @@
 
     assert (input_buf_size >= 0);
 
-    // Must also work and return correct type object
-    // for 0 elements to read.
+    // Must also work and return correct type object for 0 elements to read.
     std::istream *isp = input_stream ();
 
     if (! isp)
@@ -6607,15 +6606,16 @@
 
         // Initialize eof_pos variable just once per function call
         off_t eof_pos = 0;
+        off_t cur_pos = 0;
         if (skip != 0 && is && ! is.eof ())
           {
-            off_t orig_pos = is.tellg ();
+            cur_pos = is.tellg ();
             is.seekg (0, is.end);
             eof_pos = is.tellg ();
-            is.seekg (orig_pos, is.beg);
+            is.seekg (cur_pos, is.beg);
           }
 
-        std::list <void *> input_buf_list;
+        std::list<void *> input_buf_list;
 
         while (is && ! is.eof ()
                && (read_to_eof || tmp_count < elts_to_read))
@@ -6635,6 +6635,7 @@
             size_t gcount = is.gcount ();
 
             char_count += gcount;
+            cur_pos += gcount;
 
             octave_idx_type nel = gcount / input_elt_size;
 
@@ -6642,20 +6643,22 @@
 
             input_buf_list.push_back (input_buf);
 
-            if (is && skip != 0 && nel == block_size)
+            if (skip != 0 && nel == block_size && is)
               {
                 // Attempt to skip.
                 // If skip would move past EOF, position at EOF.
-                off_t orig_pos = is.tellg ();
-                off_t remaining = eof_pos - orig_pos;
+                off_t remaining = eof_pos - cur_pos;
 
                 if (remaining < skip)
-                  is.seekg (0, is.end);
+                  {
+                    is.seekg (0, is.end);
+                    cur_pos = eof_pos;
+                  }
                 else
-                  is.seekg (skip, is.cur);
-
-                if (! is)
-                  break;
+                  {
+                    is.seekg (skip, is.cur);
+                    cur_pos += skip;
+                  }
               }
           }