#4028 Fix performance issues

This commit is contained in:
Magne Sjaastad 2019-01-31 09:13:29 +01:00
parent 55b215e66b
commit dfac372a9c

View File

@ -23,7 +23,7 @@
#include <errno.h> #include <errno.h>
#include <ert/util/util.h> #include <ert/util/util.h>
#include <ert/util/type_macros.hpp> #include <ert/util/type_macros.h>
#include <ert/ecl/fortio.h> #include <ert/ecl/fortio.h>
#include <ecl/fortio.h> #include <ecl/fortio.h>
@ -119,9 +119,13 @@ static fortio_type * fortio_alloc__(const char *filename , bool fmt_file , bool
*/ */
static bool __read_int(FILE * stream , int * value, bool endian_flip) { static bool __read_int(FILE * stream , int * value, bool endian_flip) {
int ok = eclfio_sizeof( stream, endian_flip ? "c" : "ce", value ); /* This fread() can legitemately fail - can not use util_fread() here. */
fseek( stream, sizeof( int32_t ), SEEK_CUR ); if (fread(value , sizeof * value , 1 , stream) == 1) {
return !ok; if (endian_flip)
util_endian_flip_vector(value , sizeof * value , 1);
return true;
} else
return false;
} }
@ -415,14 +419,30 @@ void fortio_fclose(fortio_type *fortio) {
bool fortio_is_fortio_file(fortio_type * fortio) { bool fortio_is_fortio_file(fortio_type * fortio) {
fpos_t init_pos; offset_type init_pos = fortio_ftell(fortio);
fgetpos( fortio->stream, &init_pos ); int elm_read;
bool is_fortio_file = false;
int record_size;
elm_read = fread(&record_size , sizeof(record_size) , 1 , fortio->stream);
if (elm_read == 1) {
int trailer;
int err = eclfio_get( fortio->stream, fortio->opts, NULL, NULL ); if (fortio->endian_flip_header)
util_endian_flip_vector(&record_size , sizeof record_size , 1);
fsetpos( fortio->stream, &init_pos ); if (fortio_fseek(fortio , (offset_type) record_size , SEEK_CUR) == 0) {
if (fread(&trailer , sizeof(record_size) , 1 , fortio->stream) == 1) {
if (fortio->endian_flip_header)
util_endian_flip_vector(&trailer , sizeof trailer , 1);
return err == ECL_OK; if (trailer == record_size)
is_fortio_file = true;
}
}
}
fortio_fseek(fortio , init_pos , SEEK_SET);
return is_fortio_file;
} }
@ -434,17 +454,26 @@ bool fortio_is_fortio_file(fortio_type * fortio) {
*/ */
int fortio_init_read(fortio_type *fortio) { int fortio_init_read(fortio_type *fortio) {
int32_t record_size; int elm_read;
int err = eclfio_sizeof( fortio->stream, fortio->opts, &record_size ); int record_size;
// this function exposes successful reads as advanced file pointers
if( err == 0 ) fseek( fortio->stream, 4, SEEK_CUR ); elm_read = fread(&record_size , sizeof(record_size) , 1 , fortio->stream);
return err ? -1 : record_size; if (elm_read == 1) {
if (fortio->endian_flip_header)
util_endian_flip_vector(&record_size , sizeof record_size , 1);
return record_size;
} else
return -1;
} }
bool fortio_data_fskip(fortio_type* fortio, const int element_size, const int element_count, const int block_count) { bool fortio_data_fskip(fortio_type* fortio, const int element_size, const int element_count, const int block_count) {
return !eclfio_skip( fortio->stream, fortio->opts, block_count ); int headers = block_count * 4;
int trailers = block_count * 4;
int bytes_to_skip = headers + trailers + (element_size * element_count);
return fortio_fseek(fortio, bytes_to_skip, SEEK_CUR);
} }
@ -456,9 +485,9 @@ void fortio_data_fseek(fortio_type* fortio, offset_type data_offset, size_t data
int block_index = data_element / block_size; int block_index = data_element / block_size;
int headers = (block_index + 1) * 4; int headers = (block_index + 1) * 4;
int trailers = block_index * 4; int trailers = block_index * 4;
offset_type offset = data_offset + headers + trailers + (data_element * element_size); offset_type bytes_to_skip = data_offset + headers + trailers + (data_element * element_size);
fortio_fseek(fortio, offset, SEEK_SET); fortio_fseek(fortio, bytes_to_skip, SEEK_SET);
} }
} }
@ -489,6 +518,28 @@ bool fortio_complete_read(fortio_type *fortio , int record_size) {
return false; return false;
} }
/**
This function reads one record from the fortio stream, and fills
the buffer with the content. The return value is the number of
bytes read; the function will return -1 on failure.
*/
static int fortio_fread_record(fortio_type *fortio , char *buffer) {
int record_size = fortio_init_read(fortio);
if (record_size >= 0) {
size_t items_read = fread(buffer , 1 , record_size , fortio->stream);
if (items_read == record_size) {
bool complete_ok = fortio_complete_read(fortio , record_size);
if (!complete_ok)
record_size = -1;
} else
record_size = -1; /* Failure */
}
return record_size;
}
/** /**
This function fills the buffer with 'buffer_size' bytes from the This function fills the buffer with 'buffer_size' bytes from the
fortio stream. The function works by repeated calls to fortio stream. The function works by repeated calls to
@ -499,107 +550,75 @@ bool fortio_complete_read(fortio_type *fortio , int record_size) {
*/ */
bool fortio_fread_buffer(fortio_type * fortio, char * buffer , int buffer_size) { bool fortio_fread_buffer(fortio_type * fortio, char * buffer , int buffer_size) {
int total_bytes_read = 0; int total_bytes_read = 0;
while( true ) { while (true) {
int32_t record_size = buffer_size - total_bytes_read; char * buffer_ptr = &buffer[total_bytes_read];
int err = eclfio_get( fortio->stream, int bytes_read = fortio_fread_record(fortio , buffer_ptr);
fortio->opts,
&record_size,
buffer );
if( err == ECL_EINVAL ) { if (bytes_read < 0)
err = eclfio_sizeof( fortio->stream, fortio->opts, &record_size ); break;
if( err ) util_abort("%s: unable to determine size of record, " else {
"%d bytes read\n", total_bytes_read += bytes_read;
__func__, if (total_bytes_read >= buffer_size)
total_bytes_read ); break;
if( total_bytes_read + record_size > buffer_size )
util_abort("%s: internal inconsistency: "
"buffer_size:%d, would read %d bytes\n",
__func__,
buffer_size,
total_bytes_read + record_size );
return false;
}
if( err ) return false;
buffer += record_size;
total_bytes_read += record_size;
if( total_bytes_read == buffer_size )
return true;
} }
}
if (total_bytes_read == buffer_size)
return true;
if (total_bytes_read < buffer_size)
return false;
util_abort("%s: internal inconsistency: buffer_size:%d read %d bytes \n",__func__ , buffer_size , total_bytes_read);
return false;
} }
int fortio_fskip_record(fortio_type *fortio) { int fortio_fskip_record(fortio_type *fortio) {
int32_t size = 0; int record_size = fortio_init_read(fortio);
const int err = eclfio_get( fortio->stream, fortio->opts, &size, NULL ); fortio_fseek(fortio , (offset_type) record_size , SEEK_CUR);
if( err ) return -1; fortio_complete_read(fortio , record_size);
return size; return record_size;
} }
void fortio_fskip_buffer(fortio_type * fortio, int buffer_size) { void fortio_fskip_buffer(fortio_type * fortio, int buffer_size) {
int bytes_skipped = 0; int bytes_skipped = 0;
while (bytes_skipped < buffer_size) { while (bytes_skipped < buffer_size)
int size = fortio_fskip_record(fortio); bytes_skipped += fortio_fskip_record(fortio);
if( size < 0 ) util_abort( "%s: broken record in %s. "
"%d bytes skipped so far\n",
__func__,
fortio->filename,
bytes_skipped );
bytes_skipped += fortio_fskip_record(fortio);
}
if (bytes_skipped > buffer_size) if (bytes_skipped > buffer_size)
util_abort("%s: hmmmm - something is broken. The individual records in %s did not sum up to the expected buffer size \n",__func__ , fortio->filename); util_abort("%s: hmmmm - something is broken. The individual records in %s did not sum up to the expected buffer size \n",__func__ , fortio->filename);
} }
void fortio_copy_record(fortio_type * src_stream , fortio_type * target_stream , int buffer_size , void * ext_buffer, bool *at_eof) { void fortio_copy_record(fortio_type * src_stream , fortio_type * target_stream , int buffer_size , void * buffer , bool *at_eof) {
int bytes_read = 0; int bytes_read;
int record_size = fortio_init_read(src_stream);
fortio_init_write(target_stream , record_size);
bytes_read = 0;
while (bytes_read < record_size) {
int bytes;
if (record_size > buffer_size)
bytes = buffer_size;
else
bytes = record_size - bytes_read;
int32_t size = 0; util_fread(buffer , 1 , bytes , src_stream->stream , __func__);
int err = eclfio_sizeof( src_stream->stream, src_stream->opts, &size ); util_fwrite(buffer , 1 , bytes , target_stream->stream , __func__);
if( err ) {
util_abort( "%s: could not peek record size after %d bytes\n",
__func__,
bytes_read );
}
void* buffer = ext_buffer; bytes_read += bytes;
if( buffer_size < size ) { }
buffer = malloc( size );
ext_buffer = NULL;
}
err = eclfio_get( src_stream->stream, src_stream->opts, &size, buffer ); fortio_complete_read(src_stream , record_size);
if( err ) { fortio_complete_write(target_stream , record_size);
util_abort( "%s: could not read record after %d bytes\n",
__func__,
bytes_read );
}
err = eclfio_put( target_stream->stream, if (feof(src_stream->stream))
target_stream->opts, *at_eof = true;
size, else
buffer ); *at_eof = false;
if( err ) {
util_abort( "%s: could not write record after %d bytes\n",
__func__,
bytes_read );
}
if( !ext_buffer ) free( buffer );
*at_eof = feof( src_stream->stream );
} }
@ -624,23 +643,19 @@ void fortio_complete_write(fortio_type *fortio , int record_size) {
void fortio_fwrite_record(fortio_type *fortio, const char *buffer , int record_size) { void fortio_fwrite_record(fortio_type *fortio, const char *buffer , int record_size) {
int err = eclfio_put( fortio->stream, fortio_init_write(fortio , record_size);
fortio->opts, util_fwrite( buffer , 1 , record_size , fortio->stream , __func__);
record_size, fortio_complete_write(fortio , record_size);
buffer );
if( err ) util_abort( "%s: unable to write %d byte record\n",
__func__,
record_size );
} }
void * fortio_fread_alloc_record(fortio_type * fortio) { void * fortio_fread_alloc_record(fortio_type * fortio) {
int32_t record_size = 0; void * buffer;
eclfio_sizeof( fortio->stream, fortio->opts, &record_size ); int record_size = fortio_init_read(fortio);
void* buffer = calloc( 1, record_size ); buffer = util_malloc( record_size );
eclfio_get( fortio->stream, fortio->opts, &record_size, buffer ); util_fread(buffer , 1 , record_size , fortio->stream , __func__);
return buffer; fortio_complete_read(fortio , record_size);
return buffer;
} }