summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/vfd_swmr_gperf_writer.c335
1 files changed, 239 insertions, 96 deletions
diff --git a/test/vfd_swmr_gperf_writer.c b/test/vfd_swmr_gperf_writer.c
index a64af45..e0a9b43 100644
--- a/test/vfd_swmr_gperf_writer.c
+++ b/test/vfd_swmr_gperf_writer.c
@@ -54,10 +54,12 @@ typedef struct {
uint32_t max_lag;
uint32_t tick_len;
bool gperf;
- double min_time;
- double max_time;
- double mean_time;
+ double min_gc_time;
+ double max_gc_time;
+ double mean_gc_time;
+ double total_gc_time;
double total_time;
+ double mean_time;
double fo_total_time;
double fc_total_time;
unsigned int num_attrs;
@@ -71,38 +73,41 @@ typedef struct {
(state_t) \
{ \
.file = H5I_INVALID_HID, .one_by_one_sid = H5I_INVALID_HID, .filename = "", \
- .filetype = H5T_NATIVE_UINT32, .asteps = 10, .nsteps = 100, .use_vfd_swmr = true, \
+ .filetype = H5T_NATIVE_UINT32, .asteps = 1, .nsteps = 100, .use_vfd_swmr = true, \
.old_style_grp = false, .grp_op_pattern = ' ', .grp_op_test = false, .at_pattern = ' ', \
- .attr_test = false, .tick_len = 4, .max_lag = 7, .gperf = false, .min_time = 100., .max_time = 0., \
- .mean_time = 0., .total_time = 0., .fo_total_time = 0., .fc_total_time = 0., .num_attrs = 1, \
- .vlstr_test = false, .ps = 4096, .pbs = 4096, .nglevels = 0 \
+ .attr_test = false, .tick_len = 4, .max_lag = 7, .gperf = false, .min_gc_time = 100., \
+ .max_gc_time = 0., .mean_gc_time = 0., .total_gc_time = 0., .total_time = 0., .mean_time = 0., \
+ .fo_total_time = 0., .fc_total_time = 0., .num_attrs = 1, .vlstr_test = false, \
+ .ps = 4096, .pbs = 4096, .nglevels =0 \
}
static void
usage(const char *progname)
{
fprintf(stderr,
- "usage: %s [-P] [-S] [-G] [-a steps] [-t tick_len] [-m max_lag][-B pbs] [-s ps]\n"
- " [-b] [-n ngroups]\n"
- " [-N num_attrs] [-l ng_levels] [-q] [-A at_pattern] [-O grp_op_pattern]\n"
+ "usage: ./%s -P -n 1000 -N 5 -q (create 1000 groups, each group has 5 attributes)\n"
+ "Options: \n"
+ " [-P] [-S] [-G] [-t tick_len] [-m max_lag][-B pbs] [-s ps]\n"
+ " [-n ngroups] [-l ng_levels] [-O grp_op_pattern]\n"
+ " [-N num_attrs] [-V] [-b] [-A at_pattern] [-a steps] [-q]\n"
"\n"
"-P: carry out the performance test\n"
"-S: do not use VFD SWMR\n"
"-G: old-style type of group\n"
- "-a steps: `steps` between adding attributes\n"
"-t tick_len: length of a tick in tenths of a second.\n"
"-m max_lag: maximum expected lag(in ticks) between writer and readers\n"
- "-B pbs: Page Buffer Size in bytes:\n"
+ "-B pbs: page Buffer Size in bytes:\n"
" The default value is 4K(4096).\n"
- "-s ps: Page size used by page aggregation, page buffer and \n"
+ "-s ps: page size used by page aggregation, page buffer and \n"
" the metadata file. \n"
- "-b: write data in big-endian byte order\n"
"-n ngroups: the number of groups\n"
- "-N num_attrs: the number of attributes \n"
- "-V vlstr attrs: Use variable length string attribute in the performance test. \n"
"-l ng_levels: the number of level of nested groups. \n"
" If all the groups are under the root group, \n"
" this number should be 0.\n"
+ "-N num_attrs: the number of attributes \n"
+ "-V use variable length string attributes for performance test\n"
+ "-b: write data in big-endian byte order\n"
+ " (For the performance test, -V overwrites -b)\n"
"-A at_pattern: `at_pattern' for different attribute tests\n"
" The value of `at_pattern` is one of the following:\n"
" `compact` - Attributes added in compact storage\n"
@@ -156,6 +161,8 @@ usage(const char *progname)
" dense to compact again. \n"
" The links include both hard and\n"
" soft links. \n"
+ "-a steps: `steps` between adding attributes\n"
+ " (Don't recommend to use this option for performance test.)\n"
"-q: silence printouts, few messages\n"
"\n",
progname);
@@ -1587,11 +1594,11 @@ write_group(state_t *s, unsigned int which)
}
temp_time = TIME_PASSED(start_time, end_time);
- if (temp_time < s->min_time)
- s->min_time = temp_time;
- if (temp_time > s->max_time)
- s->max_time = temp_time;
- s->total_time += temp_time;
+ if (temp_time < s->min_gc_time)
+ s->min_gc_time = temp_time;
+ if (temp_time > s->max_gc_time)
+ s->max_gc_time = temp_time;
+ s->total_gc_time += temp_time;
}
/* We need to create a dummy dataset for the object header continuation block test. */
@@ -1602,24 +1609,27 @@ write_group(state_t *s, unsigned int which)
TEST_ERROR;
}
}
- if (H5Gget_info(g, &group_info) < 0) {
- printf("H5Gget_info failed\n");
- TEST_ERROR;
- }
-
- if (s->old_style_grp) {
- if (group_info.storage_type != H5G_STORAGE_TYPE_SYMBOL_TABLE) {
- printf("Old-styled group test: but the group is not in old-style. \n");
+ /* We only need to check the first group */
+ if(which == 0) {
+ if (H5Gget_info(g, &group_info) < 0) {
+ printf("H5Gget_info failed\n");
TEST_ERROR;
}
- dbgf(2, "Writer: group is created with the old-style.\n");
- }
- else {
- if (group_info.storage_type == H5G_STORAGE_TYPE_SYMBOL_TABLE) {
- printf("The created group should NOT be in old-style . \n");
- TEST_ERROR;
+
+ if (s->old_style_grp) {
+ if (group_info.storage_type != H5G_STORAGE_TYPE_SYMBOL_TABLE) {
+ printf("Old-styled group test: but the group is not in old-style. \n");
+ TEST_ERROR;
+ }
+ dbgf(2, "Writer: group is created with the old-style.\n");
+ }
+ else {
+ if (group_info.storage_type == H5G_STORAGE_TYPE_SYMBOL_TABLE) {
+ printf("The created group should NOT be in old-style . \n");
+ TEST_ERROR;
+ }
+ dbgf(2, "Writer: group is created with the new-style.\n");
}
- dbgf(2, "Writer: group is created with the new-style.\n");
}
/* If coming to an "object header continuation block" test,
@@ -2480,6 +2490,24 @@ group_operations(state_t *s, unsigned int which)
}
static unsigned int grp_counter = 0;
+
+/*-------------------------------------------------------------------------
+ * Function: UI_Pow
+ *
+ * Purpose: Helper function to obtain the power 'n' of
+ * an unsigned integer 'x'
+ * Similar to pow(x,y) but for an unsigned integer.
+ *
+ * Parameters: unsigned int x
+ * unsigned int n
+ *
+ * Return: Return an unsigned integer of value of pow(x,n)
+ * Note: If the returned value is > 2^32-1, an overflow
+ * may occur. For our testing purpose, this may never happen.
+ *
+ *-------------------------------------------------------------------------
+ */
+
static unsigned int
UI_Pow(unsigned int x, unsigned int n)
{
@@ -2492,17 +2520,55 @@ UI_Pow(unsigned int x, unsigned int n)
return (number);
}
+/*-------------------------------------------------------------------------
+ * Function: obtain_tree_level_elems
+ *
+ * Purpose: Helper function to obtain the maximum number of elements
+ * at one level.
+ *
+ * Parameters: unsigned int total_ele
+ * The total number of elements of a tree(excluding the root)
+ *
+ * unsigned int level
+ * The number of nested levels
+ * (If every element of the tree is under the root,
+ * the level is 0.)
+ *
+ * Return: Return the maximum number of elements at one level
+ *
+ * Example: If the total number of elements is 6 and level is 1,
+ * the maximum number of elements is 2.The tree is
+ * a perfectly balanced tree.
+ * Such as:
+ * 0
+ * 1 2
+ * 3 4 5 6
+ *
+ * If the total number of elements is 5 and level is 1,
+ * the maximum number of elements is still 2. The
+ * tree is not balanced, there is no element on the
+ * right-most leaf but the level is still 1.
+ * Such as:
+ * 0
+ * 1 2
+ * 3 4 5
+ *
+ *-------------------------------------------------------------------------
+ */
+
static unsigned int
obtain_tree_level_elems(unsigned int total_ele, unsigned int level)
{
assert(level <= total_ele);
+ /* if every element is under the root, just return the total number of elements. */
if (level == 0)
return total_ele;
else {
unsigned int test_elems_level = 0;
unsigned total = 0;
unsigned int i = 1;
+ /* Obtain the maximum number of elements for a level with the brutal force way. */
while (total < total_ele) {
test_elems_level++;
total = 0;
@@ -2510,11 +2576,32 @@ obtain_tree_level_elems(unsigned int total_ele, unsigned int level)
total += UI_Pow(test_elems_level, i);
}
if (total == total_ele)
- printf("Perfectly match: Number of elements per level is %u\n", test_elems_level);
+ dbgf(2, "Perfectly match: Number of elements per level is %u\n", test_elems_level);
return test_elems_level;
}
}
+/*-------------------------------------------------------------------------
+ * Function: gen_tree_struct
+ *
+ * Purpose: Generate the nested groups
+ *
+ * Parameters: state_t *s
+ * The struct that stores information of HDF5 file, named pipe
+ * and some VFD SWMR configuration parameters
+ *
+ * unsigned int level
+ * The number of nested levels +1
+ * (Note: If every element of the tree is under the root,
+ * the level is 1 in this function.)
+ * unsigned num_elems_per_level
+ * The maximum number of element in a level
+ * hid_t group_id
+ * The ID of the parent group
+ *
+ * Return: Success: true
+ * Failure: false
+ */
static bool
gen_tree_struct(state_t *s, unsigned int level, unsigned ne_per_level, hid_t pgrp_id)
{
@@ -2524,6 +2611,9 @@ gen_tree_struct(state_t *s, unsigned int level, unsigned ne_per_level, hid_t pgr
hid_t grp_id;
bool result = true;
H5G_info_t group_info;
+ struct timespec start_time, end_time;
+ double temp_time;
+
if (level > 0 && grp_counter < s->nsteps) {
@@ -2531,6 +2621,16 @@ gen_tree_struct(state_t *s, unsigned int level, unsigned ne_per_level, hid_t pgr
esnprintf(name, sizeof(name), "group-%u", grp_counter);
if (grp_counter == s->nsteps)
break;
+
+ dbgf(2, "writer in nested group: step %d\n", grp_counter);
+ if (s->gperf) {
+
+ if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) {
+ fprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
+ }
+ }
+
/* For each i a group is created.
Use grp_counter to generate the group name.
printf("id: %u,level: %u, index: %u\n",id,level,i);
@@ -2540,6 +2640,23 @@ gen_tree_struct(state_t *s, unsigned int level, unsigned ne_per_level, hid_t pgr
TEST_ERROR;
}
+ if (s->gperf) {
+
+ if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) {
+
+ fprintf(stderr, "HDclock_gettime failed");
+
+ TEST_ERROR;
+ }
+
+ temp_time = TIME_PASSED(start_time, end_time);
+ if (temp_time < s->min_gc_time)
+ s->min_gc_time = temp_time;
+ if (temp_time > s->max_gc_time)
+ s->max_gc_time = temp_time;
+ s->total_gc_time += temp_time;
+ }
+
/* Just check the first group information. */
if (grp_counter == 0) {
if (H5Gget_info(grp_id, &group_info) < 0) {
@@ -2640,24 +2757,12 @@ main(int argc, char **argv)
* as the second parameter of H5Pset_libver_bound() that is called by
* vfd_swmr_create_fapl. Otherwise, the latest file format(H5F_LIBVER_LATEST)
* should be used as the second parameter of H5Pset_libver_bound().
- * Also pass the use_vfd_swmr, only_meta_page, config to vfd_swmr_create_fapl().*/
+ * Also pass the use_vfd_swmr, only_meta_page, page buffer size, config to vfd_swmr_create_fapl().*/
if ((fapl = vfd_swmr_create_fapl(!s.old_style_grp, s.use_vfd_swmr, true, s.pbs, &config)) < 0) {
printf("vfd_swmr_create_fapl failed\n");
TEST_ERROR;
}
-#if 0
- if ((fcpl = H5Pcreate(H5P_FILE_CREATE)) < 0) {
- printf("H5Pcreate failed\n");
- TEST_ERROR;
- }
-
- if (H5Pset_file_space_strategy(fcpl, H5F_FSPACE_STRATEGY_PAGE, false, 1) < 0) {
- printf("H5Pset_file_space_strategy failed\n");
- TEST_ERROR;
- }
-#endif
-
/* Set fs_strategy (file space strategy) and fs_page_size (file space page size) */
if ((fcpl = vfd_swmr_create_fcpl(H5F_FSPACE_STRATEGY_PAGE, s.ps)) < 0) {
HDprintf("vfd_swmr_create_fcpl() failed");
@@ -2675,86 +2780,76 @@ main(int argc, char **argv)
if (s.gperf) {
if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) {
-
fprintf(stderr, "HDclock_gettime failed");
-
TEST_ERROR;
}
}
- if (writer)
- s.file = H5Fcreate(s.filename, H5F_ACC_TRUNC, fcpl, fapl);
- else
- s.file = H5Fopen(s.filename, H5F_ACC_RDONLY, fapl);
+ s.file = H5Fcreate(s.filename, H5F_ACC_TRUNC, fcpl, fapl);
if (s.gperf) {
if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) {
-
fprintf(stderr, "HDclock_gettime failed");
-
TEST_ERROR;
}
s.fo_total_time = TIME_PASSED(start_time, end_time);
- fprintf(stdout, "H5Fopen time = %lf\n", s.fo_total_time);
}
-
if (s.file < 0) {
- printf("H5Fcreate/open failed\n");
+ printf("H5Fcreate failed\n");
TEST_ERROR;
}
- if (writer) {
- if (s.gperf) {
+ /* If generating nested groups, calculate the maximum number of
+ elements per level. */
+ if (s.nglevels > 0)
+ num_elems_per_level = obtain_tree_level_elems(s.nsteps, s.nglevels);
- if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) {
- fprintf(stderr, "HDclock_gettime failed");
+ if (s.gperf) {
- TEST_ERROR;
- }
+ if (HDclock_gettime(CLOCK_MONOTONIC, &start_time) == -1) {
+ fprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
}
+ }
+
+ /* If generating nested groups */
+ if (s.nglevels > 0) {
- if (s.nglevels > 0) {
+ /* for the recursive call, the groups under the root is treated as one level */
+ wg_ret = gen_tree_struct(&s, s.nglevels + 1, num_elems_per_level, s.file);
+ if (wg_ret == false) {
+ printf("write nested group failed at group counter %u\n", grp_counter);
+ TEST_ERROR;
+ }
+ }
+ else {
+ for (step = 0; step < s.nsteps; step++) {
- num_elems_per_level = obtain_tree_level_elems(s.nsteps, s.nglevels);
- /* for the recursive call, the groups under the root is treated as one level */
- wg_ret = gen_tree_struct(&s, s.nglevels + 1, num_elems_per_level, s.file);
+ dbgf(2, "writer: step %d\n", step);
+ wg_ret = group_operations(&s, step);
if (wg_ret == false) {
- printf("write nested group failed at group counter %u\n", grp_counter);
+ printf("write_group failed at step %d\n", step);
TEST_ERROR;
}
}
- else {
- for (step = 0; step < s.nsteps; step++) {
-
- dbgf(2, "writer: step %d\n", step);
- wg_ret = group_operations(&s, step);
- if (wg_ret == false) {
- printf("write_group failed at step %d\n", step);
- TEST_ERROR;
- }
- }
- }
-
- if (s.gperf) {
+ }
- if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) {
+ if (s.gperf) {
- fprintf(stderr, "HDclock_gettime failed");
- TEST_ERROR;
- }
+ if (HDclock_gettime(CLOCK_MONOTONIC, &end_time) == -1) {
- s.total_time = TIME_PASSED(start_time, end_time);
- s.mean_time = s.total_time / s.nsteps;
- fprintf(stdout, "group creation +5 attrs total time = %lf\n", s.total_time);
- fprintf(stdout, "group creation +5 attrs mean time = %lf\n", s.mean_time);
+ fprintf(stderr, "HDclock_gettime failed");
+ TEST_ERROR;
}
- }
- else
- printf("Reader is skipped for the performance tests.\n");
+ s.total_time = TIME_PASSED(start_time, end_time);
+ s.mean_time = s.total_time / s.nsteps;
+ s.mean_gc_time = s.total_gc_time/s.nsteps;
+ }
+
if (H5Pclose(fapl) < 0) {
printf("H5Pclose failed\n");
TEST_ERROR;
@@ -2795,7 +2890,55 @@ main(int argc, char **argv)
}
s.fc_total_time = TIME_PASSED(start_time, end_time);
+ }
+
+ /* Performance statistics summary */
+ if(s.gperf) {
+
+ if (verbosity !=0) {
+
+ fprintf(stdout, "\nPerformance Test Configuration: ");
+ if(s.use_vfd_swmr)
+ fprintf(stdout, " Using VFD SWMR \n");
+ else
+ fprintf(stdout, " Not using VFD SWMR \n");
+
+ if(s.old_style_grp)
+ fprintf(stdout, " Groups: Created via the earlist file format(old-style) \n");
+ else
+ fprintf(stdout, " Groups: Created via the latest file format(new-style) \n");
+
+ fprintf(stdout, "\n");
+
+ fprintf(stdout, "The length of a tick = %u\n",s.tick_len);
+ fprintf(stdout, "The maximum expected log(in ticks)= %u\n",s.max_lag);
+ fprintf(stdout, "The page size(in bytes) = %u\n",s.ps);
+ fprintf(stdout, "The page buffer size(in bytes) = %u\n",s.pbs);
+ fprintf(stdout, "\n");
+ fprintf(stdout, "Number of groups = %u\n" ,s.nsteps);
+ fprintf(stdout, "Group Nested levels = %u\n", s.nglevels);
+ fprintf(stdout, "Number of attributes = %u\n", s.num_attrs);
+ fprintf(stdout, "Number of element per attribute = 1\n");
+ if(s.vlstr_test)
+ fprintf(stdout, "Attribute datatype is variable length string. \n");
+ else if(s.filetype == H5T_STD_U32BE)
+ fprintf(stdout, "Attribute datatype is big-endian unsigned 32-bit integer.\n");
+ else
+ fprintf(stdout, "Attribute datatype is native unsigned 32-bit integer.\n");
+
+ fprintf(stdout, "\n");
+ fprintf(stdout, "(If the nested level is 0, all the groups are created directly under the root.)\n\n");
+ fprintf(stdout, "group creation maximum time =%lf\n", s.max_gc_time);
+ fprintf(stdout, "group creation minimum time =%lf\n", s.min_gc_time);
+ }
+
+ fprintf(stdout, "group creation total time = %lf\n", s.total_gc_time);
+ fprintf(stdout, "group creation mean time(per group) = %lf\n", s.mean_gc_time);
+ fprintf(stdout, "group creation and attributes generation total time = %lf\n", s.total_time);
+ fprintf(stdout, "group creation and attributes generation mean time(per group) = %lf\n",s.mean_time);
+ fprintf(stdout, "H5Fcreate time = %lf\n", s.fo_total_time);
fprintf(stdout, "H5Fclose time = %lf\n", s.fc_total_time);
+
}
return EXIT_SUCCESS;