http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56981



--- Comment #4 from Janne Blomqvist <jb at gcc dot gnu.org> 2013-04-17 10:50:07 
UTC ---

The reason why gfortran is slow here is that for non-regular files we use

unbuffered I/O. If you write to a regular file instead of /dev/null, you'll see

us doing ~8 KB writes at a time. On my system, timing writing to /dev/null

gives



real    0m0.727s

user    0m0.272s

sys     0m0.452s



whereas writing to a file gives



real    0m0.202s

user    0m0.180s

sys     0m0.020s





The reason for this is that non-regular files (a.k.a. special files) are

special in many ways wrt seeking. Some allow seeking just fine, some always

return 0, some return an error (and which special files behave in which way is

to some extent different on different OS'es). As the buffered IO keeps track of

the logical file pointer position, it can easily get out of sync with the

physical position if it doesn't behave as for a regular file.



Also, for special files users often expect non-buffered IO, e.g. they want

output on the terminal directly instead of waiting until the 8 KB buffer fills

up, programs communicating via pipes can deadlock if data sits in the buffers,

etc. One could of course make "unbuffered" I/O in gfortran really mean "flush

the buffer at the end of each I/O statement" rather than not using a buffer at

all and instead using the raw POSIX I/O syscalls. This would perhaps not be a

bad idea per se, but would require making the buffered I/O code handle special

files in some sensible way.



Another reason for gfortran slowness is that we do quite a lot of checking in

data_transfer_init(), which means that there's quite a lot of per-record

overhead. Writing a single element unformatted is thus the worst case. One way

to speed up data_transfer_init, I think, is that instead of checking each flag

bit (which says which I/O specifiers are present) separately, create a variable

with forbidden flags for each I/O type (unformatted/formatted,

sequential/direct/stream => 6x), and check the entire flag variable once (flag

& forbidden_flags == 0). Only if there is an error, do the bit-by-bit checking

in order to generate the error message.

Reply via email to