#include "benchmark.hpp"
#include "libpmemobj.h"
#include "queue.h"
#include <cassert>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fcntl.h>
#include <unistd.h>
#define FACTOR 8
#define LAYOUT_NAME "benchmark"
struct obj_bench;
struct obj_worker;
struct element;
TOID_DECLARE(struct item, 0);
TOID_DECLARE(struct list, 1);
typedef size_t (*fn_type_num_t)(size_t worker_idx, size_t op_idx);
typedef struct element (*fn_position_t)(struct obj_worker *obj_worker,
size_t op_idx);
typedef int (*fn_init_t)(struct worker_info *worker, size_t n_elm,
size_t list_len);
struct obj_list_args {
char *type_num;
char *position;
unsigned list_len;
bool queue;
bool range;
unsigned min_size;
unsigned seed;
};
static struct obj_bench {
PMEMobjpool *pop;
struct obj_list_args *args;
size_t *random_types;
size_t *alloc_sizes;
size_t max_len;
size_t min_len;
int type_mode;
int position_mode;
fn_type_num_t fn_type_num;
fn_position_t fn_position;
fn_init_t fn_init;
} obj_bench;
struct item {
POBJ_LIST_ENTRY(struct item) field;
CIRCLEQ_ENTRY(item) fieldq;
};
struct element {
struct item *itemq;
TOID(struct item) itemp;
bool before;
};
struct obj_worker {
POBJ_LIST_HEAD(plist, struct item) head;
CIRCLEQ_HEAD(qlist, item) headq;
TOID(struct item) * oids;
struct item **items;
size_t n_elm;
fn_position_t *fn_positions;
struct element elm;
struct obj_worker *list_move;
};
enum position_mode {
POSITION_MODE_HEAD,
POSITION_MODE_TAIL,
POSITION_MODE_MIDDLE,
POSITION_MODE_RAND,
POSITION_MODE_UNKNOWN,
};
enum type_mode {
TYPE_MODE_ONE,
TYPE_MODE_PER_THREAD,
TYPE_MODE_RAND,
TYPE_MODE_UNKNOWN,
};
static struct element
position_head(struct obj_worker *obj_worker, size_t op_idx)
{
struct element head = {0, OID_NULL, false};
head.before = true;
if (!obj_bench.args->queue)
head.itemp = POBJ_LIST_FIRST(&obj_worker->head);
else
head.itemq = CIRCLEQ_FIRST(&obj_worker->headq);
return head;
}
static struct element
position_tail(struct obj_worker *obj_worker, size_t op_idx)
{
struct element tail = {0, OID_NULL, false};
tail.before = false;
if (!obj_bench.args->queue)
tail.itemp = POBJ_LIST_LAST(&obj_worker->head, field);
else
tail.itemq = CIRCLEQ_LAST(&obj_worker->headq);
return tail;
}
static struct element
position_middle(struct obj_worker *obj_worker, size_t op_idx)
{
struct element elm = position_head(obj_worker, op_idx);
elm.before = true;
if (!obj_bench.args->queue)
elm.itemp = POBJ_LIST_NEXT(elm.itemp, field);
else
elm.itemq = CIRCLEQ_NEXT(elm.itemq, fieldq);
return elm;
}
static struct element
position_rand(struct obj_worker *obj_worker, size_t op_idx)
{
struct element elm;
elm = obj_worker->fn_positions[op_idx](obj_worker, op_idx);
elm.before = true;
return elm;
}
static size_t
type_mode_one(size_t worker_idx, size_t op_idx)
{
return 0;
}
static size_t
type_mode_per_thread(size_t worker_idx, size_t op_idx)
{
return worker_idx;
}
static size_t
type_mode_rand(size_t worker_idx, size_t op_idx)
{
return obj_bench.random_types[op_idx];
}
const char *type_num_names[] = {"one", "per-thread", "rand"};
const char *position_names[] = {"head", "tail", "middle", "rand"};
static fn_type_num_t type_num_modes[] = {type_mode_one, type_mode_per_thread,
type_mode_rand};
static fn_position_t positions[] = {position_head, position_tail,
position_middle, position_rand};
static fn_position_t rand_positions[] = {position_head, position_tail,
position_middle};
static void
get_item(struct benchmark *bench, struct operation_info *info)
{
struct obj_worker *obj_worker = (struct obj_worker *)info->worker->priv;
obj_worker->elm = obj_bench.fn_position(obj_worker, info->index);
}
static int
get_move_item(struct benchmark *bench, struct operation_info *info)
{
struct obj_worker *obj_worker = (struct obj_worker *)info->worker->priv;
obj_worker->list_move->elm =
obj_bench.fn_position(obj_worker->list_move, info->index);
get_item(bench, info);
return 0;
}
static int
parse_args(char *arg, int max, const char **names)
{
int i = 0;
for (; i < max && strcmp(names[i], arg) != 0; i++)
;
if (i == max)
fprintf(stderr, "Invalid argument\n");
return i;
}
static int
obj_init_list(struct worker_info *worker, size_t n_oids, size_t list_len)
{
size_t i;
struct obj_worker *obj_worker = (struct obj_worker *)worker->priv;
obj_worker->oids =
(TOID(struct item) *)calloc(n_oids, sizeof(TOID(struct item)));
if (obj_worker->oids == NULL) {
perror("calloc");
return -1;
}
for (i = 0; i < n_oids; i++) {
size_t type_num = obj_bench.fn_type_num(worker->index, i);
size_t size = obj_bench.alloc_sizes[i];
PMEMoid *tmp = (PMEMoid *)&obj_worker->oids[i];
if (pmemobj_alloc(obj_bench.pop, tmp, size, type_num, NULL,
NULL) != 0)
goto err_oids;
}
for (i = 0; i < list_len; i++)
POBJ_LIST_INSERT_TAIL(obj_bench.pop, &obj_worker->head,
obj_worker->oids[i], field);
return 0;
err_oids:
for (; i > 0; i--)
POBJ_FREE(&obj_worker->oids[i - 1]);
free(obj_worker->oids);
return -1;
}
static int
queue_init_list(struct worker_info *worker, size_t n_items, size_t list_len)
{
size_t i;
struct obj_worker *obj_worker = (struct obj_worker *)worker->priv;
CIRCLEQ_INIT(&obj_worker->headq);
obj_worker->items =
(struct item **)malloc(n_items * sizeof(struct item *));
if (obj_worker->items == NULL) {
perror("malloc");
return -1;
}
for (i = 0; i < n_items; i++) {
size_t size = obj_bench.alloc_sizes[i];
obj_worker->items[i] = (struct item *)calloc(1, size);
if (obj_worker->items[i] == NULL) {
perror("calloc");
goto err;
}
}
for (i = 0; i < list_len; i++)
CIRCLEQ_INSERT_TAIL(&obj_worker->headq, obj_worker->items[i],
fieldq);
return 0;
err:
for (; i > 0; i--)
free(obj_worker->items[i - 1]);
free(obj_worker->items);
return -1;
}
static void
queue_free_worker_list(struct obj_worker *obj_worker)
{
while (!CIRCLEQ_EMPTY(&obj_worker->headq)) {
struct item *tmp = CIRCLEQ_LAST(&obj_worker->headq);
CIRCLEQ_REMOVE(&obj_worker->headq, tmp, fieldq);
free(tmp);
}
free(obj_worker->items);
}
static void
obj_free_worker_list(struct obj_worker *obj_worker)
{
while (!POBJ_LIST_EMPTY(&obj_worker->head)) {
TOID(struct item) tmp = POBJ_LIST_FIRST(&obj_worker->head);
POBJ_LIST_REMOVE_FREE(obj_bench.pop, &obj_worker->head, tmp,
field);
}
free(obj_worker->oids);
}
static void
obj_free_worker_items(struct obj_worker *obj_worker)
{
for (size_t i = 0; i < obj_worker->n_elm; i++)
POBJ_FREE(&obj_worker->oids[i]);
free(obj_worker->oids);
}
static void
queue_free_worker_items(struct obj_worker *obj_worker)
{
for (size_t i = 0; i < obj_worker->n_elm; i++)
free(obj_worker->items[i]);
free(obj_worker->items);
}
static fn_position_t *
random_positions(void)
{
fn_position_t *positions = (fn_position_t *)calloc(
obj_bench.max_len, sizeof(fn_position_t));
if (positions == NULL) {
perror("calloc");
return NULL;
}
if (obj_bench.args->seed != 0)
srand(obj_bench.args->seed);
size_t rmax = ARRAY_SIZE(rand_positions);
for (size_t i = 0; i < obj_bench.max_len; i++) {
size_t id = RRAND(rmax, 0);
positions[i] = rand_positions[id];
}
return positions;
}
static size_t *
random_values(size_t min, size_t max, size_t n_ops, size_t min_range)
{
size_t *randoms = (size_t *)calloc(n_ops, sizeof(size_t));
if (randoms == NULL) {
perror("calloc");
return NULL;
}
for (size_t i = 0; i < n_ops; i++)
randoms[i] = max;
if (min > min_range) {
if (min > max) {
fprintf(stderr, "Invalid size\n");
free(randoms);
return NULL;
}
for (size_t i = 0; i < n_ops; i++)
randoms[i] = RRAND(max, min);
}
return randoms;
}
static int
queue_insert_op(struct operation_info *info)
{
struct obj_worker *obj_worker = (struct obj_worker *)info->worker->priv;
CIRCLEQ_INSERT_AFTER(&obj_worker->headq, obj_worker->elm.itemq,
obj_worker->items[info->index + obj_bench.min_len],
fieldq);
return 0;
}
static int
obj_insert_op(struct operation_info *info)
{
struct obj_worker *obj_worker = (struct obj_worker *)info->worker->priv;
POBJ_LIST_INSERT_AFTER(
obj_bench.pop, &obj_worker->head, obj_worker->elm.itemp,
obj_worker->oids[info->index + obj_bench.min_len], field);
return 0;
}
static int
queue_remove_op(struct operation_info *info)
{
struct obj_worker *obj_worker = (struct obj_worker *)info->worker->priv;
CIRCLEQ_REMOVE(&obj_worker->headq, obj_worker->elm.itemq, fieldq);
return 0;
}
static int
obj_remove_op(struct operation_info *info)
{
struct obj_worker *obj_worker = (struct obj_worker *)info->worker->priv;
POBJ_LIST_REMOVE(obj_bench.pop, &obj_worker->head,
obj_worker->elm.itemp, field);
return 0;
}
static int
insert_op(struct benchmark *bench, struct operation_info *info)
{
get_item(bench, info);
return obj_bench.args->queue ? queue_insert_op(info)
: obj_insert_op(info);
}
static int
obj_insert_new_op(struct benchmark *bench, struct operation_info *info)
{
get_item(bench, info);
struct obj_worker *obj_worker = (struct obj_worker *)info->worker->priv;
PMEMoid tmp;
size_t size = obj_bench.alloc_sizes[info->index];
size_t type_num =
obj_bench.fn_type_num(info->worker->index, info->index);
tmp = pmemobj_list_insert_new(
obj_bench.pop, offsetof(struct item, field), &obj_worker->head,
obj_worker->elm.itemp.oid, obj_worker->elm.before, size,
type_num, NULL, NULL);
if (OID_IS_NULL(tmp)) {
perror("pmemobj_list_insert_new");
return -1;
}
return 0;
}
static int
remove_op(struct benchmark *bench, struct operation_info *info)
{
get_item(bench, info);
return obj_bench.args->queue ? queue_remove_op(info)
: obj_remove_op(info);
}
static int
obj_remove_free_op(struct benchmark *bench, struct operation_info *info)
{
get_item(bench, info);
struct obj_worker *obj_worker = (struct obj_worker *)info->worker->priv;
POBJ_LIST_REMOVE_FREE(obj_bench.pop, &obj_worker->head,
obj_worker->elm.itemp, field);
return 0;
}
static int
obj_move_op(struct benchmark *bench, struct operation_info *info)
{
if (get_move_item(bench, info))
return -1;
struct obj_worker *obj_worker = (struct obj_worker *)info->worker->priv;
POBJ_LIST_MOVE_ELEMENT_BEFORE(obj_bench.pop, &obj_worker->head,
&obj_worker->list_move->head,
obj_worker->list_move->elm.itemp,
obj_worker->elm.itemp, field, field);
return 0;
}
static void
free_worker(struct obj_worker *obj_worker)
{
if (obj_bench.position_mode == POSITION_MODE_RAND)
free(obj_worker->fn_positions);
free(obj_worker);
}
static void
free_worker_list(struct benchmark *bench, struct benchmark_args *args,
struct worker_info *worker)
{
struct obj_worker *obj_worker = (struct obj_worker *)worker->priv;
obj_bench.args->queue ? queue_free_worker_list(obj_worker)
: obj_free_worker_list(obj_worker);
free_worker(obj_worker);
}
static void
free_worker_items(struct benchmark *bench, struct benchmark_args *args,
struct worker_info *worker)
{
struct obj_worker *obj_worker = (struct obj_worker *)worker->priv;
struct obj_list_args *obj_args = (struct obj_list_args *)args->opts;
obj_args->queue ? queue_free_worker_items(obj_worker)
: obj_free_worker_items(obj_worker);
free_worker(obj_worker);
}
static void
obj_move_free_worker(struct benchmark *bench, struct benchmark_args *args,
struct worker_info *worker)
{
struct obj_worker *obj_worker = (struct obj_worker *)worker->priv;
while (!POBJ_LIST_EMPTY(&obj_worker->list_move->head))
POBJ_LIST_REMOVE_FREE(
obj_bench.pop, &obj_worker->list_move->head,
POBJ_LIST_LAST(&obj_worker->list_move->head, field),
field);
if (obj_bench.position_mode == POSITION_MODE_RAND)
free(obj_worker->list_move->fn_positions);
free(obj_worker->list_move);
free_worker_list(bench, args, worker);
}
static int
obj_init_worker(struct worker_info *worker, size_t n_elm, size_t list_len)
{
struct obj_worker *obj_worker =
(struct obj_worker *)calloc(1, sizeof(struct obj_worker));
if (obj_worker == NULL) {
perror("calloc");
return -1;
}
worker->priv = obj_worker;
obj_worker->n_elm = obj_bench.max_len;
obj_worker->list_move = NULL;
if (obj_bench.position_mode == POSITION_MODE_RAND) {
obj_worker->fn_positions = random_positions();
if (obj_worker->fn_positions == NULL)
goto err;
}
if (obj_bench.fn_init(worker, n_elm, list_len) != 0)
goto err_positions;
return 0;
err_positions:
free(obj_worker->fn_positions);
err:
free(obj_worker);
return -1;
}
static int
obj_insert_init_worker(struct benchmark *bench, struct benchmark_args *args,
struct worker_info *worker)
{
return obj_init_worker(worker, obj_bench.max_len, obj_bench.min_len);
}
static int
obj_insert_new_init_worker(struct benchmark *bench, struct benchmark_args *args,
struct worker_info *worker)
{
return obj_init_worker(worker, obj_bench.min_len, obj_bench.min_len);
}
static int
obj_remove_init_worker(struct benchmark *bench, struct benchmark_args *args,
struct worker_info *worker)
{
return obj_init_worker(worker, obj_bench.max_len, obj_bench.max_len);
}
static int
obj_move_init_worker(struct benchmark *bench, struct benchmark_args *args,
struct worker_info *worker)
{
if (obj_init_worker(worker, obj_bench.max_len, obj_bench.max_len) != 0)
return -1;
struct obj_worker *obj_worker = (struct obj_worker *)worker->priv;
obj_worker->list_move =
(struct obj_worker *)calloc(1, sizeof(struct obj_worker));
if (obj_worker->list_move == NULL) {
perror("calloc");
goto free;
}
size_t i;
if (obj_bench.position_mode == POSITION_MODE_RAND) {
obj_worker->list_move->fn_positions = random_positions();
if (obj_worker->list_move->fn_positions == NULL)
goto free_list_move;
}
for (i = 0; i < obj_bench.min_len; i++) {
size_t size = obj_bench.alloc_sizes[i];
POBJ_LIST_INSERT_NEW_TAIL(obj_bench.pop,
&obj_worker->list_move->head, field,
size, NULL, NULL);
if (TOID_IS_NULL(POBJ_LIST_LAST(&obj_worker->list_move->head,
field))) {
perror("pmemobj_list_insert_new");
goto free_all;
}
}
return 0;
free_all:
for (; i > 0; i--) {
POBJ_LIST_REMOVE_FREE(
obj_bench.pop, &obj_worker->list_move->head,
POBJ_LIST_LAST(&obj_worker->list_move->head, field),
field);
}
free(obj_worker->list_move->fn_positions);
free_list_move:
free(obj_worker->list_move);
free:
free_worker_list(bench, args, worker);
return -1;
}
static int
obj_init(struct benchmark *bench, struct benchmark_args *args)
{
assert(bench != NULL);
assert(args != NULL);
assert(args->opts != NULL);
obj_bench.args = (struct obj_list_args *)args->opts;
obj_bench.min_len = obj_bench.args->list_len + 1;
obj_bench.max_len = args->n_ops_per_thread + obj_bench.min_len;
obj_bench.fn_init =
obj_bench.args->queue ? queue_init_list : obj_init_list;
size_t obj_size = args->dsize < sizeof(struct item)
? sizeof(struct item)
: args->dsize;
size_t min_size = obj_bench.args->min_size < sizeof(struct item)
? sizeof(struct item)
: obj_bench.args->min_size;
obj_bench.alloc_sizes = random_values(
min_size, obj_size, obj_bench.max_len, sizeof(struct item));
if (obj_bench.alloc_sizes == NULL)
goto free_random_types;
obj_bench.position_mode =
parse_args(obj_bench.args->position, POSITION_MODE_UNKNOWN,
position_names);
if (obj_bench.position_mode == POSITION_MODE_UNKNOWN)
goto free_all;
obj_bench.fn_position = positions[obj_bench.position_mode];
if (!obj_bench.args->queue) {
obj_bench.type_mode =
parse_args(obj_bench.args->type_num, TYPE_MODE_UNKNOWN,
type_num_names);
if (obj_bench.type_mode == TYPE_MODE_UNKNOWN)
return -1;
obj_bench.fn_type_num = type_num_modes[obj_bench.type_mode];
if (obj_bench.type_mode == TYPE_MODE_RAND) {
obj_bench.random_types = random_values(
1, UINT32_MAX, obj_bench.max_len, 0);
if (obj_bench.random_types == NULL)
return -1;
}
size_t psize =
(args->n_ops_per_thread + obj_bench.min_len + 1) *
obj_size * args->n_threads * FACTOR;
if (args->is_poolset) {
if (args->fsize < psize) {
fprintf(stderr, "insufficient size "
"of poolset\n");
goto free_all;
}
psize = 0;
} else {
if (psize < PMEMOBJ_MIN_POOL)
psize = PMEMOBJ_MIN_POOL;
}
if ((obj_bench.pop = pmemobj_create(args->fname, LAYOUT_NAME,
psize, args->fmode)) ==
NULL) {
perror(pmemobj_errormsg());
goto free_all;
}
}
return 0;
free_all:
free(obj_bench.alloc_sizes);
free_random_types:
if (obj_bench.type_mode == TYPE_MODE_RAND)
free(obj_bench.random_types);
return -1;
}
static int
obj_exit(struct benchmark *bench, struct benchmark_args *args)
{
if (!obj_bench.args->queue) {
pmemobj_close(obj_bench.pop);
if (obj_bench.type_mode == TYPE_MODE_RAND)
free(obj_bench.random_types);
}
free(obj_bench.alloc_sizes);
return 0;
}
static struct benchmark_clo obj_list_clo[6];
static struct benchmark_info obj_insert;
static struct benchmark_info obj_remove;
static struct benchmark_info obj_insert_new;
static struct benchmark_info obj_remove_free;
static struct benchmark_info obj_move;
CONSTRUCTOR(pmem_atomic_list_costructor)
void
pmem_atomic_list_costructor(void)
{
obj_list_clo[0].opt_short = 'T';
obj_list_clo[0].opt_long = "type-number";
obj_list_clo[0].descr = "Type number mode - one, per-thread, "
"rand";
obj_list_clo[0].def = "one";
obj_list_clo[0].off = clo_field_offset(struct obj_list_args, type_num);
obj_list_clo[0].type = CLO_TYPE_STR;
obj_list_clo[1].opt_short = 'P';
obj_list_clo[1].opt_long = "position";
obj_list_clo[1].descr = "Place where operation will be "
"performed - head, tail, rand, middle";
obj_list_clo[1].def = "middle";
obj_list_clo[1].off = clo_field_offset(struct obj_list_args, position);
obj_list_clo[1].type = CLO_TYPE_STR;
obj_list_clo[2].opt_short = 'l';
obj_list_clo[2].opt_long = "list-len";
obj_list_clo[2].type = CLO_TYPE_UINT;
obj_list_clo[2].descr = "Initial list len";
obj_list_clo[2].off = clo_field_offset(struct obj_list_args, list_len);
obj_list_clo[2].def = "1";
obj_list_clo[2].type_uint.size =
clo_field_size(struct obj_list_args, list_len);
obj_list_clo[2].type_uint.base = CLO_INT_BASE_DEC | CLO_INT_BASE_HEX;
obj_list_clo[2].type_uint.min = 1;
obj_list_clo[2].type_uint.max = ULONG_MAX;
obj_list_clo[3].opt_short = 'm';
obj_list_clo[3].opt_long = "min-size";
obj_list_clo[3].type = CLO_TYPE_UINT;
obj_list_clo[3].descr = "Min allocation size";
obj_list_clo[3].off = clo_field_offset(struct obj_list_args, min_size);
obj_list_clo[3].def = "0";
obj_list_clo[3].type_uint.size =
clo_field_size(struct obj_list_args, min_size);
obj_list_clo[3].type_uint.base = CLO_INT_BASE_DEC;
obj_list_clo[3].type_uint.min = 0;
obj_list_clo[3].type_uint.max = UINT_MAX;
obj_list_clo[4].opt_short = 's';
obj_list_clo[4].type_uint.max = INT_MAX;
obj_list_clo[4].opt_long = "seed";
obj_list_clo[4].type = CLO_TYPE_UINT;
obj_list_clo[4].descr = "Seed value";
obj_list_clo[4].off = clo_field_offset(struct obj_list_args, seed);
obj_list_clo[4].def = "0";
obj_list_clo[4].type_uint.size =
clo_field_size(struct obj_list_args, seed);
obj_list_clo[4].type_uint.base = CLO_INT_BASE_DEC;
obj_list_clo[4].type_uint.min = 0;
obj_list_clo[5].opt_short = 'q';
obj_list_clo[5].opt_long = "queue";
obj_list_clo[5].descr = "Use circleq from queue.h instead "
"pmemobj";
obj_list_clo[5].type = CLO_TYPE_FLAG;
obj_list_clo[5].off = clo_field_offset(struct obj_list_args, queue);
obj_insert.name = "obj_insert";
obj_insert.brief = "pmemobj_list_insert() benchmark";
obj_insert.init = obj_init;
obj_insert.exit = obj_exit;
obj_insert.multithread = true;
obj_insert.multiops = true;
obj_insert.init_worker = obj_insert_init_worker;
obj_insert.free_worker = free_worker_items;
obj_insert.operation = insert_op;
obj_insert.measure_time = true;
obj_insert.clos = obj_list_clo;
obj_insert.nclos = ARRAY_SIZE(obj_list_clo);
obj_insert.opts_size = sizeof(struct obj_list_args);
obj_insert.rm_file = true;
obj_insert.allow_poolset = true;
REGISTER_BENCHMARK(obj_insert);
obj_remove.name = "obj_remove";
obj_remove.brief = "pmemobj_list_remove() benchmark "
"without freeing element";
obj_remove.init = obj_init;
obj_remove.exit = obj_exit;
obj_remove.multithread = true;
obj_remove.multiops = true;
obj_remove.init_worker = obj_remove_init_worker;
obj_remove.free_worker = free_worker_items;
obj_remove.operation = remove_op;
obj_remove.measure_time = true;
obj_remove.clos = obj_list_clo;
obj_remove.nclos = ARRAY_SIZE(obj_list_clo);
obj_remove.opts_size = sizeof(struct obj_list_args);
obj_remove.rm_file = true;
obj_remove.allow_poolset = true;
REGISTER_BENCHMARK(obj_remove);
obj_insert_new.name = "obj_insert_new";
obj_insert_new.brief = "pmemobj_list_insert_new() benchmark";
obj_insert_new.init = obj_init;
obj_insert_new.exit = obj_exit;
obj_insert_new.multithread = true;
obj_insert_new.multiops = true;
obj_insert_new.init_worker = obj_insert_new_init_worker;
obj_insert_new.free_worker = free_worker_list;
obj_insert_new.operation = obj_insert_new_op;
obj_insert_new.measure_time = true;
obj_insert_new.clos = obj_list_clo;
obj_insert_new.nclos = ARRAY_SIZE(obj_list_clo) - 1;
obj_insert_new.opts_size = sizeof(struct obj_list_args);
obj_insert_new.rm_file = true;
obj_insert_new.allow_poolset = true;
REGISTER_BENCHMARK(obj_insert_new);
obj_remove_free.name = "obj_remove_free";
obj_remove_free.brief = "pmemobj_list_remove() benchmark "
"with freeing element";
obj_remove_free.init = obj_init;
obj_remove_free.exit = obj_exit;
obj_remove_free.multithread = true;
obj_remove_free.multiops = true;
obj_remove_free.init_worker = obj_remove_init_worker;
obj_remove_free.free_worker = free_worker_list;
obj_remove_free.operation = obj_remove_free_op;
obj_remove_free.measure_time = true;
obj_remove_free.clos = obj_list_clo;
obj_remove_free.nclos = ARRAY_SIZE(obj_list_clo) - 1;
obj_remove_free.opts_size = sizeof(struct obj_list_args);
obj_remove_free.rm_file = true;
obj_remove_free.allow_poolset = true;
REGISTER_BENCHMARK(obj_remove_free);
obj_move.name = "obj_move";
obj_move.brief = "pmemobj_list_move() benchmark";
obj_move.init = obj_init;
obj_move.exit = obj_exit;
obj_move.multithread = true;
obj_move.multiops = true;
obj_move.init_worker = obj_move_init_worker;
obj_move.free_worker = obj_move_free_worker;
obj_move.operation = obj_move_op;
obj_move.measure_time = true;
obj_move.clos = obj_list_clo;
obj_move.nclos = ARRAY_SIZE(obj_list_clo) - 1;
obj_move.opts_size = sizeof(struct obj_list_args);
obj_move.rm_file = true;
obj_move.allow_poolset = true;
REGISTER_BENCHMARK(obj_move);
}