2019-01-25 18:35:16 +00:00
|
|
|
#include "PerformanceTestInfo.h"
|
|
|
|
#include <Common/getMultipleKeysFromConfig.h>
|
|
|
|
#include <IO/ReadBufferFromFile.h>
|
|
|
|
#include <IO/ReadHelpers.h>
|
|
|
|
#include <IO/WriteBufferFromFile.h>
|
|
|
|
#include "applySubstitutions.h"
|
2019-07-31 22:37:41 +00:00
|
|
|
#include <filesystem>
|
2019-01-28 11:20:44 +00:00
|
|
|
#include <iostream>
|
2019-01-25 18:35:16 +00:00
|
|
|
|
2019-07-31 22:37:41 +00:00
|
|
|
|
2019-01-25 18:35:16 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int BAD_ARGUMENTS;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
|
|
|
|
void extractSettings(
|
|
|
|
const XMLConfigurationPtr & config,
|
2019-01-28 16:20:29 +00:00
|
|
|
const std::string & key,
|
2019-01-25 18:35:16 +00:00
|
|
|
const Strings & settings_list,
|
2019-04-25 14:08:20 +00:00
|
|
|
SettingsChanges & settings_to_apply)
|
2019-01-25 18:35:16 +00:00
|
|
|
{
|
2019-01-28 16:20:29 +00:00
|
|
|
for (const std::string & setup : settings_list)
|
2019-01-25 18:35:16 +00:00
|
|
|
{
|
|
|
|
if (setup == "profile")
|
|
|
|
continue;
|
|
|
|
|
2019-01-28 16:20:29 +00:00
|
|
|
std::string value = config->getString(key + "." + setup);
|
2019-01-25 18:35:16 +00:00
|
|
|
if (value.empty())
|
|
|
|
value = "true";
|
|
|
|
|
2019-04-25 14:08:20 +00:00
|
|
|
settings_to_apply.emplace_back(SettingChange{setup, value});
|
2019-01-25 18:35:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-31 22:37:41 +00:00
|
|
|
namespace fs = std::filesystem;
|
2019-01-25 18:35:16 +00:00
|
|
|
|
|
|
|
PerformanceTestInfo::PerformanceTestInfo(
|
|
|
|
XMLConfigurationPtr config,
|
2019-02-18 15:43:58 +00:00
|
|
|
const std::string & profiles_file_,
|
|
|
|
const Settings & global_settings_)
|
2019-01-25 18:35:16 +00:00
|
|
|
: profiles_file(profiles_file_)
|
2019-02-18 15:43:58 +00:00
|
|
|
, settings(global_settings_)
|
2019-01-25 18:35:16 +00:00
|
|
|
{
|
2019-01-31 13:46:43 +00:00
|
|
|
path = config->getString("path");
|
2019-06-18 14:37:27 +00:00
|
|
|
test_name = fs::path(path).stem().string();
|
2019-02-06 11:44:00 +00:00
|
|
|
if (config->has("main_metric"))
|
|
|
|
{
|
|
|
|
Strings main_metrics;
|
|
|
|
config->keys("main_metric", main_metrics);
|
|
|
|
if (main_metrics.size())
|
|
|
|
main_metric = main_metrics[0];
|
|
|
|
}
|
|
|
|
|
2019-01-25 18:35:16 +00:00
|
|
|
applySettings(config);
|
|
|
|
extractQueries(config);
|
2019-05-21 12:57:19 +00:00
|
|
|
extractAuxiliaryQueries(config);
|
2019-01-25 18:35:16 +00:00
|
|
|
processSubstitutions(config);
|
|
|
|
getExecutionType(config);
|
|
|
|
getStopConditions(config);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PerformanceTestInfo::applySettings(XMLConfigurationPtr config)
|
|
|
|
{
|
|
|
|
if (config->has("settings"))
|
|
|
|
{
|
2019-04-25 14:08:20 +00:00
|
|
|
SettingsChanges settings_to_apply;
|
2019-01-28 16:20:29 +00:00
|
|
|
Strings config_settings;
|
2019-01-25 18:35:16 +00:00
|
|
|
config->keys("settings", config_settings);
|
|
|
|
|
|
|
|
auto settings_contain = [&config_settings] (const std::string & setting)
|
|
|
|
{
|
|
|
|
auto position = std::find(config_settings.begin(), config_settings.end(), setting);
|
|
|
|
return position != config_settings.end();
|
|
|
|
|
|
|
|
};
|
|
|
|
/// Preprocess configuration file
|
|
|
|
if (settings_contain("profile"))
|
|
|
|
{
|
|
|
|
if (!profiles_file.empty())
|
|
|
|
{
|
2019-01-28 16:20:29 +00:00
|
|
|
std::string profile_name = config->getString("settings.profile");
|
2019-01-25 18:35:16 +00:00
|
|
|
XMLConfigurationPtr profiles_config(new XMLConfiguration(profiles_file));
|
|
|
|
|
2019-01-28 16:20:29 +00:00
|
|
|
Strings profile_settings;
|
2019-01-25 18:35:16 +00:00
|
|
|
profiles_config->keys("profiles." + profile_name, profile_settings);
|
|
|
|
|
|
|
|
extractSettings(profiles_config, "profiles." + profile_name, profile_settings, settings_to_apply);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extractSettings(config, "settings", config_settings, settings_to_apply);
|
2019-07-29 11:03:50 +00:00
|
|
|
settings.loadFromChanges(settings_to_apply);
|
2019-01-25 18:35:16 +00:00
|
|
|
|
|
|
|
if (settings_contain("average_rows_speed_precision"))
|
|
|
|
TestStats::avg_rows_speed_precision =
|
|
|
|
config->getDouble("settings.average_rows_speed_precision");
|
|
|
|
|
|
|
|
if (settings_contain("average_bytes_speed_precision"))
|
|
|
|
TestStats::avg_bytes_speed_precision =
|
|
|
|
config->getDouble("settings.average_bytes_speed_precision");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PerformanceTestInfo::extractQueries(XMLConfigurationPtr config)
|
|
|
|
{
|
|
|
|
if (config->has("query"))
|
|
|
|
queries = getMultipleValuesFromConfig(*config, "", "query");
|
|
|
|
|
|
|
|
if (config->has("query_file"))
|
|
|
|
{
|
2019-01-28 16:20:29 +00:00
|
|
|
const std::string filename = config->getString("query_file");
|
2019-01-25 18:35:16 +00:00
|
|
|
if (filename.empty())
|
|
|
|
throw Exception("Empty file name", ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
|
|
|
bool tsv = fs::path(filename).extension().string() == ".tsv";
|
|
|
|
|
|
|
|
ReadBufferFromFile query_file(filename);
|
|
|
|
std::string query;
|
|
|
|
|
|
|
|
if (tsv)
|
|
|
|
{
|
|
|
|
while (!query_file.eof())
|
|
|
|
{
|
|
|
|
readEscapedString(query, query_file);
|
|
|
|
assertChar('\n', query_file);
|
|
|
|
queries.push_back(query);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
readStringUntilEOF(query, query_file);
|
|
|
|
queries.push_back(query);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (queries.empty())
|
|
|
|
throw Exception("Did not find any query to execute: " + test_name,
|
|
|
|
ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PerformanceTestInfo::processSubstitutions(XMLConfigurationPtr config)
|
|
|
|
{
|
|
|
|
if (config->has("substitutions"))
|
|
|
|
{
|
|
|
|
/// Make "subconfig" of inner xml block
|
|
|
|
ConfigurationPtr substitutions_view(config->createView("substitutions"));
|
|
|
|
constructSubstitutions(substitutions_view, substitutions);
|
|
|
|
|
2019-05-21 12:57:19 +00:00
|
|
|
auto create_and_fill_queries_preformat = create_and_fill_queries;
|
|
|
|
create_and_fill_queries.clear();
|
|
|
|
for (const auto & query : create_and_fill_queries_preformat)
|
|
|
|
{
|
|
|
|
auto formatted = formatQueries(query, substitutions);
|
|
|
|
create_and_fill_queries.insert(create_and_fill_queries.end(), formatted.begin(), formatted.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
auto queries_preformat = queries;
|
2019-01-25 18:35:16 +00:00
|
|
|
queries.clear();
|
2019-05-21 12:57:19 +00:00
|
|
|
for (const auto & query : queries_preformat)
|
2019-01-25 18:35:16 +00:00
|
|
|
{
|
|
|
|
auto formatted = formatQueries(query, substitutions);
|
|
|
|
queries.insert(queries.end(), formatted.begin(), formatted.end());
|
|
|
|
}
|
2019-05-21 12:57:19 +00:00
|
|
|
|
|
|
|
auto drop_queries_preformat = drop_queries;
|
|
|
|
drop_queries.clear();
|
|
|
|
for (const auto & query : drop_queries_preformat)
|
|
|
|
{
|
|
|
|
auto formatted = formatQueries(query, substitutions);
|
|
|
|
drop_queries.insert(drop_queries.end(), formatted.begin(), formatted.end());
|
|
|
|
}
|
2019-01-25 18:35:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PerformanceTestInfo::getExecutionType(XMLConfigurationPtr config)
|
|
|
|
{
|
|
|
|
if (!config->has("type"))
|
|
|
|
throw Exception("Missing type property in config: " + test_name,
|
|
|
|
ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
2019-01-28 16:20:29 +00:00
|
|
|
std::string config_exec_type = config->getString("type");
|
2019-01-25 18:35:16 +00:00
|
|
|
if (config_exec_type == "loop")
|
|
|
|
exec_type = ExecutionType::Loop;
|
|
|
|
else if (config_exec_type == "once")
|
|
|
|
exec_type = ExecutionType::Once;
|
|
|
|
else
|
|
|
|
throw Exception("Unknown type " + config_exec_type + " in :" + test_name,
|
|
|
|
ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PerformanceTestInfo::getStopConditions(XMLConfigurationPtr config)
|
|
|
|
{
|
|
|
|
TestStopConditions stop_conditions_template;
|
|
|
|
if (config->has("stop_conditions"))
|
|
|
|
{
|
|
|
|
ConfigurationPtr stop_conditions_config(config->createView("stop_conditions"));
|
|
|
|
stop_conditions_template.loadFromConfig(stop_conditions_config);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stop_conditions_template.empty())
|
|
|
|
throw Exception("No termination conditions were found in config",
|
|
|
|
ErrorCodes::BAD_ARGUMENTS);
|
|
|
|
|
2019-01-28 11:20:44 +00:00
|
|
|
times_to_run = config->getUInt("times_to_run", 1);
|
|
|
|
|
2019-01-25 18:35:16 +00:00
|
|
|
for (size_t i = 0; i < times_to_run * queries.size(); ++i)
|
|
|
|
stop_conditions_by_run.push_back(stop_conditions_template);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-02-01 15:10:13 +00:00
|
|
|
void PerformanceTestInfo::extractAuxiliaryQueries(XMLConfigurationPtr config)
|
|
|
|
{
|
|
|
|
if (config->has("create_query"))
|
2019-05-22 11:36:31 +00:00
|
|
|
{
|
2019-05-21 12:57:19 +00:00
|
|
|
create_and_fill_queries = getMultipleValuesFromConfig(*config, "", "create_query");
|
2019-05-22 11:36:31 +00:00
|
|
|
}
|
2019-02-01 15:10:13 +00:00
|
|
|
|
2019-05-22 11:36:31 +00:00
|
|
|
if (config->has("fill_query"))
|
|
|
|
{
|
2019-05-21 12:57:19 +00:00
|
|
|
auto fill_queries = getMultipleValuesFromConfig(*config, "", "fill_query");
|
|
|
|
create_and_fill_queries.insert(create_and_fill_queries.end(), fill_queries.begin(), fill_queries.end());
|
|
|
|
}
|
2019-02-01 15:10:13 +00:00
|
|
|
|
|
|
|
if (config->has("drop_query"))
|
2019-05-22 11:36:31 +00:00
|
|
|
{
|
2019-02-01 15:10:13 +00:00
|
|
|
drop_queries = getMultipleValuesFromConfig(*config, "", "drop_query");
|
2019-05-22 11:36:31 +00:00
|
|
|
}
|
2019-02-01 15:10:13 +00:00
|
|
|
}
|
|
|
|
|
2019-01-25 18:35:16 +00:00
|
|
|
}
|