2 #include "../profile.h"
11 #define SAMPLE_SEC 3600 /* 1h checks */
13 struct act_pass_criteria {
14 unsigned int max_usec;
15 unsigned int max_perm;
17 #define ACT_MAX_CRIT 3
19 static struct act_pass_criteria act_pass[ACT_MAX_CRIT] = {
34 struct act_prof_data {
35 struct timeval sample_tv;
36 uint64_t lat_buckets[ACT_MAX_CRIT];
40 static char *device_names;
41 static unsigned int load = 1;
42 static unsigned int prep;
43 static unsigned int threads_per_queue;
44 static unsigned int num_read_blocks;
45 static unsigned int write_size;
47 #define ACT_MAX_OPTS 128
48 static const char *act_opts[ACT_MAX_OPTS] = {
51 "random_generator=lfsr",
55 static unsigned int opt_idx = 4;
56 static unsigned int org_idx;
58 static int act_add_opt(const char *format, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
60 static struct fio_option options[] = {
62 .name = "device-names",
63 .lname = "device-names",
64 .type = FIO_OPT_STR_STORE,
65 .roff1 = &device_names,
66 .help = "Devices to use",
67 .category = FIO_OPT_C_PROFILE,
68 .group = FIO_OPT_G_ACT,
72 .lname = "Load multiplier",
75 .help = "ACT load multipler (default 1x)",
77 .category = FIO_OPT_C_PROFILE,
78 .group = FIO_OPT_G_ACT,
81 .name = "threads-per-queue",
82 .lname = "Number of read IO threads per device",
84 .roff1 = &threads_per_queue,
85 .help = "Number of read IO threads per device",
87 .category = FIO_OPT_C_PROFILE,
88 .group = FIO_OPT_G_ACT,
91 .name = "read-req-num-512-blocks",
92 .lname = "Number of 512b blocks to read",
94 .roff1 = &num_read_blocks,
95 .help = "Number of 512b blocks to read at the time",
97 .category = FIO_OPT_C_PROFILE,
98 .group = FIO_OPT_G_ACT,
101 .name = "large-block-op-kbytes",
102 .lname = "Size of large block ops (writes)",
104 .roff1 = &write_size,
105 .help = "Size of large block ops (writes)",
107 .category = FIO_OPT_C_PROFILE,
108 .group = FIO_OPT_G_ACT,
112 .lname = "Run ACT prep phase",
113 .type = FIO_OPT_STR_SET,
115 .help = "Set to run ACT prep phase",
116 .category = FIO_OPT_C_PROFILE,
117 .group = FIO_OPT_G_ACT,
124 static int act_add_opt(const char *str, ...)
130 if (opt_idx == ACT_MAX_OPTS) {
131 log_err("act: ACT_MAX_OPTS is too small\n");
136 len = vsnprintf(buffer, sizeof(buffer), str, args);
140 act_opts[opt_idx++] = strdup(buffer);
145 static int act_add_rw(const char *dev, int reads)
147 if (act_add_opt("name=act-%s-%s", reads ? "read" : "write", dev))
149 if (act_add_opt("filename=%s", dev))
151 if (act_add_opt("rw=%s", reads ? "randread" : "randwrite"))
154 int rload = load * R_LOAD / threads_per_queue;
156 if (act_add_opt("numjobs=%u", threads_per_queue))
158 if (act_add_opt("rate_iops=%u", rload))
160 if (act_add_opt("bs=%u", num_read_blocks * 512))
163 const int rsize = write_size / (num_read_blocks * 512);
164 int wload = (load * W_LOAD + rsize - 1) / rsize;
166 if (act_add_opt("rate_iops=%u", wload))
168 if (act_add_opt("bs=%u", write_size))
175 static int act_add_dev_prep(const char *dev)
177 /* Add sequential zero phase */
178 if (act_add_opt("name=act-prep-zeroes-%s", dev))
180 if (act_add_opt("filename=%s", dev))
182 if (act_add_opt("bs=1M"))
184 if (act_add_opt("zero_buffers"))
186 if (act_add_opt("rw=write"))
189 /* Randomly overwrite device */
190 if (act_add_opt("name=act-prep-salt-%s", dev))
192 if (act_add_opt("stonewall"))
194 if (act_add_opt("filename=%s", dev))
196 if (act_add_opt("bs=4k"))
198 if (act_add_opt("ioengine=libaio"))
200 if (act_add_opt("iodepth=64"))
202 if (act_add_opt("rw=randwrite"))
208 static int act_add_dev(const char *dev)
211 return act_add_dev_prep(dev);
213 if (act_add_opt("runtime=24h"))
215 if (act_add_opt("time_based=1"))
218 if (act_add_rw(dev, 1))
220 if (act_add_rw(dev, 0))
227 * Fill our private options into the command line
229 static int act_prep_cmdline(void)
232 log_err("act: need device-names\n");
241 dev = strsep(&device_names, ",");
245 if (act_add_dev(dev)) {
246 log_err("act: failed adding device to the mix\n");
254 static int act_io_u_lat(struct thread_data *td, uint64_t usec)
256 struct act_prof_data *apd = td->prof_data;
265 for (i = ACT_MAX_CRIT - 1; i >= 0; i--) {
266 if (usec > act_pass[i].max_usec) {
267 apd->lat_buckets[i]++;
272 if (time_since_now(&apd->sample_tv) < SAMPLE_SEC)
275 /* SAMPLE_SEC has passed, check criteria for pass */
276 for (i = 0; i < ACT_MAX_CRIT; i++) {
277 perm = (1000.0 * apd->lat_buckets[i]) / apd->total_ios;
278 if (perm < act_pass[i].max_perm)
281 log_err("act: %f%% exceeds pass criteria of %f%%\n", perm / 10.0, (double) act_pass[i].max_perm / 10.0);
286 memset(apd->lat_buckets, 0, sizeof(apd->lat_buckets));
289 fio_gettime(&apd->sample_tv, NULL);
293 static int act_td_init(struct thread_data *td)
295 struct act_prof_data *apd;
297 apd = calloc(sizeof(*apd), 1);
298 fio_gettime(&apd->sample_tv, NULL);
303 static void act_td_exit(struct thread_data *td)
306 td->prof_data = NULL;
309 static struct prof_io_ops act_io_ops = {
310 .td_init = act_td_init,
311 .td_exit = act_td_exit,
312 .io_u_lat = act_io_u_lat,
315 static struct profile_ops act_profile = {
317 .desc = "ACT Aerospike like benchmark",
319 .prep_cmd = act_prep_cmdline,
321 .io_ops = &act_io_ops,
324 static void fio_init act_register(void)
326 if (register_profile(&act_profile))
327 log_err("fio: failed to register profile 'act'\n");
330 static void fio_exit act_unregister(void)
332 while (org_idx && org_idx < opt_idx)
333 free((void *) act_opts[++org_idx]);
335 unregister_profile(&act_profile);