Skip to content

Commit bf1aacc

Browse files
committed
Fix performance issue with backspace (call fseek() from the loop only when really needed)
This is supplementary to the commit which introduces buffered I/O. Signed-off-by: Paul Osmialowski <[email protected]>
1 parent ae704e7 commit bf1aacc

File tree

2 files changed

+29
-7
lines changed

2 files changed

+29
-7
lines changed

runtime/flang/backspace.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,15 @@ _f90io_backspace(__INT_T *unit, __INT_T *bitv, __INT_T *iostat, int swap_bytes)
8989
if (FIO_FCB_FTELL(f) == 0) /* use ftell in case file opened 'append' */
9090
return 0;
9191

92-
FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __fortio_error(__io_errno()));
93-
fp = f->__io_fp;
94-
9592
if (f->form == FIO_UNFORMATTED) { /* CASE 1: unformatted file */
9693
int reclen;
9794
/* variable length record is stored as length:record:length
9895
so back up over trailing length field, read the size, then
9996
back up over the record and both length fields */
10097

98+
FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __fortio_error(__io_errno()));
99+
fp = f->__io_fp;
100+
101101
rec_continued:
102102
if (__io_fseek(fp, -((seekoffx_t)RCWSZ), SEEK_CUR) != 0)
103103
return __fortio_error(__io_errno());
@@ -115,17 +115,21 @@ _f90io_backspace(__INT_T *unit, __INT_T *bitv, __INT_T *iostat, int swap_bytes)
115115
goto rec_continued;
116116
f->coherent = 0; /* avoid unnecessary seek later on */
117117
} else { /* CASE 2: formatted file */
118+
int ch;
118119
seekoffx_t pos;
119120
assert(f->form == FIO_FORMATTED);
120-
pos = __io_ftell(fp) - 1;
121+
pos = FIO_FCB_FTELL(f) - 1L;
121122
assert(pos >= 0);
122123
while (TRUE) {
123124
if (pos > 0)
124125
--pos;
125-
if (__io_fseek(fp, pos, SEEK_SET) != 0)
126-
return __fortio_error(__io_errno());
126+
FIO_FCB_FSEEK_SET(f, pos, return __fortio_error(__io_errno()));
127127

128-
if (pos == 0 || __io_fgetc(fp) == '\n') {
128+
if (pos == 0)
129+
ch = 0;
130+
else
131+
FIO_FCB_BUFFERED_GETC(ch, f, return __fortio_error(__io_errno()));
132+
if (pos == 0 || ch == '\n') {
129133
/* must set coherent flag to 'read' in case the next operation
130134
on this file is a write: */
131135
f->coherent = 2 /*read*/;

runtime/flang/global.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,24 @@ typedef struct fcb {
334334
on_error; \
335335
}
336336

337+
#define FIO_FCB_FSEEK_SET(fcb, offset, on_error) if (0 <= ((fcb)->getc_bufpos)) { \
338+
long tmp = ((fcb)->getc_bufpos) + ((offset) - ((fcb)->getc_filepos)); \
339+
(fcb)->getc_filepos = offset; \
340+
if ((0L <= tmp) && (tmp < ((fcb)->getc_inbuffer))) { \
341+
(fcb)->getc_bufpos = tmp; \
342+
} else { \
343+
(fcb)->getc_bufpos = -1; \
344+
if (__io_feof((fcb)->__io_fp)) \
345+
__io_clearerr((fcb)->__io_fp); \
346+
if (__io_fseek((fcb)->__io_fp, (offset), SEEK_SET) != 0) \
347+
on_error; \
348+
} \
349+
} else \
350+
{ \
351+
if (__io_fseek((fcb)->__io_fp, (offset), SEEK_SET) != 0) \
352+
on_error; \
353+
}
354+
337355
#define FIO_FCB_BUFFERED_GETC(c, fcb, on_error) do { \
338356
if ((fcb)->getc_buffer_notuse) { \
339357
(c) = __io_fgetc((fcb)->__io_fp); \

0 commit comments

Comments
 (0)