|
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 |
}
|