re PR libfortran/91030 (Poor performance of I/O -fconvert=big-endian)
2019-07-21 Thomas König <tkoenig@gcc.gnu.org> PR libfortran/91030 * gfortran.texi (GFORTRAN_FORMATTED_BUFFER_SIZE): Document (GFORTRAN_UNFORMATTED_BUFFER_SIZE): Likewise. 2019-07-21 Thomas König <tkoenig@gcc.gnu.org> PR libfortran/91030 * io/unix.c (BUFFER_SIZE): Delete. (BUFFER_FORMATTED_SIZE_DEFAULT): New variable. (BUFFER_UNFORMATTED_SIZE_DEFAULT): New variable. (unix_stream): Add buffer_size. (buf_read): Use s->buffer_size instead of BUFFER_SIZE. (buf_write): Likewise. (buf_init): Add argument unformatted. Handle block sizes for unformatted vs. formatted, using defaults if provided. (fd_to_stream): Add argument unformatted in call to buf_init. * libgfortran.h (options_t): Add buffer_size_formatted and buffer_size_unformatted. * runtime/environ.c (variable_table): Add GFORTRAN_UNFORMATTED_BUFFER_SIZE and GFORTRAN_FORMATTED_BUFFER_SIZE. From-SVN: r273643
This commit is contained in:
parent
037455d49c
commit
c37b0163fe
@ -1,3 +1,9 @@
|
||||
2019-07-21 Thomas König <tkoenig@gcc.gnu.org>
|
||||
|
||||
PR libfortran/91030
|
||||
* gfortran.texi (GFORTRAN_FORMATTED_BUFFER_SIZE): Document
|
||||
(GFORTRAN_UNFORMATTED_BUFFER_SIZE): Likewise.
|
||||
|
||||
2019-07-16 Harald Anlauf <anlauf@gmx.de>
|
||||
|
||||
PR fortran/90903
|
||||
|
@ -611,6 +611,8 @@ Malformed environment variables are silently ignored.
|
||||
* GFORTRAN_LIST_SEPARATOR:: Separator for list output
|
||||
* GFORTRAN_CONVERT_UNIT:: Set endianness for unformatted I/O
|
||||
* GFORTRAN_ERROR_BACKTRACE:: Show backtrace on run-time errors
|
||||
* GFORTRAN_FORMATTED_BUFFER_SIZE:: Buffer size for formatted files.
|
||||
* GFORTRAN_UNFORMATTED_BUFFER_SIZE:: Buffer size for unformatted files.
|
||||
@end menu
|
||||
|
||||
@node TMPDIR
|
||||
@ -782,6 +784,20 @@ the backtracing, set the variable to @samp{n}, @samp{N}, @samp{0}.
|
||||
Default is to print a backtrace unless the @option{-fno-backtrace}
|
||||
compile option was used.
|
||||
|
||||
@node GFORTRAN_FORMATTED_BUFFER_SIZE
|
||||
@section @env{GFORTRAN_FORMATTED_BUFFER_SIZE}---Set buffer size for formatted I/O
|
||||
|
||||
The @env{GFORTRAN_FORMATTED_BUFFER_SIZE} environment variable
|
||||
specifies buffer size in bytes to be used for formatted output.
|
||||
The default value is 8192.
|
||||
|
||||
@node GFORTRAN_UNFORMATTED_BUFFER_SIZE
|
||||
@section @env{GFORTRAN_UNFORMATTED_BUFFER_SIZE}---Set buffer size for unformatted I/O
|
||||
|
||||
The @env{GFORTRAN_UNFORMATTED_BUFFER_SIZE} environment variable
|
||||
specifies buffer size in bytes to be used for unformatted output.
|
||||
The default value is 131072.
|
||||
|
||||
@c =====================================================================
|
||||
@c PART II: LANGUAGE REFERENCE
|
||||
@c =====================================================================
|
||||
|
@ -1,3 +1,21 @@
|
||||
2019-07-21 Thomas König <tkoenig@gcc.gnu.org>
|
||||
|
||||
PR libfortran/91030
|
||||
* io/unix.c (BUFFER_SIZE): Delete.
|
||||
(BUFFER_FORMATTED_SIZE_DEFAULT): New variable.
|
||||
(BUFFER_UNFORMATTED_SIZE_DEFAULT): New variable.
|
||||
(unix_stream): Add buffer_size.
|
||||
(buf_read): Use s->buffer_size instead of BUFFER_SIZE.
|
||||
(buf_write): Likewise.
|
||||
(buf_init): Add argument unformatted. Handle block sizes
|
||||
for unformatted vs. formatted, using defaults if provided.
|
||||
(fd_to_stream): Add argument unformatted in call to buf_init.
|
||||
* libgfortran.h (options_t): Add buffer_size_formatted and
|
||||
buffer_size_unformatted.
|
||||
* runtime/environ.c (variable_table): Add
|
||||
GFORTRAN_UNFORMATTED_BUFFER_SIZE and
|
||||
GFORTRAN_FORMATTED_BUFFER_SIZE.
|
||||
|
||||
2019-06-25 Kwok Cheung Yeung <kcy@codesourcery.com>
|
||||
Andrew Stubbs <ams@codesourcery.com>
|
||||
|
||||
|
@ -193,7 +193,8 @@ fallback_access (const char *path, int mode)
|
||||
|
||||
/* Unix and internal stream I/O module */
|
||||
|
||||
static const int BUFFER_SIZE = 8192;
|
||||
static const int FORMATTED_BUFFER_SIZE_DEFAULT = 8192;
|
||||
static const int UNFORMATTED_BUFFER_SIZE_DEFAULT = 128*1024;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -205,6 +206,7 @@ typedef struct
|
||||
gfc_offset file_length; /* Length of the file. */
|
||||
|
||||
char *buffer; /* Pointer to the buffer. */
|
||||
ssize_t buffer_size; /* Length of the buffer. */
|
||||
int fd; /* The POSIX file descriptor. */
|
||||
|
||||
int active; /* Length of valid bytes in the buffer */
|
||||
@ -592,9 +594,9 @@ buf_read (unix_stream *s, void *buf, ssize_t nbyte)
|
||||
&& raw_seek (s, new_logical, SEEK_SET) < 0)
|
||||
return -1;
|
||||
s->buffer_offset = s->physical_offset = new_logical;
|
||||
if (to_read <= BUFFER_SIZE/2)
|
||||
if (to_read <= s->buffer_size/2)
|
||||
{
|
||||
did_read = raw_read (s, s->buffer, BUFFER_SIZE);
|
||||
did_read = raw_read (s, s->buffer, s->buffer_size);
|
||||
if (likely (did_read >= 0))
|
||||
{
|
||||
s->physical_offset += did_read;
|
||||
@ -632,11 +634,11 @@ buf_write (unix_stream *s, const void *buf, ssize_t nbyte)
|
||||
s->buffer_offset = s->logical_offset;
|
||||
|
||||
/* Does the data fit into the buffer? As a special case, if the
|
||||
buffer is empty and the request is bigger than BUFFER_SIZE/2,
|
||||
buffer is empty and the request is bigger than s->buffer_size/2,
|
||||
write directly. This avoids the case where the buffer would have
|
||||
to be flushed at every write. */
|
||||
if (!(s->ndirty == 0 && nbyte > BUFFER_SIZE/2)
|
||||
&& s->logical_offset + nbyte <= s->buffer_offset + BUFFER_SIZE
|
||||
if (!(s->ndirty == 0 && nbyte > s->buffer_size/2)
|
||||
&& s->logical_offset + nbyte <= s->buffer_offset + s->buffer_size
|
||||
&& s->buffer_offset <= s->logical_offset
|
||||
&& s->buffer_offset + s->ndirty >= s->logical_offset)
|
||||
{
|
||||
@ -651,7 +653,7 @@ buf_write (unix_stream *s, const void *buf, ssize_t nbyte)
|
||||
the request is bigger than the buffer size, write directly
|
||||
bypassing the buffer. */
|
||||
buf_flush (s);
|
||||
if (nbyte <= BUFFER_SIZE/2)
|
||||
if (nbyte <= s->buffer_size/2)
|
||||
{
|
||||
memcpy (s->buffer, buf, nbyte);
|
||||
s->buffer_offset = s->logical_offset;
|
||||
@ -688,7 +690,7 @@ buf_write (unix_stream *s, const void *buf, ssize_t nbyte)
|
||||
static int
|
||||
buf_markeor (unix_stream *s)
|
||||
{
|
||||
if (s->unbuffered || s->ndirty >= BUFFER_SIZE / 2)
|
||||
if (s->unbuffered || s->ndirty >= s->buffer_size / 2)
|
||||
return buf_flush (s);
|
||||
return 0;
|
||||
}
|
||||
@ -765,11 +767,32 @@ static const struct stream_vtable buf_vtable = {
|
||||
};
|
||||
|
||||
static int
|
||||
buf_init (unix_stream *s)
|
||||
buf_init (unix_stream *s, bool unformatted)
|
||||
{
|
||||
s->st.vptr = &buf_vtable;
|
||||
|
||||
s->buffer = xmalloc (BUFFER_SIZE);
|
||||
/* Try to guess a good value for the buffer size. For formatted
|
||||
I/O, we use so many CPU cycles converting the data that there is
|
||||
more sense in converving memory and especially cache. For
|
||||
unformatted, a bigger block can have a large impact in some
|
||||
environments. */
|
||||
|
||||
if (unformatted)
|
||||
{
|
||||
if (options.unformatted_buffer_size > 0)
|
||||
s->buffer_size = options.unformatted_buffer_size;
|
||||
else
|
||||
s->buffer_size = UNFORMATTED_BUFFER_SIZE_DEFAULT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (options.formatted_buffer_size > 0)
|
||||
s->buffer_size = options.formatted_buffer_size;
|
||||
else
|
||||
s->buffer_size = FORMATTED_BUFFER_SIZE_DEFAULT;
|
||||
}
|
||||
|
||||
s->buffer = xmalloc (s->buffer_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1120,13 +1143,13 @@ fd_to_stream (int fd, bool unformatted)
|
||||
(s->fd == STDIN_FILENO
|
||||
|| s->fd == STDOUT_FILENO
|
||||
|| s->fd == STDERR_FILENO)))
|
||||
buf_init (s);
|
||||
buf_init (s, unformatted);
|
||||
else
|
||||
{
|
||||
if (unformatted)
|
||||
{
|
||||
s->unbuffered = true;
|
||||
buf_init (s);
|
||||
buf_init (s, unformatted);
|
||||
}
|
||||
else
|
||||
raw_init (s);
|
||||
|
@ -540,6 +540,7 @@ typedef struct
|
||||
|
||||
int all_unbuffered, unbuffered_preconnected;
|
||||
int fpe, backtrace;
|
||||
int unformatted_buffer_size, formatted_buffer_size;
|
||||
}
|
||||
options_t;
|
||||
|
||||
|
@ -198,6 +198,14 @@ static variable variable_table[] = {
|
||||
/* Print out a backtrace if possible on runtime error */
|
||||
{ "GFORTRAN_ERROR_BACKTRACE", -1, &options.backtrace, init_boolean },
|
||||
|
||||
/* Buffer size for unformatted files. */
|
||||
{ "GFORTRAN_UNFORMATTED_BUFFER_SIZE", 0, &options.unformatted_buffer_size,
|
||||
init_integer },
|
||||
|
||||
/* Buffer size for formatted files. */
|
||||
{ "GFORTRAN_FORMATTED_BUFFER_SIZE", 0, &options.formatted_buffer_size,
|
||||
init_integer },
|
||||
|
||||
{ NULL, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user