Blame test/fragmentation_benchmark_pmem.cpp

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