Skip to content

Commit 001b16d

Browse files
committed
Use STL seekg/tellg for G3Reader frame indexing
This fixes a regression caused by the boost::iostreams variant. Profiling files with many thousands of frames reproduces the problem and verifies the solution.
1 parent 453f870 commit 001b16d

File tree

4 files changed

+29
-53
lines changed

4 files changed

+29
-53
lines changed

core/include/core/dataio.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,6 @@ typedef boost::iostreams::filtering_ostream g3_ostream;
3030
int g3_istream_from_path(g3_istream &stream, const std::string &path,
3131
float timeout=-1.0, size_t buffersize=1024*1024);
3232

33-
/**
34-
* Seek to a byte offset in an open input file stream.
35-
*
36-
* @param stream A reference to the filtering istream, e.g. as configured by
37-
* g3_istream_from_path.
38-
* @param offset File offset to seek to, in bytes, relative to the beginning
39-
* of the file.
40-
* @return New read head position, or -1 on error.
41-
*/
42-
off_t g3_istream_seek(g3_istream &stream, off_t offset);
43-
44-
/**
45-
* Return the current read head position in an open input file stream.
46-
*
47-
* @param stream A reference to the filtering istream, e.g. as configured by
48-
* g3_istream_from_path.
49-
* @return Current read head position, or -1 on error.
50-
*/
51-
off_t g3_istream_tell(g3_istream &stream);
52-
5333
/**
5434
* Configure a filtering stream for G3Frame compression to a local file.
5535
*

core/src/G3Reader.cxx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,14 @@ void G3Reader::Process(G3FramePtr frame, std::deque<G3FramePtr> &out)
100100
}
101101

102102
off_t G3Reader::Seek(off_t offset) {
103-
try {
104-
return g3_istream_seek(stream_, offset);
105-
} catch (...) {
103+
if (stream_.peek() == EOF && offset != Tell())
106104
log_fatal("Cannot seek %s; stream closed at EOF.", cur_file_.c_str());
107-
}
105+
stream_.seekg(offset, std::ios_base::beg);
106+
return offset;
108107
}
109108

110109
off_t G3Reader::Tell() {
111-
return g3_istream_tell(stream_);
110+
return stream_.tellg();
112111
}
113112

114113
PYBINDINGS("core") {

core/src/dataio.cxx

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -162,20 +162,6 @@ g3_istream_from_path(g3_istream &stream, const std::string &path,
162162
return fd;
163163
}
164164

165-
off_t
166-
g3_istream_seek(g3_istream &stream, off_t offset)
167-
{
168-
if (stream.peek() == EOF && offset != g3_istream_tell(stream))
169-
log_fatal("Cannot seek stream, closed at EOF.");
170-
return boost::iostreams::seek(stream, offset, std::ios_base::beg);
171-
}
172-
173-
off_t
174-
g3_istream_tell(g3_istream &stream)
175-
{
176-
return boost::iostreams::seek(stream, 0, std::ios_base::cur);
177-
}
178-
179165
void
180166
g3_ostream_to_path(g3_ostream &stream, const std::string &path,
181167
bool append, bool counter)

core/tests/fileio.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33
from spt3g import core
44
import time
55

6+
nframes = 1000
7+
verbose = False
8+
69
# File to disk
10+
core.log_notice("Writing %d frames to disk" % nframes)
711
pipe = core.G3Pipeline()
8-
pipe.Add(core.G3InfiniteSource, type=core.G3FrameType.Timepoint, n=10)
12+
pipe.Add(core.G3InfiniteSource, type=core.G3FrameType.Timepoint, n=nframes)
913
# Drop a wiring frame in the middle
1014
count = 0
1115
def addwiring(fr):
@@ -25,16 +29,18 @@ def addinfo(fr):
2529
fr['count'] = n
2630
n += 1
2731
pipe.Add(addinfo)
28-
pipe.Add(core.Dump)
32+
if verbose:
33+
pipe.Add(core.Dump)
2934
pipe.Add(core.G3Writer, filename='test.g3')
30-
pipe.Run()
31-
assert n == 10, 'Wrong number of frames written (%d should be %d)' % (n, 10)
35+
pipe.Run(profile=True)
36+
assert n == nframes, 'Wrong number of frames written (%d should be %d)' % (n, nframes)
3237

3338
# And back from disk
34-
print('Reading')
39+
core.log_notice("Reading %d frames from disk" % nframes)
3540
pipe = core.G3Pipeline()
3641
pipe.Add(core.G3Reader, filename='test.g3', track_filename=True)
37-
pipe.Add(core.Dump)
42+
if verbose:
43+
pipe.Add(core.Dump)
3844
n = 0
3945
def checkinfo(fr):
4046
global n
@@ -45,20 +51,21 @@ def checkinfo(fr):
4551
assert fr._filename == 'test.g3', 'Wrong filename'
4652
n += 1
4753
pipe.Add(checkinfo)
48-
pipe.Run()
54+
pipe.Run(profile=True)
4955

50-
assert n == 10, 'Wrong number of frames read (%d should be %d)' % (n, 10)
56+
assert n == nframes, 'Wrong number of frames read (%d should be %d)' % (n, nframes)
5157

5258
# Skip empty files
59+
core.log_notice("Reading %d frames from disk with empty files" % nframes)
5360
with core.G3Writer("empty.g3") as wr:
5461
pass
5562
n = 0
5663
pipe = core.G3Pipeline()
5764
pipe.Add(core.G3Reader, filename=["empty.g3", "test.g3", "empty.g3"], track_filename=True)
5865
pipe.Add(checkinfo)
59-
pipe.Run()
66+
pipe.Run(profile=True)
6067

61-
assert n == 10, 'Wrong number of frames read (%d should be %d)' % (n, 10)
68+
assert n == nframes, 'Wrong number of frames read (%d should be %d)' % (n, nframes)
6269

6370
# Indexing
6471
class CachingReader:
@@ -78,10 +85,12 @@ def __call__(self, frame):
7885

7986
cacher = CachingReader()
8087

88+
core.log_notice("Reading %d frames from disk with frame indexing" % nframes)
8189
pipe = core.G3Pipeline()
8290
pipe.Add(cacher)
83-
pipe.Add(core.Dump)
84-
pipe.Run()
91+
if verbose:
92+
pipe.Add(core.Dump)
93+
pipe.Run(profile=True)
8594

8695
assert cacher.w_pos is not None, 'Missing wiring frame'
8796

@@ -107,10 +116,12 @@ def __call__(self, frame):
107116

108117
cached = CachedReader(start=cacher.w_pos)
109118

119+
core.log_notice("Reading %d frames from disk with seek" % nframes)
110120
pipe = core.G3Pipeline()
111121
pipe.Add(cached)
112-
pipe.Add(core.Dump)
113-
pipe.Run()
122+
if verbose:
123+
pipe.Add(core.Dump)
124+
pipe.Run(profile=True)
114125

115126
assert cached.pos is None, "Missing wiring frame"
116127

0 commit comments

Comments
 (0)