Blame test/fragmentation_benchmark_pmem.cpp

Packit 345191
/*
Packit 345191
 * Copyright (C) 2019 Intel Corporation.
Packit 345191
 * All rights reserved.
Packit 345191
 *
Packit 345191
 * Redistribution and use in source and binary forms, with or without
Packit 345191
 * modification, are permitted provided that the following conditions are met:
Packit 345191
 * 1. Redistributions of source code must retain the above copyright notice(s),
Packit 345191
 *    this list of conditions and the following disclaimer.
Packit 345191
 * 2. Redistributions in binary form must reproduce the above copyright notice(s),
Packit 345191
 *    this list of conditions and the following disclaimer in the documentation
Packit 345191
 *    and/or other materials provided with the distribution.
Packit 345191
 *
Packit 345191
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS
Packit 345191
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
Packit 345191
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
Packit 345191
 * EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit 345191
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 345191
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Packit 345191
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Packit 345191
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
Packit 345191
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
Packit 345191
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 345191
 */
Packit 345191
Packit 345191
#include <memkind.h>
Packit 345191
Packit 345191
#include <iostream>
Packit 345191
#include <chrono>
Packit 345191
#include <cstdio>
Packit 345191
#include <cstring>
Packit 345191
#include <ctime>
Packit 345191
#include <random>
Packit 345191
#include <vector>
Packit 345191
Packit 345191
#define MB (1024 * 1024)
Packit 345191
#define PRINT_FREQ 100000
Packit 345191
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
Packit 345191
#define BENCHMARK_LOG "bench_single_thread_%Y%m%d-%H%M"
Packit 345191
Packit 345191
static size_t block_size [] =
Packit 345191
{8519680, 4325376, 8519680, 4325376, 8519680, 4325376, 8519680, 4325376, 432517, 608478};
Packit 345191
Packit 345191
static struct memkind *pmem_kind;
Packit 345191
static FILE *log_file;
Packit 345191
Packit 345191
static const char *const log_tag[] = {
Packit 345191
    "_mem_default.log",
Packit 345191
    "_mem_conservative.log"
Packit 345191
};
Packit 345191
Packit 345191
static void usage(char *name)
Packit 345191
{
Packit 345191
    fprintf(stderr,
Packit 345191
            "Usage: %s pmem_kind_dir_path pmem_size pmem_policy test_time_limit_in_sec\n",
Packit 345191
            name);
Packit 345191
}
Packit 345191
Packit 345191
static int fragmentatation_test(size_t pmem_max_size, double test_time)
Packit 345191
{
Packit 345191
    std::random_device rd;
Packit 345191
    std::mt19937 mt(rd());
Packit 345191
    std::uniform_int_distribution<> m_size(0, ARRAY_SIZE(block_size) - 1);
Packit 345191
    char *pmem_str = nullptr;
Packit 345191
    std::vector<char *> pmem_strs;
Packit 345191
    size_t total_size = pmem_max_size;
Packit 345191
    size_t print_iter = 0;
Packit 345191
    size_t total_allocated = 0;
Packit 345191
    double elapsed_seconds;
Packit 345191
    auto start = std::chrono::steady_clock::now();
Packit 345191
Packit 345191
    do {
Packit 345191
        print_iter++;
Packit 345191
        int index = m_size(mt);
Packit 345191
        size_t size = block_size[index];
Packit 345191
        size_t length = pmem_strs.size() / 2;
Packit 345191
        std::uniform_int_distribution<size_t> m_index(0, length - 1);
Packit 345191
Packit 345191
        while ((pmem_str = static_cast<char *>(memkind_malloc(pmem_kind,
Packit 345191
                                                              size))) == nullptr) {
Packit 345191
            size_t to_evict = m_index(mt);
Packit 345191
            char *str_to_evict = pmem_strs[to_evict];
Packit 345191
            size_t evict_size = memkind_malloc_usable_size(pmem_kind, str_to_evict);
Packit 345191
            total_allocated -= evict_size;
Packit 345191
Packit 345191
            if (total_allocated < total_size * 0.1) {
Packit 345191
                fprintf(stderr,"allocated less than 10 percent.\n");
Packit 345191
                return 1;
Packit 345191
            }
Packit 345191
            memkind_free(pmem_kind, str_to_evict);
Packit 345191
            pmem_strs.erase(pmem_strs.begin() + to_evict);
Packit 345191
        }
Packit 345191
        pmem_strs.push_back(pmem_str);
Packit 345191
        total_allocated += memkind_malloc_usable_size(pmem_kind, pmem_str);
Packit 345191
Packit 345191
        if (print_iter % PRINT_FREQ == 0) {
Packit 345191
            fprintf(log_file,"%f\n", static_cast<double>(total_allocated) / total_size);
Packit 345191
            fflush(stdout);
Packit 345191
        }
Packit 345191
Packit 345191
        auto finish = std::chrono::steady_clock::now();
Packit 345191
        elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>
Packit 345191
                          (finish - start).count();
Packit 345191
    } while (elapsed_seconds < test_time);
Packit 345191
    return 0;
Packit 345191
}
Packit 345191
Packit 345191
static int create_pmem(const char *pmem_dir, size_t pmem_size,
Packit 345191
                       memkind_mem_usage_policy policy)
Packit 345191
{
Packit 345191
    int err = 0;
Packit 345191
    if (pmem_size == 0 ) {
Packit 345191
        fprintf(stderr, "Invalid size to pmem kind must be not equal zero.\n");
Packit 345191
        return 1;
Packit 345191
    }
Packit 345191
Packit 345191
    if (policy > MEMKIND_MEM_USAGE_POLICY_MAX_VALUE) {
Packit 345191
        fprintf(stderr, "Invalid memory usage policy param %u.\n", policy);
Packit 345191
        return 1;
Packit 345191
    }
Packit 345191
Packit 345191
    memkind_config *pmem_cfg = memkind_config_new();
Packit 345191
    if (!pmem_cfg) {
Packit 345191
        fprintf(stderr, "Unable to create pmem configuration.\n");
Packit 345191
        return 1;
Packit 345191
    }
Packit 345191
Packit 345191
    memkind_config_set_path(pmem_cfg, pmem_dir);
Packit 345191
    memkind_config_set_size(pmem_cfg, pmem_size);
Packit 345191
    memkind_config_set_memory_usage_policy(pmem_cfg, policy);
Packit 345191
Packit 345191
    err = memkind_create_pmem_with_config(pmem_cfg, &pmem_kind);
Packit 345191
    memkind_config_delete(pmem_cfg);
Packit 345191
    if (err) {
Packit 345191
        fprintf(stderr, "Unable to create pmem kind.\n");
Packit 345191
        return 1;
Packit 345191
    }
Packit 345191
Packit 345191
    return 0;
Packit 345191
}
Packit 345191
Packit 345191
static int create_log_file(memkind_mem_usage_policy policy)
Packit 345191
{
Packit 345191
    char file_name[100] = {'\0'};
Packit 345191
    auto result = std::time(nullptr);
Packit 345191
Packit 345191
    strftime(file_name, 100, BENCHMARK_LOG, std::localtime(&result));
Packit 345191
    std::strcat(file_name, log_tag[policy]);
Packit 345191
Packit 345191
    if ((log_file = fopen(file_name, "w+")) == nullptr) {
Packit 345191
        fprintf(stderr, "Cannot create output file %s.\n", file_name);
Packit 345191
        return 1;
Packit 345191
    }
Packit 345191
Packit 345191
    return 0;
Packit 345191
}
Packit 345191
Packit 345191
int main(int argc, char *argv[])
Packit 345191
{
Packit 345191
    char *pmem_dir;
Packit 345191
    size_t pmem_size;
Packit 345191
    memkind_mem_usage_policy pmem_policy;
Packit 345191
    double test_time_limit_in_sec;
Packit 345191
    int status = 0;
Packit 345191
    int err = 0;
Packit 345191
Packit 345191
    if (argc != 5) {
Packit 345191
        usage(argv[0]);
Packit 345191
        return 1;
Packit 345191
    } else {
Packit 345191
        pmem_dir = argv[1];
Packit 345191
        pmem_size = std::stoull(argv[2]) * MB;
Packit 345191
        pmem_policy = static_cast<memkind_mem_usage_policy>(std::stoul(argv[3]));
Packit 345191
        test_time_limit_in_sec = std::stod(argv[4]);
Packit 345191
    }
Packit 345191
Packit 345191
    err = create_pmem(pmem_dir, pmem_size, pmem_policy);
Packit 345191
    if (err) {
Packit 345191
        fprintf(stderr, "Cannot create pmem.\n");
Packit 345191
        return 1;
Packit 345191
    }
Packit 345191
Packit 345191
    err = create_log_file(pmem_policy);
Packit 345191
    if (err) {
Packit 345191
        memkind_destroy_kind(pmem_kind);
Packit 345191
        fprintf(stderr, "Cannot create log file.\n");
Packit 345191
        return 1;
Packit 345191
    }
Packit 345191
Packit 345191
    status = fragmentatation_test(pmem_size, test_time_limit_in_sec);
Packit 345191
Packit 345191
    err = memkind_destroy_kind(pmem_kind);
Packit 345191
    if (err) {
Packit 345191
        fprintf(stderr, "Unable to destroy pmem kind.\n");
Packit 345191
    }
Packit 345191
Packit 345191
    fclose(log_file);
Packit 345191
    return status;
Packit 345191
Packit 345191
}