From 1eb15039114f4bcda7269cc406111138ceba1f0f Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 5 Jun 2002 10:19:07 -0500 Subject: [svn-r5535] Purpose: New feature. Description: Added a "small data" block allocation mechanism to the library, similar to the mechanism used for allocating metadata currently. See the RFC for more details: http://hdf.ncsa.uiuc.edu/RFC/SmallData/SmallData.html This reduces the number of I/O operations which hit the disk for my test program from 19 to 15 (i.e. from 393 to 15, overall). Platforms tested: Solaris 2.7 (arabica) w/FORTRAN and FreeBSD 4.5 (sleipnir) w/C++ --- release_docs/RELEASE.txt | 2 + src/H5F.c | 2 + src/H5FD.c | 179 +++++++++++++++++++++++++++++++++-------------- src/H5FDfamily.c | 1 + src/H5FDgass.c | 1 + src/H5FDlog.c | 1 + src/H5FDmpio.c | 1 + src/H5FDmulti.c | 1 + src/H5FDpublic.h | 11 +++ src/H5FDsec2.c | 1 + src/H5FDsrb.c | 1 + src/H5FDstdio.c | 1 + src/H5FDstream.c | 1 + src/H5Fprivate.h | 1 + src/H5P.c | 4 +- 15 files changed, 154 insertions(+), 54 deletions(-) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 7a8a71b..8f4fd7e 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -42,6 +42,8 @@ New Features ========= o General --------- + * Added internal "small data" aggregation, which can reduce the number of + actual I/O calls made, improving performance. QAK - 2002/06/05 * Improved internal metadata aggregation, which can reduce the number of actual I/O calls made, improving performance. Additionally, this can reduce the size of files produced. QAK - 2002/06/04 diff --git a/src/H5F.c b/src/H5F.c index b373e45..cc59183 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -232,6 +232,7 @@ H5F_init_interface(void) H5F_access_dflt.alignment = 1; /*no alignment*/ H5F_access_dflt.gc_ref = 0; /*don't garbage-collect references*/ H5F_access_dflt.meta_block_size = 2048; /* set metadata block allocations to 2KB */ + H5F_access_dflt.sdata_block_size = 2048; /* set "small data" block allocations to 2KB */ H5F_access_dflt.sieve_buf_size = 64*1024; /* set sieve buffer allocation to 64KB */ H5F_access_dflt.driver_id = H5FD_SEC2; /*default driver*/ H5F_access_dflt.driver_info = NULL; /*driver file access properties*/ @@ -491,6 +492,7 @@ H5Fget_access_plist(hid_t file_id) _fapl.alignment = f->shared->alignment; _fapl.gc_ref = f->shared->gc_ref; _fapl.meta_block_size = f->shared->lf->def_meta_block_size; + _fapl.sdata_block_size = f->shared->lf->def_sdata_block_size; _fapl.sieve_buf_size = f->shared->sieve_buf_size; _fapl.driver_id = f->shared->lf->driver_id; _fapl.driver_info = NULL; /*just for now */ diff --git a/src/H5FD.c b/src/H5FD.c index 638c756..522e35b 100644 --- a/src/H5FD.c +++ b/src/H5FD.c @@ -812,6 +812,7 @@ H5FD_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) file->maxaddr = maxaddr; HDmemset(file->fl, 0, sizeof(file->fl)); file->def_meta_block_size = fapl->meta_block_size; + file->def_sdata_block_size = fapl->sdata_block_size; file->accum_loc = HADDR_UNDEF; file->threshold = fapl->threshold; file->alignment = fapl->alignment; @@ -1413,72 +1414,144 @@ H5FD_alloc(H5FD_t *file, H5FD_mem_t type, hsize_t size) } #endif - /* - * If the metadata aggregation feature is enabled for this VFL driver, - * allocate "generic" metadata space and sub-allocate out of that, if - * possible. Otherwise just allocate through H5FD_real_alloc() - */ - /* Allocate all types of metadata out of the metadata block */ - if((file->feature_flags&H5FD_FEAT_AGGREGATE_METADATA) && type!=H5FD_MEM_DRAW) { - /* Check if the space requested is larger than the space left in the block */ - if(size>file->cur_meta_block_size) { - haddr_t new_meta; /* Address for new metadata */ - - /* Check if the block asked for is too large for a metadata block */ - if(size>=file->def_meta_block_size) { - /* Allocate more room for this new block the regular way */ - new_meta=H5FD_real_alloc(file,type,size); - - /* Check if the new metadata is at the end of the current metadata block */ - if(file->eoma+file->cur_meta_block_size==new_meta) { - /* Treat the allocation request as if the current metadata block - * grew by the amount allocated and just update the eoma - * address. Don't bother updating the cur_meta_block_size - * since it will just grow and shrink by the same amount. - */ - ret_value=file->eoma; - file->eoma+=size; + /* Handle metadata differently from "raw" data */ + if(type!=H5FD_MEM_DRAW) { + /* + * If the metadata aggregation feature is enabled for this VFL driver, + * allocate "generic" metadata space and sub-allocate out of that, if + * possible. Otherwise just allocate through H5FD_real_alloc() + */ + /* Allocate all types of metadata out of the metadata block */ + if(file->feature_flags&H5FD_FEAT_AGGREGATE_METADATA) { + /* Check if the space requested is larger than the space left in the block */ + if(size>file->cur_meta_block_size) { + haddr_t new_meta; /* Address for new metadata */ + + /* Check if the block asked for is too large for a metadata block */ + if(size>=file->def_meta_block_size) { + /* Allocate more room for this new block the regular way */ + new_meta=H5FD_real_alloc(file,type,size); + + /* Check if the new metadata is at the end of the current metadata block */ + if(file->eoma+file->cur_meta_block_size==new_meta) { + /* Treat the allocation request as if the current metadata block + * grew by the amount allocated and just update the eoma + * address. Don't bother updating the cur_meta_block_size + * since it will just grow and shrink by the same amount. + */ + ret_value=file->eoma; + file->eoma+=size; + } /* end if */ + else { + /* Use the new metadata block for the space allocated */ + ret_value=new_meta; + } /* end else */ } /* end if */ else { - /* Use the new metadata block for the space allocated */ - ret_value=new_meta; - } /* end else */ - } /* end if */ - else { - /* Allocate another metadata block */ - new_meta=H5FD_real_alloc(file,H5FD_MEM_DEFAULT,file->def_meta_block_size); + /* Allocate another metadata block */ + new_meta=H5FD_real_alloc(file,H5FD_MEM_DEFAULT,file->def_meta_block_size); - /* Check if the new metadata is at the end of the current metadata block */ - if(file->eoma+file->cur_meta_block_size==new_meta) { - file->cur_meta_block_size+=file->def_meta_block_size; - } /* end if */ - else { - /* - * Instead of just dropping the remainder of the block on the - * floor and leaving the space in the file unused, we should - * return this small piece of unused space to the free list - * management. - QAK - */ - file->eoma=new_meta; - file->cur_meta_block_size=file->def_meta_block_size; - } /* end else */ + /* Check if the new metadata is at the end of the current metadata block */ + if(file->eoma+file->cur_meta_block_size==new_meta) { + file->cur_meta_block_size+=file->def_meta_block_size; + } /* end if */ + else { + /* + * Instead of just dropping the remainder of the block on the + * floor and leaving the space in the file unused, we should + * return this small piece of unused space to the free list + * management. - QAK + */ + file->eoma=new_meta; + file->cur_meta_block_size=file->def_meta_block_size; + } /* end else */ + /* Allocate space out of the metadata block */ + ret_value=file->eoma; + file->cur_meta_block_size-=size; + file->eoma+=size; + } /* end else */ + } /* end if */ + else { /* Allocate space out of the metadata block */ ret_value=file->eoma; file->cur_meta_block_size-=size; file->eoma+=size; } /* end else */ } /* end if */ - else { - /* Allocate space out of the metadata block */ - ret_value=file->eoma; - file->cur_meta_block_size-=size; - file->eoma+=size; + else { /* Allocate data the regular way */ + ret_value=H5FD_real_alloc(file,type,size); } /* end else */ } /* end if */ - else { /* Allocate data the regular way */ - ret_value=H5FD_real_alloc(file,type,size); + else { /* Allocate "raw" data */ + /* + * If the "small data" aggregation feature is enabled for this VFL driver, + * allocate "small data" space and sub-allocate out of that, if + * possible. Otherwise just allocate through H5FD_real_alloc() + */ + if(file->feature_flags&H5FD_FEAT_AGGREGATE_SMALLDATA) { + /* Check if the space requested is larger than the space left in the block */ + if(size>file->cur_sdata_block_size) { + haddr_t new_data; /* Address for new raw data block */ + + /* Check if the block asked for is too large for the "small data" block */ + if(size>=file->def_sdata_block_size) { + /* Allocate more room for this new block the regular way */ + new_data=H5FD_real_alloc(file,type,size); + + /* Check if the new raw data is at the end of the current "small data" block */ + if(file->eosda+file->cur_sdata_block_size==new_data) { + /* Treat the allocation request as if the current "small data" + * block grew by the amount allocated and just update the + * eosda address. Don't bother updating the + * cur_sdata_block_size since it will just grow and shrink by + * the same amount. + */ + ret_value=file->eosda; + file->eosda+=size; + } /* end if */ + else { + /* Use the new "small data" block for the space allocated */ + ret_value=new_data; + } /* end else */ + } /* end if */ + else { + /* Allocate another "small data" block */ + new_data=H5FD_real_alloc(file,type,file->def_sdata_block_size); + + /* Check if the new raw data is at the end of the current "small data" block */ + if(file->eosda+file->cur_sdata_block_size==new_data) { + file->cur_sdata_block_size+=file->def_sdata_block_size; + } /* end if */ + else { + /* + * Instead of just dropping the remainder of the block on the + * floor and leaving the space in the file unused, we should + * return this small piece of unused space to the free list + * management. - QAK + */ + file->eosda=new_data; + file->cur_sdata_block_size=file->def_sdata_block_size; + } /* end else */ + + + /* Allocate space out of the "small data" block */ + ret_value=file->eosda; + file->cur_sdata_block_size-=size; + file->eosda+=size; + } /* end else */ + } /* end if */ + else { + /* Allocate space out of the "small data" block */ + ret_value=file->eosda; + file->cur_sdata_block_size-=size; + file->eosda+=size; + } /* end else */ + } /* end if */ + else { /* Allocate data the regular way */ + ret_value=H5FD_real_alloc(file,type,size); + } /* end else */ } /* end else */ done: diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c index 12a102c..320e916 100644 --- a/src/H5FDfamily.c +++ b/src/H5FDfamily.c @@ -639,6 +639,7 @@ H5FD_family_query(const H5FD_t UNUSED *_f, unsigned long *flags /* out */) *flags|=H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */ *flags|=H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */ *flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */ + *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ } FUNC_LEAVE(ret_value); diff --git a/src/H5FDgass.c b/src/H5FDgass.c index 26d40c0..41ef7d7 100644 --- a/src/H5FDgass.c +++ b/src/H5FDgass.c @@ -463,6 +463,7 @@ H5FD_gass_query(const UNUSED H5FD_t *_f, unsigned long *flags /* out */) if(flags) { *flags = 0; *flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */ + *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ } FUNC_LEAVE(ret_value); diff --git a/src/H5FDlog.c b/src/H5FDlog.c index 67d3a0b..0fdfe5c 100644 --- a/src/H5FDlog.c +++ b/src/H5FDlog.c @@ -657,6 +657,7 @@ H5FD_log_query(const H5FD_t UNUSED *_f, unsigned long *flags /* out */) *flags|=H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */ *flags|=H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */ *flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */ + *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ } FUNC_LEAVE(ret_value); diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index fe7cfb1..6b4a20c 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -952,6 +952,7 @@ H5FD_mpio_query(const H5FD_t *_file, unsigned long *flags /* out */) if(flags) { *flags=0; *flags|=H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */ + *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ } /* end if */ FUNC_LEAVE(ret_value); diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c index c8773ff..48e711f 100644 --- a/src/H5FDmulti.c +++ b/src/H5FDmulti.c @@ -1359,6 +1359,7 @@ H5FD_multi_query(const H5FD_t *_f, unsigned long *flags /* out */) if(flags) { *flags=0; *flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */ + *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ } return(0); diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index 815a940..802b1c9 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -99,6 +99,12 @@ typedef enum H5FD_mem_t { * http://www.mcs.anl.gov/~thakur/papers/mpio-high-perf.ps.gz */ #define H5FD_FEAT_DATA_SIEVE 0x00000004 + /* + * Defining the H5FD_FEAT_AGGREGATE_SMALLDATA for a VFL driver means that + * the library will attempt to allocate a larger block for "small" raw data + * and then sub-allocate "small" raw data requests from that larger block. + */ +#define H5FD_FEAT_AGGREGATE_SMALLDATA 0x00000008 /* Forward declaration */ @@ -162,6 +168,11 @@ struct H5FD_t { hsize_t cur_meta_block_size; /* Current size of metadata allocation region left */ haddr_t eoma; /* End of metadata allocated region */ + /* "Small data" aggregation fields */ + hsize_t def_sdata_block_size; /* "Small data" allocation block size (if aggregating "small data") */ + hsize_t cur_sdata_block_size; /* Current size of "small data" allocation region left */ + haddr_t eosda; /* End of "small data" allocated region */ + /* Metadata accumulator fields */ unsigned char *meta_accum; /* Buffer to hold the accumulated metadata */ haddr_t accum_loc; /* File location (offset) of the accumulated metadata */ diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c index 06a5e49..85c5a31 100644 --- a/src/H5FDsec2.c +++ b/src/H5FDsec2.c @@ -430,6 +430,7 @@ H5FD_sec2_query(const H5FD_t UNUSED *_f, unsigned long *flags /* out */) *flags|=H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */ *flags|=H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */ *flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */ + *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ } FUNC_LEAVE(ret_value); diff --git a/src/H5FDsrb.c b/src/H5FDsrb.c index ae7d447..21beb41 100644 --- a/src/H5FDsrb.c +++ b/src/H5FDsrb.c @@ -391,6 +391,7 @@ H5FD_srb_query(const UNUSED H5FD_t *_f, unsigned long *flags /* out */) if(flags) { *flags = 0; *flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */ + *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ } FUNC_LEAVE(ret_value); diff --git a/src/H5FDstdio.c b/src/H5FDstdio.c index 9569f8f..f748254 100644 --- a/src/H5FDstdio.c +++ b/src/H5FDstdio.c @@ -462,6 +462,7 @@ H5FD_stdio_query(const H5FD_t *_f, unsigned long *flags /* out */) *flags|=H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */ *flags|=H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */ *flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */ + *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ } return(0); diff --git a/src/H5FDstream.c b/src/H5FDstream.c index fcbee7e..74db940 100644 --- a/src/H5FDstream.c +++ b/src/H5FDstream.c @@ -945,6 +945,7 @@ H5FD_stream_query(const H5FD_t UNUSED *_f, *flags = 0; /* OK to perform data sieving for faster raw data reads & writes */ *flags |= H5FD_FEAT_DATA_SIEVE; + *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */ } FUNC_LEAVE (SUCCEED); diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 971cf2d..31ec3ba 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -241,6 +241,7 @@ typedef struct H5F_access_t { hsize_t threshold; /* Threshold for alignment */ hsize_t alignment; /* Alignment */ size_t meta_block_size; /* Minimum metadata allocation block size (when aggregating metadata allocations) */ + size_t sdata_block_size; /* Minimum "small data" allocation block size (when aggregating "small data" allocations) */ hsize_t sieve_buf_size; /* Maximum sieve buffer size (when data sieving is allowed by file driver) */ unsigned gc_ref; /* Garbage-collect references? */ hid_t driver_id; /* File driver ID */ diff --git a/src/H5P.c b/src/H5P.c index f71537a..76ef5d0 100644 --- a/src/H5P.c +++ b/src/H5P.c @@ -3778,6 +3778,8 @@ H5Pget_vlen_mem_manager(hid_t plist_id, H5MM_allocate_t *alloc_func/*out*/, * Friday, August 25, 2000 * * Modifications: + * Quincey Koziol, June 5, 2002 + * Also sets the "small data" aggregation size * *------------------------------------------------------------------------- */ @@ -3797,7 +3799,7 @@ H5Pset_meta_block_size(hid_t fapl_id, hsize_t size) } /* Set values */ - fapl->meta_block_size = size; + fapl->sdata_block_size = fapl->meta_block_size = size; FUNC_LEAVE (SUCCEED); } -- cgit v0.12