1 /* This is part of the netCDF package. Copyright 2018 University
2    Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
3    conditions of use. See www.unidata.ucar.edu for more info.
4 
5    This program benchmarks creating a netCDF file with many objects.
6 
7    Ed Hartnett
8 */
9 
10 #include <config.h>
11 #include <nc_tests.h>
12 #include "err_macros.h"
13 #include <netcdf.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <time.h>
17 #include <sys/time.h> /* Extra high precision time info. */
18 
19 /* We will create this file. */
20 #define FILE_NAME "bm_many_objs.nc"
21 
22 /* Prototype from tst_utils.c. */
23 int nc4_timeval_subtract(struct timeval *result, struct timeval *x,
24                          struct timeval *y);
25 
main(int argc,char ** argv)26 int main(int argc, char **argv)
27 {
28     struct timeval start_time, end_time, diff_time;
29     double sec;
30     int nitem = 10000;		/* default number of objects of each type */
31     int i;
32     int ncid;
33     int data[] = {42};
34     int g, grp, numgrp;
35     char gname[16];
36     int v, var, numvar, vn, vleft, nvars;
37 
38     if(argc > 2) { 	/* Usage */
39 	printf("NetCDF performance test, writing many groups and variables.\n");
40 	printf("Usage:\t%s [N]\n", argv[0]);
41 	printf("\tN: number of objects\n");
42 	return(0);
43     }
44     for(i = 1; i < argc; i++) {
45 	nitem = atoi(argv[i]);
46     }
47 
48     /*  create new file */
49     if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
50     if (gettimeofday(&start_time, NULL))
51 	ERR;
52     /* create N groups, printing time after every 1000 */
53     numgrp = nitem;
54     for(g = 1; g < numgrp + 1; g++) {
55 	sprintf(gname, "group%d", g);
56 	if (nc_def_grp(ncid, gname, &grp)) ERR;
57 	if (nc_def_var(grp, "var", NC_INT, 0, NULL, &var)) ERR;
58 	if(nc_enddef (grp)) ERR;
59 	if(nc_put_var(grp, var, data)) ERR;
60 	if(g%1000 == 0) {		/* only print every 1000th group name */
61 	    if (gettimeofday(&end_time, NULL)) ERR;
62 	    if (nc4_timeval_subtract(&diff_time, &end_time, &start_time)) ERR;
63 	    sec = diff_time.tv_sec + 1.0e-6 * diff_time.tv_usec;
64 	    printf("%s\t%.3g sec\n", gname, sec);
65 	}
66     }
67     nc_close(ncid);
68 
69     /*  create new file */
70     if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
71     /* create N variables, printing time after every 1000.
72      * Put NC_MAX_VARS variables per group (even though netcdf4 non-classic
73      * format does not limit variable count), create the necessary number
74      * of groups to hold nitem variables. */
75     numvar = nitem;
76     v = 1;
77     numgrp = (numvar - 1) / NC_MAX_VARS + 1;
78     vleft = numvar - (NC_MAX_VARS * (numgrp - 1));
79     if (gettimeofday(&start_time, NULL))
80 	ERR;
81 
82     for(g = 1; g < numgrp + 1; g++) {
83 	sprintf(gname, "group%d", g);
84 	if (nc_def_grp(ncid, gname, &grp)) ERR;
85 	nvars = g < numgrp ? NC_MAX_VARS : vleft; /* leftovers on last time through */
86 	for(vn = 1; vn < nvars + 1; vn++) {
87 	    int var;
88 	    char vname[20];
89 	    sprintf(vname, "variable%d", v);
90 	    if(nc_def_var(grp, vname, NC_INT, 0, NULL, &var)) ERR;
91 	    if(nc_put_var(grp, var, data)) ERR;
92 	    if(v%1000 == 0) {		/* only print every 1000th variable name */
93 		if (gettimeofday(&end_time, NULL)) ERR;
94 		if (nc4_timeval_subtract(&diff_time, &end_time, &start_time)) ERR;
95 		sec = diff_time.tv_sec + 1.0e-6 * diff_time.tv_usec;
96 		printf("%s/%s\t%.3g sec\n", gname, vname, sec);
97 	    }
98 	    v++;
99 	}
100     }
101     nc_close(ncid);
102     FINAL_RESULTS;
103 }
104