From ab989cd1a8d5b65120fe88a84b3b925f1b174db8 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sat, 12 Jun 2004 22:11:27 -0500 Subject: [svn-r8670] Purpose: Code optimization Description: Avoid a memory copy by directly reading from the variable-length sequence buffer when there is no type conversion on the way to disk. Platforms tested: Solaris 2.7 (arabica) FreeBSD 4.10 (sleipnir) w/parallel Too minor to require h5committest --- src/H5Tconv.c | 52 +++++++++++++++++++++++----------- src/H5Tpkg.h | 2 ++ src/H5Tvlen.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 16 deletions(-) diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 57ed1c3..8d3e44a 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -2429,6 +2429,7 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, H5T_vlen_alloc_info_t vl_alloc_info;/* VL allocation information */ H5T_path_t *tpath; /* Type conversion path */ hbool_t noop_conv=FALSE; /* Flag to indicate a noop conversion */ + hbool_t write_to_file=FALSE; /* Flag to indicate writing to file */ hid_t tsrc_id = -1, tdst_id = -1;/*temporary type atoms */ H5T_t *src = NULL; /*source data type */ H5T_t *dst = NULL; /*destination data type */ @@ -2442,12 +2443,11 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, hssize_t seq_len; /*the number of elements in the current sequence*/ hsize_t bg_seq_len=0, parent_seq_len=0; size_t src_base_size, dst_base_size;/*source & destination base size*/ - size_t src_size, dst_size; /*source & destination total size in bytes*/ void *conv_buf=NULL; /*temporary conversion buffer */ size_t conv_buf_size=0; /*size of conversion buffer in bytes */ void *tmp_buf=NULL; /*temporary background buffer */ size_t tmp_buf_size=0; /*size of temporary bkg buffer */ - int nested=0; /*flag of nested VL case */ + hbool_t nested=FALSE; /*flag of nested VL case */ hsize_t elmtno; /*element number counter */ hsize_t i; herr_t ret_value=SUCCEED; /* Return value */ @@ -2530,8 +2530,12 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, if(H5T_vlen_get_alloc_info(dxpl_id,&vl_alloc_info)<0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to retrieve VL allocation info"); + /* Set flags to indicate we are writing to or reading from the file */ + if(dst->u.vlen.f!=NULL) + write_to_file=TRUE; + /* Set the flag for nested VL case */ - if(dst->u.vlen.f!=NULL && H5T_detect_class(dst->parent,H5T_VLEN) && bkg!=NULL) + if(write_to_file && H5T_detect_class(dst->parent,H5T_VLEN) && bkg!=NULL) nested=1; /* The outer loop of the type conversion macro, controlling which */ @@ -2580,21 +2584,33 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, /* Get length of element sequences */ if((seq_len=(*(src->u.vlen.getlen))(s))<0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "incorrect length"); - H5_CHECK_OVERFLOW(seq_len,hssize_t,size_t); - src_size=(size_t)seq_len*src_base_size; - dst_size=(size_t)seq_len*dst_base_size; - - /* Check if conversion buffer is large enough, resize if - * necessary */ - if(conv_buf_sizeu.vlen.getptr))(s))==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid source pointer"); } /* end if */ + else { + size_t src_size, dst_size; /*source & destination total size in bytes*/ + + H5_CHECK_OVERFLOW(seq_len,hssize_t,size_t); + src_size=(size_t)seq_len*src_base_size; + dst_size=(size_t)seq_len*dst_base_size; + + /* Check if conversion buffer is large enough, resize if + * necessary */ + if(conv_buf_sizeu.vlen.read))(src->u.vlen.f,dxpl_id,s,conv_buf,src_size)<0) - HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL data"); + /* Read in VL sequence */ + if((*(src->u.vlen.read))(src->u.vlen.f,dxpl_id,s,conv_buf,src_size)<0) + HGOTO_ERROR(H5E_DATATYPE, H5E_READERROR, FAIL, "can't read VL data"); + } /* end else */ if(!noop_conv) { /* Check if temporary buffer is large enough, resize if necessary */ @@ -2672,6 +2688,10 @@ H5T_conv_vlen(hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, hsize_t nelmts, nelmts-=safe; } /* end while */ + /* Reset the conversion buffer pointer, so it doesn't get freed */ + if(write_to_file && noop_conv) + conv_buf=NULL; + /* Release the temporary datatype IDs used */ if (tsrc_id >= 0) H5I_dec_ref(tsrc_id); diff --git a/src/H5Tpkg.h b/src/H5Tpkg.h index 13118e0..68789bb 100644 --- a/src/H5Tpkg.h +++ b/src/H5Tpkg.h @@ -144,6 +144,7 @@ typedef struct H5T_enum_t { /* VL function pointers */ typedef hssize_t (*H5T_vlen_getlenfunc_t)(void *vl_addr); +typedef void * (*H5T_vlen_getptrfunc_t)(void *vl_addr); typedef htri_t (*H5T_vlen_isnullfunc_t)(H5F_t *f, void *vl_addr); typedef herr_t (*H5T_vlen_readfunc_t)(H5F_t *f, hid_t dxpl_id, void *_vl, void *buf, size_t len); typedef herr_t (*H5T_vlen_writefunc_t)(H5F_t *f, hid_t dxpl_id, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *buf, void *_bg, hsize_t seq_len, hsize_t base_size); @@ -165,6 +166,7 @@ typedef struct H5T_vlen_t { H5T_str_t pad; /* For VL string. space or null padding of * extra bytes */ H5F_t *f; /* File ID (if VL data is on disk) */ + H5T_vlen_getptrfunc_t getptr; /* Function to get VL sequence pointer */ H5T_vlen_getlenfunc_t getlen; /* Function to get VL sequence size (in element units, not bytes) */ H5T_vlen_isnullfunc_t isnull; /* Function to check if VL value is NIL */ H5T_vlen_readfunc_t read; /* Function to read VL sequence into buffer */ diff --git a/src/H5Tvlen.c b/src/H5Tvlen.c index a2ef55a..bec8611 100644 --- a/src/H5Tvlen.c +++ b/src/H5Tvlen.c @@ -44,16 +44,19 @@ H5FL_EXTERN(H5T_t); /* Local functions */ static herr_t H5T_vlen_reclaim_recurse(void *elem, const H5T_t *dt, H5MM_free_t free_func, void *free_info); static hssize_t H5T_vlen_seq_mem_getlen(void *_vl); +static void * H5T_vlen_seq_mem_getptr(void *_vl); static htri_t H5T_vlen_seq_mem_isnull(H5F_t *f, void *_vl); static herr_t H5T_vlen_seq_mem_read(H5F_t *f, hid_t dxpl_id, void *_vl, void *_buf, size_t len); static herr_t H5T_vlen_seq_mem_write(H5F_t *f, hid_t dxpl_id, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, hsize_t seq_len, hsize_t base_size); static herr_t H5T_vlen_seq_mem_setnull(H5F_t *f, hid_t dxpl_id, void *_vl, void *_bg); static hssize_t H5T_vlen_str_mem_getlen(void *_vl); +static void * H5T_vlen_str_mem_getptr(void *_vl); static htri_t H5T_vlen_str_mem_isnull(H5F_t *f, void *_vl); static herr_t H5T_vlen_str_mem_read(H5F_t *f, hid_t dxpl_id, void *_vl, void *_buf, size_t len); static herr_t H5T_vlen_str_mem_write(H5F_t *f, hid_t dxpl_id, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, hsize_t seq_len, hsize_t base_size); static herr_t H5T_vlen_str_mem_setnull(H5F_t *f, hid_t dxpl_id, void *_vl, void *_bg); static hssize_t H5T_vlen_disk_getlen(void *_vl); +static void * H5T_vlen_disk_getptr(void *_vl); static htri_t H5T_vlen_disk_isnull(H5F_t *f, void *_vl); static herr_t H5T_vlen_disk_read(H5F_t *f, hid_t dxpl_id, void *_vl, void *_buf, size_t len); static herr_t H5T_vlen_disk_write(H5F_t *f, hid_t dxpl_id, const H5T_vlen_alloc_info_t *vl_alloc_info, void *_vl, void *_buf, void *_bg, hsize_t seq_len, hsize_t base_size); @@ -229,6 +232,7 @@ H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc) /* Set up the function pointers to access the VL sequence in memory */ dt->u.vlen.getlen=H5T_vlen_seq_mem_getlen; + dt->u.vlen.getptr=H5T_vlen_seq_mem_getptr; dt->u.vlen.isnull=H5T_vlen_seq_mem_isnull; dt->u.vlen.read=H5T_vlen_seq_mem_read; dt->u.vlen.write=H5T_vlen_seq_mem_write; @@ -239,6 +243,7 @@ H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc) /* Set up the function pointers to access the VL string in memory */ dt->u.vlen.getlen=H5T_vlen_str_mem_getlen; + dt->u.vlen.getptr=H5T_vlen_str_mem_getptr; dt->u.vlen.isnull=H5T_vlen_str_mem_isnull; dt->u.vlen.read=H5T_vlen_str_mem_read; dt->u.vlen.write=H5T_vlen_str_mem_write; @@ -267,6 +272,7 @@ H5T_vlen_set_loc(H5T_t *dt, H5F_t *f, H5T_loc_t loc) /* Set up the function pointers to access the VL information on disk */ /* VL sequences and VL strings are stored identically on disk, so use the same functions */ dt->u.vlen.getlen=H5T_vlen_disk_getlen; + dt->u.vlen.getptr=H5T_vlen_disk_getptr; dt->u.vlen.isnull=H5T_vlen_disk_isnull; dt->u.vlen.read=H5T_vlen_disk_read; dt->u.vlen.write=H5T_vlen_disk_write; @@ -315,6 +321,34 @@ H5T_vlen_seq_mem_getlen(void *_vl) /*------------------------------------------------------------------------- + * Function: H5T_vlen_seq_mem_getptr + * + * Purpose: Retrieves the pointer for a memory based VL element. + * + * Return: Non-NULL on success/NULL on failure + * + * Programmer: Quincey Koziol + * Saturday, June 12, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5T_vlen_seq_mem_getptr(void *_vl) +{ + hvl_t *vl=(hvl_t *)_vl; /* Pointer to the user's hvl_t information */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_seq_mem_getptr) + + /* check parameters */ + assert(vl); + + FUNC_LEAVE_NOAPI(vl->p) +} /* end H5T_vlen_seq_mem_getptr() */ + + +/*------------------------------------------------------------------------- * Function: H5T_vlen_seq_mem_isnull * * Purpose: Checks if a memory sequence is the "null" sequence @@ -499,6 +533,34 @@ H5T_vlen_str_mem_getlen(void *_vl) /*------------------------------------------------------------------------- + * Function: H5T_vlen_str_mem_getptr + * + * Purpose: Retrieves the pointer for a memory based VL string. + * + * Return: Non-NULL on success/NULL on failure + * + * Programmer: Quincey Koziol + * Saturday, June 12, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5T_vlen_str_mem_getptr(void *_vl) +{ + char *s=*(char **)_vl; /* Pointer to the user's string information */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_str_mem_getptr) + + /* check parameters */ + assert(s); + + FUNC_LEAVE_NOAPI(s) +} /* end H5T_vlen_str_mem_getptr() */ + + +/*------------------------------------------------------------------------- * Function: H5T_vlen_str_mem_isnull * * Purpose: Checks if a memory string is a NULL pointer @@ -669,6 +731,34 @@ H5T_vlen_disk_getlen(void *_vl) /*------------------------------------------------------------------------- + * Function: H5T_vlen_disk_getptr + * + * Purpose: Retrieves the pointer to a disk based VL element. + * + * Return: Non-NULL on success/NULL on failure + * + * Programmer: Quincey Koziol + * Saturday, June 12, 2004 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5T_vlen_disk_getptr(void *_vl) +{ + uint8_t *vl=(uint8_t *)_vl; /* Pointer to the disk VL information */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5T_vlen_disk_getptr) + + /* check parameters */ + assert(vl); + + FUNC_LEAVE_NOAPI(NULL) +} /* end H5T_vlen_disk_getptr() */ + + +/*------------------------------------------------------------------------- * Function: H5T_vlen_disk_isnull * * Purpose: Checks if a disk VL info object is the "nil" object -- cgit v0.12