1 /* This is part of the netCDF package. Copyright 2018 University
2  * Corporation for Atmospheric Research/Unidata. See COPYRIGHT file
3  * for conditions of use.
4  *
5  * Test the netCDF-4 attribute code.
6  *
7  * WARNING: do not attempt to run this under windows because of the use
8  * of gettimeofday().
9  *
10  * Ed Hartnett 6/19/18
11 */
12 
13 #include <config.h>
14 #include <nc_tests.h>
15 #include "err_macros.h"
16 #include "nc4internal.h"
17 #include <sys/time.h>
18 #include <hdf5.h>
19 
20 #define TEST "tst_attsperf"
21 #define VAR "bigvar"
22 #define NDIMS 2
23 #define DIM0 "d0"
24 #define DIM1 "d1"
25 #define DIMSIZE0 16
26 #define DIMSIZE1 512
27 #define TOTALSIZE (DIMSIZE0 * DIMSIZE1)
28 #define NUM_ATTS 100
29 #define ATT_LEN 100
30 #define NUM_VARS 1
31 
32 int
add_attributes(int ncid,int varid,size_t num_atts,size_t att_len)33 add_attributes(int ncid, int varid, size_t num_atts, size_t att_len)
34 {
35    char att_name[NC_MAX_NAME + 1];
36    double *att_data;
37    int i, a;
38 
39    /* Allocate space for attribute data. */
40    if (!(att_data = malloc(att_len * sizeof(double))))
41       return NC_ENOMEM;
42 
43    /* Fill up data. */
44    for (i = 0; i < ATT_LEN; i++)
45       att_data[i] = i;
46 
47    /* Write a bunch of attributes. */
48    for (a = 0; a < num_atts; a++)
49    {
50       sprintf(att_name, "%s_varid_%d_att_%d", TEST, varid, a);
51       if (nc_put_att_double(ncid, varid, att_name, NC_DOUBLE,
52                             att_len, att_data)) ERR;
53    }
54 
55    free(att_data);
56 
57    return 0;
58 }
59 
60 /* Build the test file. */
61 int
buildfile(size_t num_vars,size_t num_atts,size_t att_len,char * file_name)62 buildfile(size_t num_vars, size_t num_atts, size_t att_len,
63           char *file_name)
64 {
65    int ncid, varid;
66    int dimids[NDIMS];
67    int v;
68 
69    if (nc_create(file_name, NC_NETCDF4, &ncid)) ERR;
70 
71    if (nc_def_dim(ncid, DIM0, DIMSIZE0, &dimids[0])) ERR;
72    if (nc_def_dim(ncid, DIM1, DIMSIZE1, &dimids[1])) ERR;
73    for (v = 0; v < num_vars; v++)
74    {
75       char var_name[NC_MAX_NAME + 1];
76       sprintf(var_name, "%s_var_%d", TEST, v);
77       if (nc_def_var(ncid, var_name, NC_INT, NDIMS, dimids, &varid)) ERR;
78       if (add_attributes(ncid, v, num_atts, att_len)) ERR;
79    }
80    if (!num_vars)
81       if (add_attributes(ncid, NC_GLOBAL, num_atts, att_len)) ERR;
82    if (nc_enddef(ncid)) ERR;
83 
84    if (nc_close(ncid)) ERR;
85    return 0;
86 }
87 
88 /* Open/close the file with netCDF. */
89 int
readfile(char * file_name,long long * delta,int do_inq,int num_vars)90 readfile(char *file_name, long long *delta, int do_inq, int num_vars)
91 {
92    int ncid;
93    struct timeval starttime, endtime;
94    long long startt, endt;
95    int natts;
96    int v;
97 
98    /* Start the clock. */
99    gettimeofday(&starttime, NULL);
100 
101    /* Open the file. */
102    if (nc_open(file_name, NC_NETCDF4, &ncid)) ERR;
103 
104    /* Do an inq if desired, triggering read of atts. */
105    for (v = 0; v < num_vars; v++)
106       if (nc_inq_varnatts(ncid, v, &natts)) ERR;
107 
108    if (nc_inq_natts(ncid, &natts)) ERR;
109 
110    /* Close the file. */
111    if (nc_close(ncid)) ERR;
112 
113    gettimeofday(&endtime, NULL);
114 
115    /* Compute the time delta */
116    startt = (1000000 * starttime.tv_sec) + starttime.tv_usec;
117    endt = (1000000 * endtime.tv_sec) + endtime.tv_usec;
118    *delta = endt - startt;
119 
120    return 0;
121 }
122 
123 /* Open/close the file with HDF5. */
124 int
readfile_hdf5(char * file_name,long long * delta,int do_inq,int num_vars)125 readfile_hdf5(char *file_name, long long *delta, int do_inq, int num_vars)
126 {
127    hid_t hdfid, hdf_grpid;
128    hid_t fapl_id;
129    struct timeval starttime, endtime;
130    long long startt, endt;
131 
132    /* Start the clock. */
133    gettimeofday(&starttime, NULL);
134 
135    /* Open and close the root group. */
136    if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
137    if (H5Pset_fclose_degree(fapl_id, H5F_CLOSE_SEMI)) ERR;
138    if ((hdfid = H5Fopen(file_name, H5F_ACC_RDONLY, fapl_id)) < 0) ERR;
139    if ((hdf_grpid = H5Gopen2(hdfid, "/", H5P_DEFAULT)) < 0) ERR;
140 
141    /* Do we want to do an inq? */
142    if (do_inq)
143    {
144       if (num_vars)
145       {
146       }
147       else /* global atts */
148       {
149          hsize_t num_obj;
150 
151          /* Find out how many attributes. */
152          if ((num_obj = H5Aget_num_attrs(hdf_grpid)) < 0) ERR;
153       }
154    }
155 
156    if (H5Gclose(hdf_grpid) < 0) ERR;
157    if (H5Fclose(hdfid) < 0) ERR;
158 
159    gettimeofday(&endtime, NULL);
160 
161    /* Compute the time delta */
162    startt = (1000000 * starttime.tv_sec) + starttime.tv_usec;
163    endt = (1000000 * endtime.tv_sec) + endtime.tv_usec;
164    *delta = endt - startt;
165 
166    return 0;
167 }
168 
169 #define NUM_RUNS 5
170 #define NUM_STEPS 20
171 #define FACTOR 100
172 #define NUM_INQ_TESTS 2
173 int
main(int argc,char ** argv)174 main(int argc, char **argv)
175 {
176    size_t num_atts = 1;
177    char file_name[NC_MAX_NAME + 1];
178    float tot_nc4, tot_hdf5;
179    int factor;
180    int r, s, num_vars, do_inq;
181 
182    for (do_inq = 0; do_inq < NUM_INQ_TESTS; do_inq++)
183    {
184       for (num_vars = 0; num_vars <= NUM_VARS; num_vars++)
185       {
186          /* Reset. */
187          num_atts = 1;
188 
189          factor = FACTOR;
190 
191          printf("*** %s %s\n", num_vars ? "variable attributes" : "global attributes",
192                 do_inq ? "with inq" : "");
193          printf("Number of Attributes\tHDF5 Open Time (s)\tNetcdf4 Open Time (s)\n");
194          for (s = 0; s < NUM_STEPS; s++)
195          {
196             tot_nc4 = 0;
197             tot_hdf5 = 0;
198             num_atts += factor * s;
199 
200             for (r = 0; r < NUM_RUNS; r++)
201             {
202                long long nc4_open_time;
203                long long hdf5_open_time;
204 
205                /* Determine file name. */
206                sprintf(file_name, "%s_%d_%d_%d.nc", TEST, num_vars, s, r);
207 
208                if (buildfile(num_vars, num_atts, ATT_LEN, file_name)) ERR;
209                if (readfile(file_name, &nc4_open_time, do_inq, num_vars)) ERR;
210                if (readfile_hdf5(file_name, &hdf5_open_time, do_inq, num_vars)) ERR;
211                tot_nc4 += nc4_open_time;
212                tot_hdf5 += hdf5_open_time;
213             }
214 
215             /* Print average results to the millisec */
216             printf("%ld\t%g\t%g\n", num_atts, tot_hdf5/((float)NUM_RUNS * 1000000),
217                    tot_nc4/((float)NUM_RUNS * 1000000));
218          }
219       }
220    } /* next do_inq */
221    SUMMARIZE_ERR;
222    FINAL_RESULTS;
223 }
224