From bc6f56390ae85bf312693e561f9fb1e9d2ca327a Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Fri, 4 Oct 2002 15:51:00 -0500 Subject: [svn-r5959] Purpose: Performance improvement for compact dataset. Platforms tested: Linux 2.2(eirene), Solaris 2.7(arabica), IRIX64 6.5(modi4) --- src/H5D.c | 5 +- src/H5Dprivate.h | 2 +- src/H5FD.c | 245 ++++++++++++++++++++++++++++++++++-------------------- src/H5FLprivate.h | 1 + 4 files changed, 161 insertions(+), 92 deletions(-) diff --git a/src/H5D.c b/src/H5D.c index d98c194..5bac61d 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -1531,6 +1531,7 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, H5D_fill_value_t fill_status; H5P_genplist_t *plist; /* Property list */ H5P_genplist_t *new_plist; /* New Property list */ + size_t ohdr_size=H5D_MINHDR_SIZE; /* Size of dataset's object header */ FUNC_ENTER_NOAPI(H5D_create, NULL); @@ -1708,6 +1709,8 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, if ((ndims=H5S_get_simple_extent_dims(space, new_dset->layout.dim, max_dim))<0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to initialize dimension size of compact dataset storage"); /* remember to check if size is small enough to fit header message */ + ohdr_size+=new_dset->layout.size; + break; default: @@ -1715,7 +1718,7 @@ H5D_create(H5G_entry_t *loc, const char *name, const H5T_t *type, } /* end switch */ /* Create (open for write access) an object header */ - if (H5O_create(f, 256, &(new_dset->ent)) < 0) + if (H5O_create(f, ohdr_size, &(new_dset->ent)) < 0) HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to create dataset object header"); /* Retrieve properties of fill value and others. Copy them into new fill diff --git a/src/H5Dprivate.h b/src/H5Dprivate.h index 6770af3..82cfdf3 100644 --- a/src/H5Dprivate.h +++ b/src/H5Dprivate.h @@ -39,7 +39,7 @@ #define H5D_RESERVED_ATOMS 0 /* Set the minimum object header size to create objects with */ -#define H5D_MINHDR_SIZE 512 +#define H5D_MINHDR_SIZE 256 /* ======== Dataset creation properties ======== */ /* Definitions for storage layout property */ diff --git a/src/H5FD.c b/src/H5FD.c index 8534b38..6192d26 100644 --- a/src/H5FD.c +++ b/src/H5FD.c @@ -1757,114 +1757,179 @@ H5FD_free(H5FD_t *file, H5FD_mem_t type, haddr_t addr, hsize_t size) * driver deallocate the memory. */ if (mapped_type>=0) { + H5FD_free_t *last; /* Last merged node */ + H5FD_free_t *last_prev=NULL;/* Pointer to node before merged node */ H5FD_free_t *curr; /* Current free block being inspected */ H5FD_free_t *prev; /* Previous free block being inspected */ + /* Adjust the metadata accumulator to remove the freed block, if it overlaps */ + if((file->feature_flags&H5FD_FEAT_ACCUMULATE_METADATA) + && H5F_addr_overlap(addr,size,file->accum_loc,file->accum_size)) { + size_t overlap_size; /* Size of overlap with accumulator */ + + /* Check for overlapping the beginning of the accumulator */ + if(H5F_addr_le(addr,file->accum_loc)) { + /* Check for completely overlapping the accumulator */ + if(H5F_addr_ge(addr+size,file->accum_loc+file->accum_size)) { + /* Reset the entire accumulator */ + file->accum_loc=HADDR_UNDEF; + file->accum_size=FALSE; + file->accum_dirty=FALSE; + } /* end if */ + /* Block to free must end within the accumulator */ + else { + size_t new_accum_size; /* Size of new accumulator buffer */ + + /* Calculate the size of the overlap with the accumulator, etc. */ + overlap_size=(addr+size)-file->accum_loc; + new_accum_size=file->accum_size-overlap_size; + + /* Move the accumulator buffer information to eliminate the freed block */ + HDmemmove(file->meta_accum,file->meta_accum+overlap_size,new_accum_size); + + /* Adjust the accumulator information */ + file->accum_loc+=overlap_size; + file->accum_size=new_accum_size; + } /* end else */ + } /* end if */ + /* Block to free must start within the accumulator */ + else { + /* Calculate the size of the overlap with the accumulator */ + overlap_size=(file->accum_loc+file->accum_size)-addr; + + /* Block to free is in the middle of the accumulator */ + if(H5F_addr_lt(addr,file->accum_loc+file->accum_size)) { + haddr_t tail_addr; + hsize_t tail_size; + + /* Calculate the address & size of the tail to write */ + tail_addr=addr+size; + tail_size=(file->accum_loc+file->accum_size)-tail_addr; + + /* Write out the part of the accumulator after the block to free */ + if (H5FD_write(file, H5FD_MEM_DEFAULT, H5P_DEFAULT, tail_addr, tail_size, file->meta_accum+(tail_addr-file->accum_loc))<0) + HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "file write request failed"); + } /* end if */ + + /* Adjust the accumulator information */ + file->accum_size=file->accum_size-overlap_size; + } /* end else */ + } /* end if */ + /* Scan through the existing blocks for the mapped type to see if we can extend one */ curr=file->fl[mapped_type]; - prev=NULL; + last=prev=NULL; while(curr!=NULL) { /* Check if the block to free adjoins the start of the current block */ if((addr+size)==curr->addr) { + /* If we previously found & merged a node, eliminate it from the list & free it */ + if(last!=NULL) { + /* Check if there was a previous block in the list */ + if(last_prev!=NULL) + /* Eliminate the merged block from the list */ + last_prev->next=last->next; + /* No previous block, this must be the head of the list */ + else + /* Eliminate the merged block from the list */ + file->fl[mapped_type] = last->next; + + /* Check for eliminating the block before the 'current' one */ + if(last==prev) + prev=last_prev; + + /* Free the memory for the merged block */ + H5FL_FREE(H5FD_free_t,last); + } /* end if */ + /* Adjust the address and size of the block found */ curr->addr=addr; curr->size+=size; - /* Break out of loop */ - break; + /* Adjust the information about to memory block to include the merged block */ + addr=curr->addr; + size=curr->size; + + /* Update the information about the merged node */ + last=curr; + last_prev=prev; } /* end if */ else { /* Check if the block to free adjoins the end of the current block */ if((curr->addr+curr->size)==addr) { - /* Adjust the size of the block found */ - curr->size+=size; - - /* Break out of loop */ - break; - } /* end if */ - else { - /* Advance to next node in list */ - prev=curr; - curr=curr->next; - } /* end else */ - } /* end else */ - } /* end while */ + /* If we previously found & merged a node, eliminate it from the list & free it */ + if(last!=NULL) { + /* Check if there was a previous block in the list */ + if(last_prev!=NULL) + /* Eliminate the merged block from the list */ + last_prev->next=last->next; + /* No previous block, this must be the head of the list */ + else + /* Eliminate the merged block from the list */ + file->fl[mapped_type] = last->next; - /* Check if we adjusted an existing block */ - if(curr!=NULL) { - H5FD_free_t *merge_curr; /* Current free block for merging */ - H5FD_free_t *merge_prev; /* Previous free block for merging */ + /* Check for eliminating the block before the 'current' one */ + if(last==prev) + prev=last_prev; + /* Free the memory for the merged block */ + H5FL_FREE(H5FD_free_t,last); + } /* end if */ - /* Scan through the existing blocks for the mapped type to see if we can merge the block we just found */ - merge_curr=file->fl[mapped_type]; - merge_prev=NULL; - while(merge_curr!=NULL) { - /* Check if the found block adjoins the start of the current block */ - if((curr->addr+curr->size)==merge_curr->addr) { /* Adjust the size of the block found */ - curr->size+=merge_curr->size; + curr->size+=size; - /* Break out of loop */ - break; - } /* end if */ - else { - /* Check if the found block adjoins the end of the current block */ - if((merge_curr->addr+merge_curr->size)==curr->addr) { - /* Adjust the address and size of the block found */ - curr->addr=merge_curr->addr; - curr->size+=merge_curr->size; - - /* Break out of loop */ - break; - } /* end if */ - else { - /* Advance to next node in list */ - merge_prev=merge_curr; - merge_curr=merge_curr->next; - } /* end else */ - } /* end else */ - } /* end while */ - - /* Check if we merged a block out of existance */ - if(merge_curr!=NULL) { - /* Check if there was a previous block in the list */ - if(merge_prev!=NULL) - /* Eliminate the merged block from the list */ - merge_prev->next=merge_curr->next; - /* No previous block, this must be the head of the list */ - else - /* Eliminate the merged block from the list */ - file->fl[mapped_type] = merge_curr->next; + /* Adjust the information about to memory block to include the merged block */ + size=curr->size; - /* Check for eliminating the block before the 'found' one */ - if(merge_curr==prev) - prev=merge_prev; + /* Update the information about the merged node */ + last=curr; + last_prev=prev; + } /* end if */ + } /* end else */ - /* Free the memory for the merged block */ - H5FL_FREE(H5FD_free_t,merge_curr); - } /* end if */ + /* Advance to next node in list */ + prev=curr; + curr=curr->next; + } /* end while */ + /* Check if we adjusted an existing block */ + if(last!=NULL) { /* Move the node found to the front, if it wasn't already there */ - if(prev!=NULL) { - prev->next=curr->next; - curr->next = file->fl[mapped_type]; - file->fl[mapped_type] = curr; + if(last_prev!=NULL) { + last_prev->next=last->next; + last->next = file->fl[mapped_type]; + file->fl[mapped_type] = last; } /* end if */ } /* end if */ else { /* Allocate a new node to hold the free block's information */ - if(NULL==(curr = H5FL_ALLOC(H5FD_free_t,0))) + if(NULL==(last = H5FL_ALLOC(H5FD_free_t,0))) HGOTO_ERROR(H5E_FILE, H5E_NOSPACE, FAIL, "can't allocate node for free space info"); - curr->addr = addr; - curr->size = size; - curr->next = file->fl[mapped_type]; - file->fl[mapped_type] = curr; + last->addr = addr; + last->size = size; + last->next = file->fl[mapped_type]; + file->fl[mapped_type] = last; } /* end else */ /* Check if we increased the size of the largest block on the list */ - file->maxsize = MAX(file->maxsize, curr->size); + file->maxsize = MAX(file->maxsize, last->size); + + /* Check if this free block is at the end of file allocated space. + * Truncate it if this is true. */ + if(file->cls->get_eoa) { + haddr_t eoa; + eoa = file->cls->get_eoa(file); + if(eoa == (last->addr+last->size)) { + if(file->cls->set_eoa(file, last->addr) < 0) + HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "set end of space allocation request failed"); + /* Remove this free block from the list */ + file->fl[mapped_type] = last->next; + if(file->maxsize==last->size) + file->maxsize=0; /*unknown*/ + H5FL_FREE(H5FD_free_t, last); + } + } } else if (file->cls->free) { if ((file->cls->free)(file, type, addr, size)<0) HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "driver free request failed"); @@ -2567,12 +2632,12 @@ H5FD_write(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t si if((addr+size)==file->accum_loc) { /* Check if we need more buffer space */ if((size+file->accum_size)>file->accum_buf_size) { + /* Adjust the buffer size, by doubling it */ + file->accum_buf_size = MAX(file->accum_buf_size*2,size+file->accum_size); + /* Reallocate the metadata accumulator buffer */ - if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size+file->accum_size))==NULL) + if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer"); - - /* Note the new buffer size */ - file->accum_buf_size=size+file->accum_size; } /* end if */ /* Move the existing metadata to the proper location */ @@ -2592,12 +2657,12 @@ H5FD_write(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t si else if(addr==(file->accum_loc+file->accum_size)) { /* Check if we need more buffer space */ if((size+file->accum_size)>file->accum_buf_size) { + /* Adjust the buffer size, by doubling it */ + file->accum_buf_size = MAX(file->accum_buf_size*2,size+file->accum_size); + /* Reallocate the metadata accumulator buffer */ - if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,size+file->accum_size))==NULL) + if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer"); - - /* Note the new buffer size */ - file->accum_buf_size=size+file->accum_size; } /* end if */ /* Copy the new metadata to the end */ @@ -2624,12 +2689,12 @@ H5FD_write(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t si /* Check if we need more buffer space */ if(new_size>file->accum_buf_size) { + /* Adjust the buffer size, by doubling it */ + file->accum_buf_size = MAX(file->accum_buf_size*2,new_size); + /* Reallocate the metadata accumulator buffer */ - if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,new_size))==NULL) + if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer"); - - /* Note the new buffer size */ - file->accum_buf_size=new_size; } /* end if */ /* Calculate the proper offset of the existing metadata */ @@ -2655,12 +2720,12 @@ H5FD_write(H5FD_t *file, H5FD_mem_t type, hid_t dxpl_id, haddr_t addr, size_t si /* Check if we need more buffer space */ if(new_size>file->accum_buf_size) { + /* Adjust the buffer size, by doubling it */ + file->accum_buf_size = MAX(file->accum_buf_size*2,new_size); + /* Reallocate the metadata accumulator buffer */ - if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,new_size))==NULL) + if ((file->meta_accum=H5FL_BLK_REALLOC(meta_accum,file->meta_accum,file->accum_buf_size))==NULL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate metadata accumulator buffer"); - - /* Note the new buffer size */ - file->accum_buf_size=new_size; } /* end if */ /* Copy the new metadata to the end */ diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h index 8a8427a..35b3555 100644 --- a/src/H5FLprivate.h +++ b/src/H5FLprivate.h @@ -76,6 +76,7 @@ typedef struct H5FL_reg_head_t { */ #else /* H5_NO_REG_FREE_LISTS */ +#include "H5MMprivate.h" #define H5FL_DEFINE(t) int t##_reg_free_list_placeholder #define H5FL_EXTERN(t) extern int t##_reg_free_list_placeholder #define H5FL_DEFINE_STATIC(t) static H5FL_DEFINE(t) -- cgit v0.12