X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fdmclock%2Fsim%2Fsrc%2Fsimulate.h;fp=src%2Fceph%2Fsrc%2Fdmclock%2Fsim%2Fsrc%2Fsimulate.h;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=a967d004b6dcfcb0658edc2aa7740a6e8ffb5a21;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/dmclock/sim/src/simulate.h b/src/ceph/src/dmclock/sim/src/simulate.h deleted file mode 100644 index a967d00..0000000 --- a/src/ceph/src/dmclock/sim/src/simulate.h +++ /dev/null @@ -1,441 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab - -/* - * Copyright (C) 2016 Red Hat Inc. - */ - - -#pragma once - - -#include - -#include -#include -#include -#include -#include -#include -#include - - -namespace crimson { - namespace qos_simulation { - - template - class Simulation { - - public: - - using TimePoint = std::chrono::time_point; - - protected: - - using ClientMap = std::map; - using ServerMap = std::map; - - uint server_count = 0; - uint client_count = 0; - - ServerMap servers; - ClientMap clients; - std::vector server_ids; - - TimePoint early_time; - TimePoint servers_created_time; - TimePoint clients_created_time; - TimePoint clients_finished_time; - TimePoint late_time; - - std::default_random_engine prng; - - bool has_run = false; - - - public: - - double fmt_tp(const TimePoint& t) { - auto c = t.time_since_epoch().count(); - return uint64_t(c / 1000000.0 + 0.5) % 100000 / 1000.0; - } - - TimePoint now() { - return std::chrono::steady_clock::now(); - } - - using ClientBasedServerSelectFunc = - std::function; - - using ClientFilter = std::function; - - using ServerFilter = std::function; - - using ServerDataOutF = - std::function; - - using ClientDataOutF = - std::function; - - Simulation() : - early_time(now()), - prng(std::chrono::system_clock::now().time_since_epoch().count()) - { - // empty - } - - ~Simulation() { - for (auto c : clients) { - TC* cp = c.second; - delete cp; - } - - for (auto s : servers) { - delete s.second; - } - } - - uint get_client_count() const { return client_count; } - uint get_server_count() const { return server_count; } - TC& get_client(ClientId id) { return *clients[id]; } - TS& get_server(ServerId id) { return *servers[id]; } - const ServerId& get_server_id(uint index) const { - return server_ids[index]; - } - - - void add_servers(uint count, - std::function create_server_f) { - uint i = server_count; - - // increment server_count before creating servers since they - // will start running immediately and may use the server_count - // value; NB: this could still be an issue if servers are - // added with multiple add_servers calls; consider using a - // separate start function after all servers (and clients?) - // have been added - server_count += count; - - for (; i < server_count; ++i) { - server_ids.push_back(i); - servers[i] = create_server_f(i); - } - - servers_created_time = now(); - } - - - void add_clients(uint count, - std::function create_client_f) { - uint i = client_count; - - // increment client_count before creating clients since they - // will start running immediately and may use the client_count - // value (e.g., in the server selection function); NB: this could - // still be an issue if clients are added with multiple - // add_clients calls; consider using a separate start function - // after all clients have been added - client_count += count; - - for (; i < client_count; ++i) { - clients[i] = create_client_f(i); - } - - clients_created_time = now(); - } - - - void run() { - assert(server_count > 0); - assert(client_count > 0); - - std::cout << "simulation started" << std::endl; - - // clients are now running; wait for all to finish - - for (auto const &i : clients) { - i.second->wait_until_done(); - } - - late_time = clients_finished_time = now(); - - std::cout << "simulation completed in " << - std::chrono::duration_cast(clients_finished_time - servers_created_time).count() << - " millisecs" << std::endl; - - has_run = true; - } // run - - - void display_stats(std::ostream& out, - ServerDataOutF server_out_f, ClientDataOutF client_out_f, - ServerFilter server_filter = - [] (const ServerId&) { return true; }, - ClientFilter client_filter = - [] (const ClientId&) { return true; }, - int head_w = 12, int data_w = 7, int data_prec = 2) { - assert(has_run); - - // skip first 2 secondsd of data - const std::chrono::seconds skip_amount(0); - // calculate in groups of 5 seconds - const std::chrono::seconds measure_unit(2); - // unit to output reports in - const std::chrono::seconds report_unit(1); - - // compute and display stats - - TimePoint earliest_start = late_time; - TimePoint latest_start = early_time; - TimePoint earliest_finish = late_time; - TimePoint latest_finish = early_time; - - for (auto const &c : clients) { - auto start = c.second->get_op_times().front(); - auto end = c.second->get_op_times().back(); - - if (start < earliest_start) { earliest_start = start; } - if (start > latest_start) { latest_start = start; } - if (end < earliest_finish) { earliest_finish = end; } - if (end > latest_finish) { latest_finish = end; } - } - - double ops_factor = - std::chrono::duration_cast>(measure_unit) / - std::chrono::duration_cast>(report_unit); - - const auto start_edge = clients_created_time + skip_amount; - - std::map> ops_data; - - for (auto const &c : clients) { - auto it = c.second->get_op_times().begin(); - const auto end = c.second->get_op_times().end(); - while (it != end && *it < start_edge) { ++it; } - - for (auto time_edge = start_edge + measure_unit; - time_edge <= latest_finish + measure_unit; - time_edge += measure_unit) { - int count = 0; - for (; it != end && *it < time_edge; ++count, ++it) { /* empty */ } - double ops_per_second = double(count) / ops_factor; - ops_data[c.first].push_back(ops_per_second); - } - } - - out << "==== Client Data ====" << std::endl; - - out << std::setw(head_w) << "client:"; - for (auto const &c : clients) { - if (!client_filter(c.first)) continue; - out << " " << std::setw(data_w) << c.first; - } - out << std::setw(data_w) << "total" << std::endl; - - { - bool has_data; - size_t i = 0; - do { - std::string line_header = "t_" + std::to_string(i) + ":"; - out << std::setw(head_w) << line_header; - has_data = false; - double total = 0.0; - for (auto const &c : clients) { - double data = 0.0; - if (i < ops_data[c.first].size()) { - data = ops_data[c.first][i]; - has_data = true; - } - total += data; - - if (!client_filter(c.first)) continue; - - out << " " << std::setw(data_w) << std::setprecision(data_prec) << - std::fixed << data; - } - out << " " << std::setw(data_w) << std::setprecision(data_prec) << - std::fixed << total << std::endl; - ++i; - } while(has_data); - } - - client_out_f(out, this, client_filter, head_w, data_w, data_prec); - - display_client_internal_stats(out, - "nanoseconds"); - - out << std::endl << "==== Server Data ====" << std::endl; - - out << std::setw(head_w) << "server:"; - for (auto const &s : servers) { - if (!server_filter(s.first)) continue; - out << " " << std::setw(data_w) << s.first; - } - out << " " << std::setw(data_w) << "total" << std::endl; - - server_out_f(out, this, server_filter, head_w, data_w, data_prec); - - display_server_internal_stats(out, - "nanoseconds"); - - // clean up clients then servers - - for (auto i = clients.begin(); i != clients.end(); ++i) { - delete i->second; - i->second = nullptr; - } - - for (auto i = servers.begin(); i != servers.end(); ++i) { - delete i->second; - i->second = nullptr; - } - } // display_stats - - - template - void display_server_internal_stats(std::ostream& out, - std::string time_unit) { - T add_request_time(0); - T request_complete_time(0); - uint32_t add_request_count = 0; - uint32_t request_complete_count = 0; - - for (uint i = 0; i < get_server_count(); ++i) { - const auto& server = get_server(i); - const auto& is = server.get_internal_stats(); - add_request_time += - std::chrono::duration_cast(is.add_request_time); - request_complete_time += - std::chrono::duration_cast(is.request_complete_time); - add_request_count += is.add_request_count; - request_complete_count += is.request_complete_count; - } - - double add_request_time_per_unit = - double(add_request_time.count()) / add_request_count ; - out << "total time to add requests: " << - std::fixed << add_request_time.count() << " " << time_unit << - ";" << std::endl << - " count: " << add_request_count << ";" << std::endl << - " average: " << add_request_time_per_unit << - " " << time_unit << " per request/response" << std::endl; - - double request_complete_time_unit = - double(request_complete_time.count()) / request_complete_count ; - out << "total time to note requests complete: " << std::fixed << - request_complete_time.count() << " " << time_unit << ";" << - std::endl << - " count: " << request_complete_count << ";" << std::endl << - " average: " << request_complete_time_unit << - " " << time_unit << " per request/response" << std::endl; - - out << std::endl; - - assert(add_request_count == request_complete_count); - out << "server timing for QOS algorithm: " << - add_request_time_per_unit + request_complete_time_unit << - " " << time_unit << " per request/response" << std::endl; - } - - - template - void display_client_internal_stats(std::ostream& out, - std::string time_unit) { - T track_resp_time(0); - T get_req_params_time(0); - uint32_t track_resp_count = 0; - uint32_t get_req_params_count = 0; - - for (uint i = 0; i < get_client_count(); ++i) { - const auto& client = get_client(i); - const auto& is = client.get_internal_stats(); - track_resp_time += - std::chrono::duration_cast(is.track_resp_time); - get_req_params_time += - std::chrono::duration_cast(is.get_req_params_time); - track_resp_count += is.track_resp_count; - get_req_params_count += is.get_req_params_count; - } - - double track_resp_time_unit = - double(track_resp_time.count()) / track_resp_count; - out << "total time to track responses: " << - std::fixed << track_resp_time.count() << " " << time_unit << ";" << - std::endl << - " count: " << track_resp_count << ";" << std::endl << - " average: " << track_resp_time_unit << " " << time_unit << - " per request/response" << std::endl; - - double get_req_params_time_unit = - double(get_req_params_time.count()) / get_req_params_count; - out << "total time to get request parameters: " << - std::fixed << get_req_params_time.count() << " " << time_unit << - ";" << std::endl << - " count: " << get_req_params_count << ";" << std::endl << - " average: " << get_req_params_time_unit << " " << time_unit << - " per request/response" << std::endl; - - out << std::endl; - - assert(track_resp_count == get_req_params_count); - out << "client timing for QOS algorithm: " << - track_resp_time_unit + get_req_params_time_unit << " " << - time_unit << " per request/response" << std::endl; - } - - - // **** server selection functions **** - - - const ServerId& server_select_alternate(uint64_t seed, - uint16_t client_idx) { - uint index = (client_idx + seed) % server_count; - return server_ids[index]; - } - - - // returns a lambda using the range specified as servers_per (client) - ClientBasedServerSelectFunc - make_server_select_alt_range(uint16_t servers_per) { - return [servers_per,this](uint64_t seed, uint16_t client_idx) - -> const ServerId& { - double factor = double(server_count) / client_count; - uint offset = seed % servers_per; - uint index = (uint(0.5 + client_idx * factor) + offset) % server_count; - return server_ids[index]; - }; - } - - - // function to choose a server randomly - const ServerId& server_select_random(uint64_t seed, uint16_t client_idx) { - uint index = prng() % server_count; - return server_ids[index]; - } - - - // function to choose a server randomly - ClientBasedServerSelectFunc - make_server_select_ran_range(uint16_t servers_per) { - return [servers_per,this](uint64_t seed, uint16_t client_idx) - -> const ServerId& { - double factor = double(server_count) / client_count; - uint offset = prng() % servers_per; - uint index = (uint(0.5 + client_idx * factor) + offset) % server_count; - return server_ids[index]; - }; - } - - - // function to always choose the first server - const ServerId& server_select_0(uint64_t seed, uint16_t client_idx) { - return server_ids[0]; - } - }; // class Simulation - - }; // namespace qos_simulation -}; // namespace crimson