diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 24fe4c11750..3bd3e011c1d 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -356,6 +356,15 @@ New Features Library: -------- + - Improved performance of H5Sget_select_elem_pointlist + + Modified library to cache the point after the last block of points + retrieved by H5Sget_select_elem_pointlist, so a subsequent call to the + same function to retrieve the next block of points from the list can + proceed immediately without needing to iterate over the point list. + + (NAF - 2021/01/19) + - Replaced H5E_ATOM with H5E_ID in H5Epubgen.h The term "atom" is archaic and not in line with current HDF5 library diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 8b1922be82d..5fe87950977 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -137,6 +137,11 @@ struct H5S_pnt_list_t { H5S_pnt_node_t *head; /* Pointer to head of point list */ H5S_pnt_node_t *tail; /* Pointer to tail of point list */ + + hsize_t last_idx; /* Index of the point after the last returned from H5S__get_select_elem_pointlist() */ + H5S_pnt_node_t *last_idx_pnt; /* Point after the last returned from H5S__get_select_elem_pointlist(). + * If we ever add a way to remove points or add points in the middle of + * the pointlist we will need to invalidate these fields. */ }; /* Information about hyperslab spans */ diff --git a/src/H5Spoint.c b/src/H5Spoint.c index c58e7a76811..6cb5d9bd5ba 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -843,6 +843,10 @@ H5S__copy_pnt_list(const H5S_pnt_list_t *src, unsigned rank) H5MM_memcpy(dst->high_bounds, src->high_bounds, (rank * sizeof(hsize_t))); H5MM_memcpy(dst->low_bounds, src->low_bounds, (rank * sizeof(hsize_t))); + /* Clear cached iteration point */ + dst->last_idx = 0; + dst->last_idx_pnt = NULL; + /* Set return value */ ret_value = dst; @@ -1511,6 +1515,7 @@ H5S__point_deserialize(H5S_t **space, const uint8_t **p) static herr_t H5S__get_select_elem_pointlist(const H5S_t *space, hsize_t startpoint, hsize_t numpoints, hsize_t *buf) { + const hsize_t endpoint = startpoint + numpoints; /* Index of last point in iteration */ H5S_pnt_node_t *node; /* Point node */ unsigned rank; /* Dataspace rank */ @@ -1522,14 +1527,20 @@ H5S__get_select_elem_pointlist(const H5S_t *space, hsize_t startpoint, hsize_t n /* Get the dataspace extent rank */ rank = space->extent.rank; - /* Get the head of the point list */ - node = space->select.sel_info.pnt_lst->head; + /* Check for cached point at the correct index */ + if(space->select.sel_info.pnt_lst->last_idx_pnt + && startpoint == space->select.sel_info.pnt_lst->last_idx) + node = space->select.sel_info.pnt_lst->last_idx_pnt; + else { + /* Get the head of the point list */ + node = space->select.sel_info.pnt_lst->head; - /* Iterate to the first point to return */ - while (node != NULL && startpoint > 0) { - startpoint--; - node = node->next; - } /* end while */ + /* Iterate to the first point to return */ + while (node != NULL && startpoint > 0) { + startpoint--; + node = node->next; + } /* end while */ + } /* end else */ /* Iterate through the node, copying each point's information */ while (node != NULL && numpoints > 0) { @@ -1539,6 +1550,10 @@ H5S__get_select_elem_pointlist(const H5S_t *space, hsize_t startpoint, hsize_t n node = node->next; } /* end while */ + /* Cached next point in iteration */ + space->select.sel_info.pnt_lst->last_idx = endpoint; + space->select.sel_info.pnt_lst->last_idx_pnt = node; + FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5S__get_select_elem_pointlist() */ @@ -2331,6 +2346,10 @@ H5S__point_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *of } /* end for */ } /* end else */ + /* Clear cached iteration point */ + new_space->select.sel_info.pnt_lst->last_idx = 0; + new_space->select.sel_info.pnt_lst->last_idx_pnt = NULL; + /* Number of elements selected will be the same */ new_space->select.num_elem = base_space->select.num_elem;