
git-subtree-dir: deps/memkind/src git-subtree-split: bb9f19dd1b3ed6cc5e1b35919564ccf6f4b32f69
232 lines
8.5 KiB
C++
232 lines
8.5 KiB
C++
/*
|
|
* Copyright (C) 2015 - 2018 Intel Corporation.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
* 1. Redistributions of source code must retain the above copyright notice(s),
|
|
* this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice(s),
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS
|
|
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
* EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
#include "Configuration.hpp"
|
|
#include "AllocatorFactory.hpp"
|
|
#include "TaskFactory.hpp"
|
|
#include "Task.hpp"
|
|
#include "ConsoleLog.hpp"
|
|
#include "Stats.hpp"
|
|
#include "Thread.hpp"
|
|
#include "Tests.hpp"
|
|
#include "CommandLine.hpp"
|
|
#include "FunctionCallsPerformanceTask.h"
|
|
#include "StressIncreaseToMax.h"
|
|
|
|
/*
|
|
Command line description.
|
|
Syntax:
|
|
key=value
|
|
Options:
|
|
- 'test' - specify the test case. This option can be used with the following values: 'calls', 'all' or 'self',
|
|
where:
|
|
'calls' - function calls performance test,
|
|
'all' - execute both above ('footprint' and 'calls') tests,
|
|
'self' - execute self tests
|
|
's1' - stress tests
|
|
(perform allocations until the maximum amount of allocated memory has been reached, than frees allocated memory.
|
|
If the time interval has not been exceed, than repeat the test),
|
|
- 'operations' - the number of memory operations per thread
|
|
- 'size_from' - lower bound for the random sizes of allocation
|
|
- 'size_to' - upper bound for the random sizes of allocation
|
|
- 'seed' - random seed
|
|
- 'threads_num' - the number of threads per test case
|
|
- 'time' - minimum execution time interval
|
|
- 'kind' - the kind to test
|
|
- 'csv_log' - if 'true' then log to csv file memory operations and statistics
|
|
- 'call' specify the allocation function call. This option can be used with the following values: 'malloc' (default), 'calloc', 'realloc',
|
|
- 'requested_memory_limit' test stops when the requested memory limit has been reached
|
|
* - maximum of available memory in OS, or maximum memory based 'operations' parameter
|
|
Example:
|
|
1. Performance test:
|
|
./perf_tool test=all operations=1000 size_from=32 size_to=20480 seed=11 threads_num=200
|
|
2. Stress test
|
|
./perf_tool test=s1 time=120 kind=MEMKIND_HBW size_from=1048576 csv_log=true requested_memory_limit=1048576
|
|
*/
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
unsigned mem_operations_num = 1000;
|
|
size_t size_from = 32, size_to = 2048*1024;
|
|
unsigned seed = 11;
|
|
//should be at least one
|
|
size_t threads_number = 10;
|
|
|
|
CommandLine cmd_line(argc, argv);
|
|
|
|
if((argc >= 1) && cmd_line.is_option_set("test", "self")) {
|
|
execute_self_tests();
|
|
getchar();
|
|
}
|
|
|
|
cmd_line.parse_with_strtol("operations", mem_operations_num);
|
|
cmd_line.parse_with_strtol("size_from", size_from);
|
|
cmd_line.parse_with_strtol("size_to", size_to);
|
|
cmd_line.parse_with_strtol("seed", seed);
|
|
cmd_line.parse_with_strtol("threads_num", threads_number);
|
|
|
|
bool is_csv_log_enabled = cmd_line.is_option_set("csv_log", "true");
|
|
|
|
//Heap Manager initialization
|
|
std::vector<AllocatorFactory::initialization_stat> stats =
|
|
AllocatorFactory().initialization_test();
|
|
|
|
if(!cmd_line.is_option_set("print_init_stats", "false")) {
|
|
printf("\nInitialization overhead:\n");
|
|
for (int i=0; i<stats.size(); i++) {
|
|
AllocatorFactory::initialization_stat stat = stats[i];
|
|
printf("%32s : time=%7.7f.s, ref_delta_time=%15f, node0=%10fMB, node1=%7.7fMB\n",
|
|
AllocatorTypes::allocator_name(stat.allocator_type).c_str(),
|
|
stat.total_time,
|
|
stat.ref_delta_time,
|
|
stat.memory_overhead[0],
|
|
stat.memory_overhead[1]);
|
|
}
|
|
}
|
|
|
|
//Stress test by repeatedly increasing memory (to maximum), until given time interval has been exceed.
|
|
if(cmd_line.is_option_set("test", "s1")) {
|
|
printf("Stress test (StressIncreaseToMax) start. \n");
|
|
|
|
if(!cmd_line.is_option_present("operations"))
|
|
mem_operations_num = 1000000;
|
|
|
|
unsigned time = 120; //Default time interval.
|
|
cmd_line.parse_with_strtol("time", time);
|
|
|
|
size_t requested_memory_limit = 1024*1024;
|
|
cmd_line.parse_with_strtol("requested_memory_limit", requested_memory_limit);
|
|
|
|
unsigned allocator = AllocatorTypes::MEMKIND_HBW;
|
|
if(cmd_line.is_option_present("kind")) {
|
|
//Enable memkind allocator and specify kind.
|
|
allocator = AllocatorTypes::allocator_type(cmd_line.get_option_value("kind"));
|
|
}
|
|
TypesConf allocator_types;
|
|
allocator_types.enable_type(allocator);
|
|
|
|
TypesConf enable_func_calls;
|
|
enable_func_calls.enable_type(FunctionCalls::MALLOC);
|
|
|
|
TaskConf task_conf = {
|
|
mem_operations_num,
|
|
{
|
|
mem_operations_num,
|
|
size_from, //No random sizes.
|
|
size_from
|
|
},
|
|
enable_func_calls,
|
|
allocator_types,
|
|
11,
|
|
is_csv_log_enabled,
|
|
};
|
|
|
|
StressIncreaseToMax::execute_test_iterations(task_conf, time,
|
|
requested_memory_limit);
|
|
return 0;
|
|
}
|
|
|
|
printf("\nTest configuration: \n");
|
|
printf("\t memory operations per thread = %u \n", mem_operations_num);
|
|
printf("\t seed = %d\n", seed);
|
|
printf("\t number of threads = %zu\n", threads_number);
|
|
printf("\t size from-to = %zu-%zu\n\n", size_from, size_to);
|
|
|
|
assert(size_from <= size_to);
|
|
|
|
|
|
TypesConf func_calls;
|
|
func_calls.enable_type(FunctionCalls::FREE);
|
|
|
|
if(cmd_line.is_option_present("call")) {
|
|
//Enable heap manager function call.
|
|
func_calls.enable_type(FunctionCalls::function_type(
|
|
cmd_line.get_option_value("call")));
|
|
} else {
|
|
func_calls.enable_type(FunctionCalls::MALLOC);
|
|
}
|
|
|
|
TypesConf allocator_types;
|
|
if(cmd_line.is_option_present("allocator")) {
|
|
allocator_types.enable_type(AllocatorTypes::allocator_type(
|
|
cmd_line.get_option_value("allocator")));
|
|
} else {
|
|
for(unsigned i = 0; i <= AllocatorTypes::MEMKIND_HBW_PREFERRED; i++) {
|
|
allocator_types.enable_type(i);
|
|
}
|
|
}
|
|
|
|
TaskConf conf = {
|
|
mem_operations_num, //number memory operations
|
|
{
|
|
mem_operations_num, //number of memory operations
|
|
size_from, //min. size of single allocation
|
|
size_to //max. size of single allocatioion
|
|
},
|
|
func_calls, //enable function calls
|
|
allocator_types, //enable allocators
|
|
seed, //random seed
|
|
is_csv_log_enabled,
|
|
};
|
|
|
|
//Function calls test
|
|
if(cmd_line.is_option_set("test", "calls") ||
|
|
cmd_line.is_option_set("test", "all")) {
|
|
TaskFactory task_factory;
|
|
std::vector<Thread *> threads;
|
|
std::vector<Task *> tasks;
|
|
|
|
for (int i=0; i<threads_number; i++) {
|
|
FunctionCallsPerformanceTask *task =
|
|
static_cast<FunctionCallsPerformanceTask *>(
|
|
task_factory.create(conf)
|
|
);
|
|
tasks.push_back(task);
|
|
threads.push_back(new Thread(task));
|
|
conf.seed += 1;
|
|
}
|
|
|
|
ThreadsManager threads_manager(threads);
|
|
threads_manager.start();
|
|
threads_manager.barrier();
|
|
|
|
TimeStats stats;
|
|
for (int i=0; i<tasks.size(); i++) {
|
|
stats += tasks[i]->get_results();
|
|
}
|
|
|
|
ConsoleLog::print_table(stats);
|
|
ConsoleLog::print_requested_memory(stats, "func. calls test");
|
|
|
|
threads_manager.release();
|
|
}
|
|
|
|
return 0;
|
|
}
|