16ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe/*
26ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe * Generate/analyze pareto/zipf distributions to better understand
36ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe * what an access pattern would look like.
46ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe *
56ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe * For instance, the following would generate a zipf distribution
66ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe * with theta 1.2, using 100,000 values and split the reporting into
76ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe * 20 buckets:
86ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe *
96ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe *	t/genzipf zipf 1.2 100000 20
106ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe *
11f880b1f60dcfb278ab00e6b20994072b04dfd5afJens Axboe * Only the distribution type (zipf or pareto) and spread input need
12f880b1f60dcfb278ab00e6b20994072b04dfd5afJens Axboe * to be given, if not given defaults are used.
13f880b1f60dcfb278ab00e6b20994072b04dfd5afJens Axboe *
146ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe */
156ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe#include <stdio.h>
166ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe#include <stdlib.h>
176ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe#include <fcntl.h>
186ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe#include <string.h>
19921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe#include <unistd.h>
206ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
216ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe#include "../lib/zipf.h"
22fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe#include "../flist.h"
23fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe#include "../hash.h"
246ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
25f880b1f60dcfb278ab00e6b20994072b04dfd5afJens Axboe#define DEF_NR		1000000
26f880b1f60dcfb278ab00e6b20994072b04dfd5afJens Axboe#define DEF_NR_OUTPUT	23
27f880b1f60dcfb278ab00e6b20994072b04dfd5afJens Axboe
28fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboestruct node {
29fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	struct flist_head list;
30fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	unsigned long long val;
31fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	unsigned long hits;
32fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe};
33fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe
34fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboestatic struct flist_head *hash;
35fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboestatic unsigned long hash_bits = 24;
36fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboestatic unsigned long hash_size = 1 << 24;
37fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe
38921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboeenum {
39921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	TYPE_NONE = 0,
40921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	TYPE_ZIPF,
41921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	TYPE_PARETO,
42921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe};
43921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboestatic const char *dist_types[] = { "None", "Zipf", "Pareto" };
44921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe
45921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboestatic int dist_type = TYPE_ZIPF;
46921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboestatic unsigned long gb_size = 500;
47444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboestatic unsigned long block_size = 4096;
48921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboestatic unsigned long output_nranges = DEF_NR_OUTPUT;
49444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboestatic double percentage;
50921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboestatic double dist_val;
51355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fustatic int output_csv = 0;
52921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe
53921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe#define DEF_ZIPF_VAL	1.2
54921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe#define DEF_PARETO_VAL	0.3
55921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe
56fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboestatic struct node *hash_lookup(unsigned long long val)
57fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe{
58fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	struct flist_head *l = &hash[hash_long(val, hash_bits)];
59fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	struct flist_head *entry;
60fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	struct node *n;
61fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe
62fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	flist_for_each(entry, l) {
63fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe		n = flist_entry(entry, struct node, list);
64fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe		if (n->val == val)
65fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe			return n;
66fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	}
67fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe
68fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	return NULL;
69fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe}
70fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe
7124baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboestatic struct node *hash_insert(struct node *n, unsigned long long val)
72fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe{
73fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	struct flist_head *l = &hash[hash_long(val, hash_bits)];
74fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe
75fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	n->val = val;
76fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	n->hits = 1;
77fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	flist_add_tail(&n->list, l);
7824baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe	return n;
796ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe}
806ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
814e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboestatic void usage(void)
824e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe{
834e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe	printf("genzipf: test zipf/pareto values for fio input\n");
844e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe	printf("\t-h\tThis help screen\n");
854e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe	printf("\t-p\tGenerate size of data set that are hit by this percentage\n");
864e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe	printf("\t-t\tDistribution type (zipf or pareto)\n");
874e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe	printf("\t-i\tDistribution algorithm input (zipf theta or pareto power)\n");
884e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe	printf("\t-b\tBlock size of a given range (in bytes)\n");
894e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe	printf("\t-g\tSize of data set (in gigabytes)\n");
904e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe	printf("\t-o\tNumber of output columns\n");
914e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe	printf("\t-c\tOutput ranges in CSV format\n");
924e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe}
934e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe
94921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboestatic int parse_options(int argc, char *argv[])
95921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe{
964e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe	const char *optstring = "t:g:i:o:b:p:ch";
97921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	int c, dist_val_set = 0;
98921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe
99921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	while ((c = getopt(argc, argv, optstring)) != -1) {
100921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		switch (c) {
1014e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe		case 'h':
1024e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe			usage();
1034e98a45014737dc4f35d0ca599e4d1ccb4ef3c9bJens Axboe			return 1;
104444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe		case 'p':
105444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe			percentage = atof(optarg);
106444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe			break;
107444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe		case 'b':
108444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe			block_size = strtoul(optarg, NULL, 10);
109444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe			break;
110921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		case 't':
111921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			if (!strncmp(optarg, "zipf", 4))
112921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe				dist_type = TYPE_ZIPF;
113921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			else if (!strncmp(optarg, "pareto", 6))
114921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe				dist_type = TYPE_PARETO;
115921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			else {
116921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe				printf("wrong dist type: %s\n", optarg);
117921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe				return 1;
118921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			}
119921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			break;
120921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		case 'g':
121921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			gb_size = strtoul(optarg, NULL, 10);
122921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			break;
123921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		case 'i':
124921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			dist_val = atof(optarg);
125921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			dist_val_set = 1;
126921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			break;
127921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		case 'o':
128921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			output_nranges = strtoul(optarg, NULL, 10);
129921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			break;
130355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		case 'c':
131355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			output_csv = 1;
132355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			break;
133921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		default:
134921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			printf("bad option %c\n", c);
135921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			return 1;
136921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		}
137921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	}
138921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe
139921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	if (dist_type == TYPE_PARETO) {
140921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		if ((dist_val >= 1.00 || dist_val < 0.00)) {
141921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			printf("pareto input must be > 0.00 and < 1.00\n");
142921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			return 1;
143921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		}
144921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		if (!dist_val_set)
145921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			dist_val = DEF_PARETO_VAL;
146921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	} else if (dist_type == TYPE_ZIPF) {
147921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		if (dist_val == 1.0) {
148921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			printf("zipf input must be different than 1.0\n");
149921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			return 1;
150921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		}
151921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		if (!dist_val_set)
152921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe			dist_val = DEF_ZIPF_VAL;
153921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	}
154921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe
155921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	return 0;
156921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe}
157921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe
158444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboestruct output_sum {
159444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe	double output;
160444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe	unsigned int nranges;
161444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe};
162444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe
16324baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboestatic int node_cmp(const void *p1, const void *p2)
16424baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe{
16524baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe	const struct node *n1 = p1;
16624baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe	const struct node *n2 = p2;
16724baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe
16824baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe	return n2->hits - n1->hits;
16924baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe}
17024baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe
1716ff3885617d8281bde48a9a19d34302add3fd017Jens Axboeint main(int argc, char *argv[])
1726ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe{
173fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	unsigned long offset;
17424baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe	unsigned long i, j, k, nr_vals, cur_vals, interval, total_vals, nnodes;
175444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe	unsigned long long nranges;
176444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe	struct output_sum *output_sums;
17724baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe	struct node *nodes;
178444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe	double perc, perc_i;
1796ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe	struct zipf_state zs;
1806ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
181921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	if (parse_options(argc, argv))
1826ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe		return 1;
1836ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
184355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu	if( !output_csv )
185355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		printf("Generating %s distribution with %f input and %lu GB size and %lu block_size.\n", dist_types[dist_type], dist_val, gb_size, block_size);
186444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe
187444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe	nranges = gb_size * 1024 * 1024 * 1024ULL;
188444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe	nranges /= block_size;
189f880b1f60dcfb278ab00e6b20994072b04dfd5afJens Axboe
190921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe	if (dist_type == TYPE_ZIPF)
191921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		zipf_init(&zs, nranges, dist_val, 1);
1926ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe	else
193921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		pareto_init(&zs, nranges, dist_val, 1);
1946ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
195c71224e777dc07706148df6310f5a7bdca67a65cJens Axboe	hash_bits = 0;
196c71224e777dc07706148df6310f5a7bdca67a65cJens Axboe	hash_size = nranges;
197c71224e777dc07706148df6310f5a7bdca67a65cJens Axboe	while ((hash_size >>= 1) != 0)
198c71224e777dc07706148df6310f5a7bdca67a65cJens Axboe		hash_bits++;
199c71224e777dc07706148df6310f5a7bdca67a65cJens Axboe
200c71224e777dc07706148df6310f5a7bdca67a65cJens Axboe	hash_size = 1 << hash_bits;
201c71224e777dc07706148df6310f5a7bdca67a65cJens Axboe
202fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	hash = malloc(hash_size * sizeof(struct flist_head));
203fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	for (i = 0; i < hash_size; i++)
204fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe		INIT_FLIST_HEAD(&hash[i]);
205fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe
20624baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe	nodes = malloc(nranges * sizeof(struct node));
20724baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe
20824baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe	for (nr_vals = i = j = 0; i < nranges; i++) {
209fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe		struct node *n;
2106ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
211921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		if (dist_type == TYPE_ZIPF)
212fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe			offset = zipf_next(&zs);
2136ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe		else
214fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe			offset = pareto_next(&zs);
215fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe
216fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe		n = hash_lookup(offset);
217fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe		if (n)
218fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe			n->hits++;
21924baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe		else {
22024baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe			hash_insert(&nodes[j], offset);
22124baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe			j++;
22224baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe		}
2236ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
2246ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe		nr_vals++;
2256ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe	}
2266ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
22724baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe	qsort(nodes, j, sizeof(struct node), node_cmp);
22824baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe	nnodes = j;
22924baa4c70c850d4c1703ae8f4e2b35fc5c5a57eaJens Axboe	nr_vals = nnodes;
2306ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
231355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu	if (output_csv) {
232355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		printf("rank, count\n");
233355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		for (k = 0; k < nnodes; k++)
234355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			printf("%lu, %lu\n", k, nodes[k].hits);
235355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu	} else {
236355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		interval = (nr_vals + output_nranges - 1) / output_nranges;
237355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu
238355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		output_sums = malloc(output_nranges * sizeof(struct output_sum));
239355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		for (i = 0; i < output_nranges; i++) {
240355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			output_sums[i].output = 0.0;
241355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			output_sums[i].nranges = 1;
242444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe		}
2436ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
244355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		total_vals = i = j = cur_vals = 0;
245355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu
246355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		for (k = 0; k < nnodes; k++) {
247355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			struct output_sum *os = &output_sums[j];
248355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			struct node *node = &nodes[k];
249355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu
250355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			if (i >= interval) {
251355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				os->output =
252355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				    (double)(cur_vals + 1) / (double)nranges;
253355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				os->output *= 100.0;
254355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				j++;
255355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				cur_vals = node->hits;
256355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				interval +=
257355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				    (nr_vals + output_nranges -
258355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				     1) / output_nranges;
259355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			} else {
260355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				cur_vals += node->hits;
261355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				os->nranges += node->hits;
262355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			}
263444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe
264355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			i++;
265355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			total_vals += node->hits;
266355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu
267355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			if (percentage) {
268355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				unsigned long blocks =
269355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				    percentage * nranges / 100;
270355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu
271355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				if (total_vals >= blocks) {
272355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu					double cs =
273355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu					    i * block_size / (1024 * 1024);
274355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu					char p = 'M';
275355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu
276355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu					if (cs > 1024.0) {
277355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu						cs /= 1024.0;
278355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu						p = 'G';
279355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu					}
280355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu					if (cs > 1024.0) {
281355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu						cs /= 1024.0;
282355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu						p = 'T';
283355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu					}
284355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu
285355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu					printf("%.2f%% of hits satisfied in %.3f%cB of cache\n", percentage, cs, p);
286355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu					percentage = 0.0;
287444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe				}
288444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe			}
289444256eaf4f0ffdc4cacef37873d58f2a65bf8e6Jens Axboe		}
2906ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
291355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		perc_i = 100.0 / (double)output_nranges;
292355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		perc = 0.0;
293921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe
294355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		printf("\n   Rows           Hits           No Hits         Size\n");
295355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		printf("--------------------------------------------------------\n");
296355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		for (i = 0; i < j; i++) {
297355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			struct output_sum *os = &output_sums[i];
298355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			double gb = (double)os->nranges * block_size / 1024.0;
299355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			char p = 'K';
300921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe
301355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			if (gb > 1024.0) {
302355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				p = 'M';
303355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				gb /= 1024.0;
304355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			}
305355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			if (gb > 1024.0) {
306355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				p = 'G';
307355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu				gb /= 1024.0;
308355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			}
309355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu
310355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			perc += perc_i;
311355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			printf("%s %6.2f%%\t%6.2f%%\t\t%8u\t%6.2f%c\n",
312355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			       i ? "|->" : "Top", perc, os->output, os->nranges,
313355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu			       gb, p);
314921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe		}
315921d17ba00f6fa106f558ea285d1d503f3a41369Jens Axboe
316355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu		free(output_sums);
317f880b1f60dcfb278ab00e6b20994072b04dfd5afJens Axboe	}
3186ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe
319fd6f237d84f0ab32c80e20184392918bbd91376cJens Axboe	free(hash);
320355934b7ed82d13a5bfc043e2243013fd1e4e5bdVincent Kang Fu	free(nodes);
3216ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe	return 0;
3226ff3885617d8281bde48a9a19d34302add3fd017Jens Axboe}
323