[svn-r8824] Purpose:

Code optimization

Description:
    Since the raw B-tree nodes are the same size and only used when reading in
or writing out a B-tree node, move raw B-tree node buffer from being per node
to a single node that is shared among all B-tree nodes of a particular tree,
freeing up a lot of space and eliminating lots of memory copies, etc.

Platforms tested:
    Solaris 2.7 (arabica)
    FreeBSD 4.10 (sleipnir) w/parallel
    Too minor to require h5committest
This commit is contained in:
Quincey Koziol
2004-07-07 16:25:33 -05:00
parent 2afbcb2f0e
commit 8d7e8124f1
10 changed files with 405 additions and 416 deletions

579
src/H5B.c

File diff suppressed because it is too large Load Diff

View File

@@ -43,12 +43,6 @@
/*
* The B-tree node as stored in memory...
*/
typedef struct H5B_key_t {
hbool_t dirty; /*native key is more recent than raw key */
uint8_t *rkey; /*ptr into node->page for raw key */
void *nkey; /*null or ptr into node->native for key */
} H5B_key_t;
struct H5B_t {
H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */
/* first field in structure */
@@ -56,14 +50,13 @@ struct H5B_t {
size_t sizeof_node; /*size of raw (disk) node */
size_t sizeof_rkey; /*size of raw (disk) key */
size_t total_native_keysize; /*size of native keys */
unsigned ndirty; /*num child ptrs to emit */
unsigned level; /*node level */
haddr_t left; /*address of left sibling */
haddr_t right; /*address of right sibling */
unsigned nchildren; /*number of child pointers */
uint8_t *page; /*disk page */
uint8_t *raw_page; /*disk page (shared) */
uint8_t *native; /*array of keys in native format */
H5B_key_t *key; /*2k+1 key entries */
void **nkey; /*2k+1 key entries */
haddr_t *child; /*2k child pointers */
};

View File

@@ -84,6 +84,7 @@ typedef struct H5B_class_t {
H5B_subid_t id; /*id as found in file*/
size_t sizeof_nkey; /*size of native (memory) key*/
size_t (*get_sizeof_rkey)(H5F_t*, const void*); /*raw key size */
void * (*get_page)(H5F_t*, const void*); /*raw disk page for node */
herr_t (*new_node)(H5F_t*, hid_t, H5B_ins_t, void*, void*, void*, haddr_t*);
int (*cmp2)(H5F_t*, hid_t, void*, void*, void*); /*compare 2 keys */
int (*cmp3)(H5F_t*, hid_t, void*, void*, void*); /*compare 3 keys */
@@ -111,6 +112,8 @@ typedef struct H5B_class_t {
/*
* Library prototypes.
*/
H5_DLL size_t H5B_nodesize(const H5F_t *f, const H5B_class_t *type,
size_t *total_nkey_size, size_t sizeof_rkey);
H5_DLL herr_t H5B_create (H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, void *udata,
haddr_t *addr_p/*out*/);
H5_DLL herr_t H5B_find (H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr,

View File

@@ -165,6 +165,7 @@ static int H5D_istore_prune_extent(H5F_t *f, hid_t dxpl_id, void *_lt_key, haddr
/* B-tree callbacks */
static size_t H5D_istore_sizeof_rkey(H5F_t *f, const void *_udata);
static void *H5D_istore_get_page(H5F_t *f, const void *_udata);
static herr_t H5D_istore_new_node(H5F_t *f, hid_t dxpl_id, H5B_ins_t, void *_lt_key,
void *_udata, void *_rt_key,
haddr_t *addr_p /*out*/);
@@ -195,6 +196,7 @@ H5B_class_t H5B_ISTORE[1] = {{
H5B_ISTORE_ID, /*id */
sizeof(H5D_istore_key_t), /*sizeof_nkey */
H5D_istore_sizeof_rkey, /*get_sizeof_rkey */
H5D_istore_get_page, /*get_page */
H5D_istore_new_node, /*new */
H5D_istore_cmp2, /*cmp2 */
H5D_istore_cmp3, /*cmp3 */
@@ -217,6 +219,9 @@ H5FL_SEQ_DEFINE_STATIC(H5D_rdcc_ent_ptr_t);
/* Declare a free list to manage the chunk sequence information */
H5FL_BLK_DEFINE_STATIC(chunk);
/* Declare a free list to manage the raw page information */
H5FL_BLK_DEFINE_STATIC(chunk_page);
/*-------------------------------------------------------------------------
* Function: H5D_istore_sizeof_rkey
@@ -255,6 +260,37 @@ H5D_istore_sizeof_rkey(H5F_t UNUSED *f, const void *_udata)
FUNC_LEAVE_NOAPI(nbytes);
} /* end H5D_istore_sizeof_rkey() */
/*-------------------------------------------------------------------------
* Function: H5D_istore_get_page
*
* Purpose: Returns the raw data page for the specified UDATA.
*
* Return: Success: Pointer to the raw B-tree page for this dataset
*
* Failure: Can't fail
*
* Programmer: Quincey Koziol
* Monday, July 5, 2004
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static void *
H5D_istore_get_page(H5F_t UNUSED *f, const void *_udata)
{
const H5D_istore_ud1_t *udata = (const H5D_istore_ud1_t *) _udata;
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_get_page);
assert(udata);
assert(udata->mesg);
assert(udata->mesg->u.chunk.raw_page);
FUNC_LEAVE_NOAPI(udata->mesg->u.chunk.raw_page);
} /* end H5D_istore_get_page() */
/*-------------------------------------------------------------------------
* Function: H5D_istore_decode_key
@@ -651,7 +687,7 @@ done:
*/
static H5B_ins_t
H5D_istore_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key,
hbool_t UNUSED *lt_key_changed,
hbool_t *lt_key_changed,
void *_md_key, void *_udata, void *_rt_key,
hbool_t UNUSED *rt_key_changed,
haddr_t *new_node_p/*out*/)
@@ -866,6 +902,9 @@ H5D_istore_iter_dump (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, hadd
herr_t
H5D_istore_init (H5F_t *f, H5D_t *dset)
{
H5D_istore_ud1_t udata;
size_t sizeof_rkey; /* Single raw key size */
size_t size; /* Raw B-tree node size */
H5D_rdcc_t *rdcc = &(dset->cache.chunk);
herr_t ret_value=SUCCEED; /* Return value */
@@ -880,6 +919,17 @@ H5D_istore_init (H5F_t *f, H5D_t *dset)
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed");
} /* end if */
/* Initialize "user" data for B-tree callbacks, etc. */
udata.mesg = &dset->layout;
/* Set up the "global" information for this dataset's chunks */
sizeof_rkey = H5D_istore_sizeof_rkey(f, &udata);
assert(sizeof_rkey);
size = H5B_nodesize(f, H5B_ISTORE, NULL, sizeof_rkey);
assert(size);
if(NULL==(dset->layout.u.chunk.raw_page=H5FL_BLK_MALLOC(chunk_page,size)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree page")
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5D_istore_init() */
@@ -1158,6 +1208,7 @@ H5D_istore_dest (H5F_t *f, hid_t dxpl_id, H5D_t *dset)
if (H5D_get_dxpl_cache(dxpl_id,&dxpl_cache)<0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
/* Flush all the cached chunks */
for (ent=rdcc->head; ent; ent=next) {
#ifdef H5D_ISTORE_DEBUG
HDfputc('c', stderr);
@@ -1173,6 +1224,9 @@ H5D_istore_dest (H5F_t *f, hid_t dxpl_id, H5D_t *dset)
H5FL_SEQ_FREE (H5D_rdcc_ent_ptr_t,rdcc->slot);
HDmemset (rdcc, 0, sizeof(H5D_rdcc_t));
/* Free the raw B-tree node buffer */
H5FL_BLK_FREE(chunk_page,dset->layout.u.chunk.raw_page);
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5D_istore_dest() */
@@ -1927,7 +1981,9 @@ H5D_istore_create(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout /*out */ )
assert(layout->u.chunk.dim[u] > 0);
#endif
/* Initialize "user" data for B-tree callbacks, etc. */
udata.mesg = layout;
if (H5B_create(f, dxpl_id, H5B_ISTORE, &udata, &(layout->u.chunk.addr)/*out*/) < 0)
HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "can't create B-tree");

View File

@@ -1554,6 +1554,10 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id)
/* Create the file's "open object" information */
if(H5FO_create(f)<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create open object TBBT")
/* Create information needed for group nodes */
if(H5G_node_init(f)<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create group node info")
} /* end else */
f->shared->nrefs++;
@@ -1640,6 +1644,10 @@ H5F_dest(H5F_t *f, hid_t dxpl_id)
ret_value = FAIL; /*but keep going*/
} /* end if */
f->shared->cwfs = H5MM_xfree (f->shared->cwfs);
if (H5G_node_close(f)<0) {
HERROR(H5E_FILE, H5E_CANTRELEASE, "problems closing file");
ret_value = FAIL; /*but keep going*/
} /* end if */
/* Destroy file creation properties */
if(H5I_GENPROP_LST != H5I_get_type(f->shared->fcpl_id))
@@ -4660,6 +4668,39 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_mpi_get_comm() */
#endif /* H5_HAVE_PARALLEL */
/*-------------------------------------------------------------------------
* Function: H5F_raw_page
*
* Purpose: Replaced a macro to retrieve the raw B-tree page value
* now that the generic properties are being used to store
* the values.
*
* Return: Success: Non-void, and the raw B-tree page value
* is returned.
*
* Failure: void (should not happen)
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
* Jul 5 2004
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
void *H5F_raw_page(const H5F_t *f)
{
/* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5F_raw_page)
assert(f);
assert(f->shared);
FUNC_LEAVE_NOAPI(f->shared->raw_page)
} /* end H5F_raw_page() */
/*-------------------------------------------------------------------------
* Function: H5Fget_filesize

View File

@@ -126,6 +126,7 @@ typedef struct H5F_file_t {
struct H5HG_heap_t **cwfs; /* Global heap cache */
H5FO_t *open_objs; /* Open objects in file */
H5F_close_degree_t fc_degree; /* File close behavior degree */
void *raw_page; /* Pointer to raw B-tree node buffer */
} H5F_file_t;
/* A record of the mount table */

View File

@@ -211,6 +211,8 @@ typedef struct H5F_t H5F_t;
#define H5F_RDCC_W0(F) ((F)->shared->rdcc_w0)
/* Check for file driver feature enabled */
#define H5F_HAS_FEATURE(F,FL) ((F)->shared->lf->feature_flags&(FL))
/* B-tree node raw page */
#define H5F_RAW_PAGE(F) ((F)->shared->raw_page)
#else /* H5F_PACKAGE */
#define H5F_SIZEOF_ADDR(F) (H5F_sizeof_addr(F))
#define H5F_SIZEOF_SIZE(F) (H5F_sizeof_size(F))
@@ -220,6 +222,7 @@ typedef struct H5F_t H5F_t;
#define H5F_RDCC_NBYTES(F) (H5F_rdcc_nbytes(F))
#define H5F_RDCC_W0(F) (H5F_rdcc_w0(F))
#define H5F_HAS_FEATURE(F,FL) (H5F_has_feature(F,FL))
#define H5F_RAW_PAGE(F) (H5F_raw_page(F))
#endif /* H5F_PACKAGE */
@@ -414,6 +417,7 @@ H5_DLL hbool_t H5F_has_feature(const H5F_t *f, unsigned feature);
H5_DLL size_t H5F_rdcc_nbytes(const H5F_t *f);
H5_DLL size_t H5F_rdcc_nelmts(const H5F_t *f);
H5_DLL double H5F_rdcc_w0(const H5F_t *f);
H5_DLL void *H5F_raw_page(const H5F_t *f);
/* Functions that operate on blocks of bytes wrt super block */
H5_DLL herr_t H5F_block_read(const H5F_t *f, H5FD_mem_t type, haddr_t addr,

View File

@@ -74,6 +74,7 @@ static herr_t H5G_node_clear(H5G_node_t *sym);
/* B-tree callbacks */
static size_t H5G_node_sizeof_rkey(H5F_t *f, const void *_udata);
static void *H5G_node_get_page(H5F_t *f, const void *_udata);
static herr_t H5G_node_create(H5F_t *f, hid_t dxpl_id, H5B_ins_t op, void *_lt_key,
void *_udata, void *_rt_key,
haddr_t *addr_p/*out*/);
@@ -113,6 +114,7 @@ H5B_class_t H5B_SNODE[1] = {{
H5B_SNODE_ID, /*id */
sizeof(H5G_node_key_t), /*sizeof_nkey */
H5G_node_sizeof_rkey, /*get_sizeof_rkey */
H5G_node_get_page, /*get_page */
H5G_node_create, /*new */
H5G_node_cmp2, /*cmp2 */
H5G_node_cmp3, /*cmp3 */
@@ -133,12 +135,15 @@ static int interface_initialize_g = 0;
/* Declare a free list to manage the H5G_node_t struct */
H5FL_DEFINE_STATIC(H5G_node_t);
/* Declare a free list to manage arrays of H5G_entry_t's */
/* Declare a free list to manage sequences of H5G_entry_t's */
H5FL_SEQ_DEFINE_STATIC(H5G_entry_t);
/* Declare a free list to manage blocks of symbol node data */
H5FL_BLK_DEFINE_STATIC(symbol_node);
/* Declare a free list to manage the raw page information */
H5FL_BLK_DEFINE_STATIC(grp_page);
/*-------------------------------------------------------------------------
* Function: H5G_node_sizeof_rkey
@@ -167,6 +172,34 @@ H5G_node_sizeof_rkey(H5F_t *f, const void UNUSED * udata)
FUNC_LEAVE_NOAPI(H5F_SIZEOF_SIZE(f)); /*the name offset */
}
/*-------------------------------------------------------------------------
* Function: H5G_node_get_page
*
* Purpose: Returns the raw data page for the specified UDATA.
*
* Return: Success: Pointer to the raw B-tree page for this
file's groups
*
* Failure: Can't fail
*
* Programmer: Robb Matzke
* Wednesday, October 8, 1997
*
* Modifications:
*
*-------------------------------------------------------------------------
*/
static void *
H5G_node_get_page(H5F_t *f, const void UNUSED *_udata)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_get_page);
assert(f);
FUNC_LEAVE_NOAPI(H5F_RAW_PAGE(f));
} /* end H5G_node_get_page() */
/*-------------------------------------------------------------------------
* Function: H5G_node_decode_key
@@ -298,7 +331,7 @@ H5G_node_size(H5F_t *f)
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_size);
FUNC_LEAVE_NOAPI(H5G_NODE_SIZEOF_HDR(f) +
(2 * H5F_SYM_LEAF_K(f)) * H5G_SIZEOF_ENTRY(f));
(2 * H5F_SYM_LEAF_K(f)) * H5G_SIZEOF_ENTRY(f));
}
@@ -477,8 +510,7 @@ H5G_node_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5G_node_
if (H5F_block_write(f, H5FD_MEM_BTREE, addr, size, dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "unable to write symbol table node to the file");
if (buf)
H5FL_BLK_FREE(symbol_node,buf);
H5FL_BLK_FREE(symbol_node,buf);
/* Reset the node's dirty flag */
sym->cache_info.dirty = FALSE;
@@ -969,6 +1001,7 @@ H5G_node_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void UNUSED *_lt_key,
HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_INS_ERROR, "unable to split symbol table node");
if (NULL==(snrt=H5AC_find(f, dxpl_id, H5AC_SNODE, *new_node_p, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_INS_ERROR, "unable to split symbol table node");
HDmemcpy(snrt->entry, sn->entry + H5F_SYM_LEAF_K(f),
H5F_SYM_LEAF_K(f) * sizeof(H5G_entry_t));
snrt->nsyms = H5F_SYM_LEAF_K(f);
@@ -1287,6 +1320,7 @@ H5G_node_iterate (H5F_t *f, hid_t dxpl_id, void UNUSED *_lt_key, haddr_t addr,
name = H5HL_peek (f, dxpl_id, bt_udata->ent->cache.stab.heap_addr, name_off[i]);
assert (name);
n = HDstrlen (name);
if (n+1>sizeof(buf)) {
if (NULL==(s = H5MM_malloc (n+1)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, H5B_ITER_ERROR, "memory allocation failed");
@@ -1347,8 +1381,9 @@ H5G_node_sumup(H5F_t *f, hid_t dxpl_id, void UNUSED *_lt_key, haddr_t addr,
/* Find the object node and add the number of symbol entries. */
if (NULL == (sn = H5AC_find(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL)))
HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node");
*num_objs += sn->nsyms;
done:
FUNC_LEAVE_NOAPI(ret_value);
}
@@ -1405,7 +1440,7 @@ H5G_node_name(H5F_t *f, hid_t dxpl_id, void UNUSED *_lt_key, haddr_t addr,
}
bt_udata->num_objs += sn->nsyms;
done:
FUNC_LEAVE_NOAPI(ret_value);
}
@@ -1458,6 +1493,79 @@ done:
FUNC_LEAVE_NOAPI(ret_value);
}
/*-------------------------------------------------------------------------
* Function: H5G_node_init
*
* Purpose: This function gets called during a file opening to initialize
* global information about group B-tree nodes for file.
*
* Return: Non-negative on success
* Negative on failure
*
* Programmer: Quincey Koziol
* Jul 5, 2004
*
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_node_init(H5F_t *f)
{
size_t sizeof_rkey; /* Single raw key size */
size_t size; /* Raw B-tree node size */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(H5G_node_init, FAIL);
/* Check arguments. */
assert(f);
/* Set up the "global" information for this file's groups */
sizeof_rkey = H5G_node_sizeof_rkey(f, NULL);
assert(sizeof_rkey);
size = H5B_nodesize(f, H5B_SNODE, NULL, sizeof_rkey);
assert(size);
if(NULL==(f->shared->raw_page=H5FL_BLK_MALLOC(grp_page,size)))
HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree page")
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5G_node_init() */
/*-------------------------------------------------------------------------
* Function: H5G_node_close
*
* Purpose: This function gets called during a file close to shutdown
* global information about group B-tree nodes for file.
*
* Return: Non-negative on success
* Negative on failure
*
* Programmer: Quincey Koziol
* Jul 5, 2004
*
*
*-------------------------------------------------------------------------
*/
herr_t
H5G_node_close(const H5F_t *f)
{
herr_t ret_value=SUCCEED;
FUNC_ENTER_NOAPI(H5G_node_close,FAIL)
/* Check arguments. */
assert(f);
/* Free the raw B-tree node buffer */
H5FL_BLK_FREE(grp_page,f->shared->raw_page);
done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5G_node_close */
/*-------------------------------------------------------------------------
* Function: H5G_node_debug
@@ -1537,4 +1645,3 @@ H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent,
done:
FUNC_LEAVE_NOAPI(ret_value);
}

View File

@@ -161,6 +161,8 @@ H5_DLL herr_t H5G_free_grp_name(H5G_t *grp);
*/
H5_DLL herr_t H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream,
int indent, int fwidth, haddr_t heap);
H5_DLL herr_t H5G_node_init(H5F_t *f);
H5_DLL herr_t H5G_node_close(const H5F_t *f);
/*
* These functions operate on symbol table entries. They're used primarily

View File

@@ -133,6 +133,7 @@ typedef struct H5O_layout_chunk_t {
unsigned ndims; /* Num dimensions in chunk */
size_t dim[H5O_LAYOUT_NDIMS]; /* Size of chunk in elements */
size_t size; /* Size of chunk in bytes */
void *raw_page; /* Buffer for raw B-tree page */
} H5O_layout_chunk_t;
typedef struct H5O_layout_compact_t {