/* * blk_write_init - function for initializing blk_write benchmark */ static int blk_write_init(struct benchmark *bench, struct benchmark_args *args) { assert(bench != NULL); assert(args != NULL); int ret; struct blk_args *ba = (struct blk_args *)args->opts; struct blk_bench *bb = (struct blk_bench *)malloc(sizeof(struct blk_bench)); if (bb == NULL) { perror("malloc"); return -1; } pmembench_set_priv(bench, bb); if (ba->file_io) bb->worker = fileio_write; else bb->worker = blk_write; ret = blk_init(bb, args); if (ret != 0) free(bb); return ret; }
/* * pmem_memcpy_init -- benchmark initialization * * Parses command line arguments, allocates persistent memory, and maps it. */ static int pmem_memcpy_init(struct benchmark *bench, struct benchmark_args *args) { assert(bench != NULL); assert(args != NULL); int ret = 0; struct pmem_bench *pmb = malloc(sizeof (struct pmem_bench)); assert(pmb != NULL); pmb->pargs = args->opts; assert(pmb->pargs != NULL); pmb->pargs->chunk_size = args->dsize; enum operation_type op_type; /* * Assign file and buffer size depending on the operation type * (READ from PMEM or WRITE to PMEM) */ if (assign_size(pmb, args, &op_type) != 0) { ret = -1; goto err_free_pmb; } if ((errno = posix_memalign( (void **) &pmb->buf, FLUSH_ALIGN, pmb->bsize)) != 0) { perror("posix_memalign"); ret = -1; goto err_free_pmb; } pmb->n_rand_offsets = args->n_ops_per_thread * args->n_threads; pmb->rand_offsets = malloc(pmb->n_rand_offsets * sizeof (*pmb->rand_offsets)); for (size_t i = 0; i < pmb->n_rand_offsets; ++i) pmb->rand_offsets[i] = rand() % args->n_ops_per_thread; /* create a pmem file */ pmb->fd = open(args->fname, O_CREAT|O_EXCL|O_RDWR, args->fmode); if (pmb->fd == -1) { perror(args->fname); ret = -1; goto err_free_buf; } /* allocate the pmem */ if ((errno = posix_fallocate(pmb->fd, 0, pmb->fsize)) != 0) { perror("posix_fallocate"); ret = -1; goto err_close_file; } /* memory map it */ if ((pmb->pmem_addr = pmem_map(pmb->fd)) == NULL) { perror("pmem_map"); ret = -1; goto err_close_file; } if (op_type == OP_TYPE_READ) { pmb->src_addr = pmb->pmem_addr; pmb->dest_addr = pmb->buf; } else { pmb->src_addr = pmb->buf; pmb->dest_addr = pmb->pmem_addr; } /* set proper func_src() and func_dest() depending on benchmark args */ if ((pmb->func_src = assign_mode_func(pmb->pargs->src_mode)) == NULL) { fprintf(stderr, "wrong src_mode parameter -- '%s'", pmb->pargs->src_mode); ret = -1; goto err_unmap; } if ((pmb->func_dest = assign_mode_func(pmb->pargs->dest_mode)) == NULL) { fprintf(stderr, "wrong dest_mode parameter -- '%s'", pmb->pargs->dest_mode); ret = -1; goto err_unmap; } close(pmb->fd); if (pmb->pargs->memcpy) { pmb->func_op = pmb->pargs->persist ? libc_memcpy_persist : libc_memcpy; } else { pmb->func_op = pmb->pargs->persist ? libpmem_memcpy_persist : libpmem_memcpy_nodrain; } pmembench_set_priv(bench, pmb); return 0; err_unmap: munmap(pmb->pmem_addr, pmb->fsize); err_close_file: close(pmb->fd); err_free_buf: free(pmb->buf); err_free_pmb: free(pmb); return ret; }
/* * memset_init -- initialization function */ static int memset_init(struct benchmark *bench, struct benchmark_args *args) { assert(bench != nullptr); assert(args != nullptr); assert(args->opts != nullptr); int ret = 0; size_t size; size_t large; size_t little; size_t file_size = 0; int flags = 0; enum file_type type = util_file_get_type(args->fname); if (type == OTHER_ERROR) { fprintf(stderr, "could not check type of file %s\n", args->fname); return -1; } int (*warmup_func)(struct memset_bench *) = warmup_persist; auto *mb = (struct memset_bench *)malloc(sizeof(struct memset_bench)); if (!mb) { perror("malloc"); return -1; } mb->pargs = (struct memset_args *)args->opts; mb->pargs->chunk_size = args->dsize; enum operation_mode op_mode = parse_op_mode(mb->pargs->mode); if (op_mode == OP_MODE_UNKNOWN) { fprintf(stderr, "Invalid operation mode argument '%s'\n", mb->pargs->mode); ret = -1; goto err_free_mb; } size = MAX_OFFSET + mb->pargs->chunk_size; large = size * args->n_ops_per_thread * args->n_threads; little = size * args->n_threads; mb->fsize = (op_mode == OP_MODE_STAT) ? little : large; /* initialize offsets[] array depending on benchmark args */ if (init_offsets(args, mb, op_mode) < 0) { ret = -1; goto err_free_mb; } /* initialize memset() value */ mb->const_b = CONST_B; if (type != TYPE_DEVDAX) { file_size = mb->fsize; flags = PMEM_FILE_CREATE | PMEM_FILE_EXCL; } /* create a pmem file and memory map it */ if ((mb->pmem_addr = pmem_map_file(args->fname, file_size, flags, args->fmode, nullptr, nullptr)) == nullptr) { perror(args->fname); ret = -1; goto err_free_offsets; } if (mb->pargs->memset) { if (mb->pargs->persist && mb->pargs->msync) { fprintf(stderr, "Invalid benchmark parameters: persist and msync cannot be specified together\n"); ret = -1; goto err_free_offsets; } if (mb->pargs->persist) { mb->func_op = libc_memset_persist; } else if (mb->pargs->msync) { mb->func_op = libc_memset_msync; warmup_func = warmup_msync; } else { mb->func_op = libc_memset; } } else { mb->func_op = (mb->pargs->persist) ? libpmem_memset_persist : libpmem_memset_nodrain; } if (!mb->pargs->no_warmup && type != TYPE_DEVDAX) { ret = warmup_func(mb); if (ret) { perror("Pool warmup failed"); goto err_free_offsets; } } pmembench_set_priv(bench, mb); return ret; err_free_offsets: free(mb->offsets); err_free_mb: free(mb); return ret; }
/* * pobj_init - common part of the benchmark initialization functions. * Parses command line arguments, set variables and creates persistent pools. */ static int pobj_init(struct benchmark *bench, struct benchmark_args *args) { unsigned i = 0; size_t psize; size_t n_objs; assert(bench != nullptr); assert(args != nullptr); enum file_type type = util_file_get_type(args->fname); if (type == OTHER_ERROR) { fprintf(stderr, "could not check type of file %s\n", args->fname); return -1; } auto *bench_priv = (struct pobj_bench *)malloc(sizeof(struct pobj_bench)); if (bench_priv == nullptr) { perror("malloc"); return -1; } assert(args->opts != nullptr); bench_priv->args_priv = (struct pobj_args *)args->opts; bench_priv->args_priv->obj_size = args->dsize; bench_priv->args_priv->range = bench_priv->args_priv->min_size > 0 ? true : false; bench_priv->n_pools = !bench_priv->args_priv->one_pool ? args->n_threads : 1; bench_priv->pool = bench_priv->n_pools > 1 ? diff_num : one_num; bench_priv->obj = !bench_priv->args_priv->one_obj ? diff_num : one_num; if ((args->is_poolset || type == TYPE_DEVDAX) && bench_priv->n_pools > 1) { fprintf(stderr, "cannot use poolset nor device dax for multiple pools," " please use -P|--one-pool option instead"); goto free_bench_priv; } /* * Multiplication by FACTOR prevents from out of memory error * as the actual size of the allocated persistent objects * is always larger than requested. */ n_objs = bench_priv->args_priv->n_objs; if (bench_priv->n_pools == 1) n_objs *= args->n_threads; psize = PMEMOBJ_MIN_POOL + n_objs * args->dsize * args->n_threads * FACTOR; /* assign type_number determining function */ bench_priv->type_mode = parse_type_mode(bench_priv->args_priv->type_num); switch (bench_priv->type_mode) { case MAX_TYPE_MODE: fprintf(stderr, "unknown type mode"); goto free_bench_priv; case TYPE_MODE_RAND: if (random_types(bench_priv, args)) goto free_bench_priv; break; default: bench_priv->random_types = nullptr; } bench_priv->fn_type_num = type_mode_func[bench_priv->type_mode]; /* assign size determining function */ bench_priv->fn_size = bench_priv->args_priv->range ? range_size : static_size; bench_priv->rand_sizes = nullptr; if (bench_priv->args_priv->range) { if (bench_priv->args_priv->min_size > args->dsize) { fprintf(stderr, "Invalid allocation size"); goto free_random_types; } bench_priv->rand_sizes = rand_sizes(bench_priv->args_priv->min_size, bench_priv->args_priv->obj_size, bench_priv->args_priv->n_objs); if (bench_priv->rand_sizes == nullptr) goto free_random_types; } assert(bench_priv->n_pools > 0); bench_priv->pop = (PMEMobjpool **)calloc(bench_priv->n_pools, sizeof(PMEMobjpool *)); if (bench_priv->pop == nullptr) { perror("calloc"); goto free_random_sizes; } bench_priv->sets = (const char **)calloc(bench_priv->n_pools, sizeof(const char *)); if (bench_priv->sets == nullptr) { perror("calloc"); goto free_pop; } if (bench_priv->n_pools > 1) { assert(!args->is_poolset); if (util_file_mkdir(args->fname, DIR_MODE) != 0) { fprintf(stderr, "cannot create directory\n"); goto free_sets; } size_t path_len = (strlen(PART_NAME) + strlen(args->fname)) + MAX_DIGITS + 1; for (i = 0; i < bench_priv->n_pools; i++) { bench_priv->sets[i] = (char *)malloc(path_len * sizeof(char)); if (bench_priv->sets[i] == nullptr) { perror("malloc"); goto free_sets; } int ret = snprintf((char *)bench_priv->sets[i], path_len, "%s%s%02x", args->fname, PART_NAME, i); if (ret < 0 || ret >= (int)path_len) { perror("snprintf"); goto free_sets; } bench_priv->pop[i] = pmemobj_create(bench_priv->sets[i], LAYOUT_NAME, psize, FILE_MODE); if (bench_priv->pop[i] == nullptr) { perror(pmemobj_errormsg()); goto free_sets; } } } else { if (args->is_poolset || type == TYPE_DEVDAX) { if (args->fsize < psize) { fprintf(stderr, "file size too large\n"); goto free_pools; } psize = 0; } bench_priv->sets[0] = args->fname; bench_priv->pop[0] = pmemobj_create( bench_priv->sets[0], LAYOUT_NAME, psize, FILE_MODE); if (bench_priv->pop[0] == nullptr) { perror(pmemobj_errormsg()); goto free_pools; } } pmembench_set_priv(bench, bench_priv); return 0; free_sets: for (; i > 0; i--) { pmemobj_close(bench_priv->pop[i - 1]); free((char *)bench_priv->sets[i - 1]); } free_pools: free(bench_priv->sets); free_pop: free(bench_priv->pop); free_random_sizes: free(bench_priv->rand_sizes); free_random_types: free(bench_priv->random_types); free_bench_priv: free(bench_priv); return -1; }
/* * log_init -- benchmark initialization function */ static int log_init(struct benchmark *bench, struct benchmark_args *args) { int ret = 0; assert(bench); assert(args != NULL); assert(args->opts != NULL); struct benchmark_info *bench_info; struct log_bench *lb = (struct log_bench *)malloc(sizeof(struct log_bench)); if (!lb) { perror("malloc"); return -1; } lb->args = (struct prog_args *)args->opts; lb->args->el_size = args->dsize; if (lb->args->vec_size == 0) lb->args->vec_size = 1; if (lb->args->rand && lb->args->min_size > lb->args->el_size) { errno = EINVAL; ret = -1; goto err_free_lb; } if (lb->args->rand && lb->args->min_size == lb->args->el_size) lb->args->rand = false; /* align pool size to ensure that we have enough usable space */ lb->psize = MMAP_ALIGN_UP(POOL_HDR_SIZE + args->n_ops_per_thread * args->n_threads * lb->args->vec_size * lb->args->el_size); /* calculate a required pool size */ if (lb->psize < PMEMLOG_MIN_POOL) lb->psize = PMEMLOG_MIN_POOL; if (args->is_poolset) { if (lb->psize > args->fsize) { fprintf(stderr, "insufficient size of poolset\n"); ret = -1; goto err_free_lb; } lb->psize = 0; } bench_info = pmembench_get_info(bench); if (!lb->args->fileio) { if ((lb->plp = pmemlog_create(args->fname, lb->psize, args->fmode)) == NULL) { perror("pmemlog_create"); ret = -1; goto err_free_lb; } bench_info->operation = (lb->args->vec_size > 1) ? log_appendv : log_append; } else { int flags = O_CREAT | O_RDWR | O_SYNC; /* Create a file if it does not exist. */ if ((lb->fd = open(args->fname, flags, args->fmode)) < 0) { perror(args->fname); ret = -1; goto err_free_lb; } /* allocate the pmem */ if ((errno = posix_fallocate(lb->fd, 0, lb->psize)) != 0) { perror("posix_fallocate"); ret = -1; goto err_close; } bench_info->operation = (lb->args->vec_size > 1) ? fileio_appendv : fileio_append; } if (!lb->args->no_warmup) { size_t warmup_nops = args->n_threads * args->n_ops_per_thread; if (do_warmup(lb, warmup_nops)) { fprintf(stderr, "warmup failed\n"); ret = -1; goto err_close; } } pmembench_set_priv(bench, lb); return 0; err_close: if (lb->args->fileio) close(lb->fd); else pmemlog_close(lb->plp); err_free_lb: free(lb); return ret; }