Loading CMakeLists.txt +6 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,12 @@ if(GKFS_USE_GUIDED_DISTRIBUTION) message(STATUS "[gekkofs] Guided data distributor input file path: ${GKFS_USE_GUIDED_DISTRIBUTION_PATH}") endif() option(GKFS_CHUNK_STATS "Gather Chunk Stats " OFF) if (GKFS_CHUNK_STATS) add_definitions(-DGKFS_CHUNK_STATS) endif () message(STATUS "[gekkofs] Gather Chunk Stats: ${GKFS_CHUNK_STATS}") configure_file(include/common/cmake_configure.hpp.in include/common/cmake_configure.hpp) Loading include/common/statistics/stats.hpp +58 −28 Original line number Diff line number Diff line Loading @@ -33,12 +33,15 @@ #include <unistd.h> #include <cassert> #include <map> #include <set> #include <vector> #include <deque> #include <chrono> #include <initializer_list> #include <thread> #include <iostream> #include <iomanip> #include <fstream> /** * Provides storage capabilities to provide stats about GekkoFS * The information is per server. Loading Loading @@ -70,27 +73,25 @@ public: IOPS_CREATE, IOPS_WRITE, IOPS_READ, IOPS_MKDIR, IOPS_RMDIR, IOPS_STATS, IOPS_DIRENTS, IOPS_REMOVE, }; enum class SIZE_OP { METADATA_SIZE, WRITE_SIZE, READ_SIZE, DATA_SIZE }; enum class SIZE_OP { WRITE_SIZE, READ_SIZE }; private: constexpr static const std::initializer_list<Stats::IOPS_OP> all_IOPS_OP = { IOPS_OP::IOPS_CREATE, IOPS_OP::IOPS_WRITE, IOPS_OP::IOPS_READ, IOPS_OP::IOPS_MKDIR, IOPS_OP::IOPS_RMDIR, IOPS_OP::IOPS_REMOVE}; IOPS_OP::IOPS_STATS, IOPS_OP::IOPS_DIRENTS, IOPS_OP::IOPS_REMOVE}; constexpr static const std::initializer_list<Stats::SIZE_OP> all_SIZE_OP = { SIZE_OP::METADATA_SIZE, SIZE_OP::DATA_SIZE, SIZE_OP::WRITE_SIZE, SIZE_OP::READ_SIZE}; SIZE_OP::WRITE_SIZE, SIZE_OP::READ_SIZE}; const std::vector<std::string> IOPS_OP_S = {"IOPS_CREATE", "IOPS_WRITE", "IOPS_READ", "IOPS_MKDIR", "IOPS_RMDIR", "IOPS_REMOVE"}; const std::vector<std::string> SIZE_OP_S = {"METADATA_SIZE", "WRITE_SIZE", "READ_SIZE", "DATA_SIZE"}; "IOPS_READ", "IOPS_STATS", "IOPS_DIRENTS", "IOPS_REMOVE"}; const std::vector<std::string> SIZE_OP_S = {"WRITE_SIZE", "READ_SIZE"}; std::chrono::time_point<std::chrono::steady_clock> last_cached; /* Measures when we started the server */ std::chrono::time_point<std::chrono::steady_clock> start; Loading @@ -108,8 +109,6 @@ private: std::map<IOPS_OP, std::deque<std::chrono::time_point<std::chrono::steady_clock>>> TIME_IOPS; // We will store 1, 5, and 10 minute mean; std::map<IOPS_OP, std::vector<double>> CACHED_IOPS; // For size operations we need to store the timestamp and // the size Loading @@ -118,8 +117,6 @@ private: std::chrono::time_point<std::chrono::steady_clock>, unsigned long long>>> TIME_SIZE; // We will store 1, 5, and 10 minute mean; std::map<enum SIZE_OP, std::vector<double>> CACHED_SIZE; // Thread that outputs stats info std::thread t_output; Loading @@ -132,16 +129,39 @@ private: * Debug Function * * @param d is the time between output * @param file_output is the output file */ void output(std::chrono::seconds d); output(std::chrono::seconds d, std::string file_output); std::map<std::pair<std::string, unsigned long long>, unsigned int> CHUNK_READ; std::map<std::pair<std::string, unsigned long long>, unsigned int> CHUNK_WRITE; /** * @brief Called by output to generate CHUNK map * * @param output is the output stream */ void output_map(std::ofstream& output); /** * @brief Dumps all the means from the stats * @param of Output stream */ void dump(std::ofstream& of); public: /** * @brief Starts the Stats module and initializes structures * * @param output_thread creates an aditional thread that outputs the stats * @param filename file where to write the output */ Stats(bool output_thread); Stats(bool output_thread, std::string filename); /** * @brief Destroys the class, and any associated thread Loading @@ -149,6 +169,24 @@ public: */ ~Stats(); /** * @brief Adds a new read access to the chunk/path specified * * @param path * @param chunk */ void add_read(std::string path, unsigned long long chunk); /** * @brief Adds a new write access to the chunk/path specified * * @param path * @param chunk */ void add_write(std::string path, unsigned long long chunk); /** * Add a new value for a IOPS, that does not involve any size * No value needed as they are simple (1 create, 1 read...) Loading Loading @@ -200,14 +238,6 @@ public: * @return std::vector< double > with 4 means */ std::vector<double> get_four_means(enum IOPS_OP); /** * @brief Dumps all the means from the stats * */ void dump(); }; } // namespace gkfs::utils Loading include/daemon/classes/fs_data.hpp +7 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ private: // Statistics std::shared_ptr<gkfs::utils::Stats> stats_; bool output_stats_ = false; std::string stats_file_; public: static FsData* Loading Loading @@ -233,6 +234,12 @@ public: void output_stats(bool output_stats); std::string stats_file() const; void stats_file(std::string stats_file); }; Loading src/common/statistics/stats.cpp +83 −29 Original line number Diff line number Diff line Loading @@ -33,19 +33,10 @@ using namespace std; namespace gkfs::utils { Stats::Stats(bool output_thread) { Stats::Stats(bool output_thread, std::string stats_file) { // Init clocks start = std::chrono::steady_clock::now(); last_cached = std::chrono::steady_clock::now(); // Init cached (4 mean values) for(auto e : all_IOPS_OP) for(int i = 0; i < 4; i++) CACHED_IOPS[e].push_back(0.0); for(auto e : all_SIZE_OP) for(int i = 0; i < 4; i++) CACHED_SIZE[e].push_back(0.0); // To simplify the control we add an element into the different maps // Statistaclly will be negligible... and we get a faster flow Loading @@ -63,7 +54,9 @@ Stats::Stats(bool output_thread) { output_thread_ = output_thread; if(output_thread_) { t_output = std::thread([this] { output(std::chrono::duration(10s)); }); t_output = std::thread([this, stats_file] { output(std::chrono::duration(10s), stats_file); }); } } Loading @@ -75,6 +68,52 @@ Stats::~Stats() { } } void Stats::add_read(std::string path, unsigned long long chunk) { CHUNK_READ[pair(path, chunk)]++; } void Stats::add_write(std::string path, unsigned long long chunk) { CHUNK_WRITE[pair(path, chunk)]++; } void Stats::output_map(std::ofstream& output) { // Ordering map<unsigned int, std::set<pair<std::string, unsigned long long>>> ORDER_WRITE; map<unsigned int, std::set<pair<std::string, unsigned long long>>> ORDER_READ; for(auto i : CHUNK_READ) { ORDER_READ[i.second].insert(i.first); } for(auto i : CHUNK_WRITE) { ORDER_WRITE[i.second].insert(i.first); } auto CHUNK_MAP = [](std::string caption, map<unsigned int, std::set<pair<std::string, unsigned long long>>>& ORDER, std::ofstream& output) { output << caption << std::endl; for(auto k : ORDER) { output << k.first << " -- "; for(auto v : k.second) { output << v.first << " // " << v.second << endl; } } }; CHUNK_MAP("READ CHUNK MAP", ORDER_READ, output); CHUNK_MAP("WRITE CHUNK MAP", ORDER_WRITE, output); } void Stats::add_value_iops(enum IOPS_OP iop) { IOPS[iop]++; Loading Loading @@ -155,11 +194,11 @@ Stats::get_four_means(enum SIZE_OP sop) { continue; results[1] += e.second; } results[0] = get_mean(sop); results[3] /= 10 * 60; results[2] /= 5 * 60; results[1] /= 60; // Mean in MB/s results[0] = get_mean(sop) / (1024.0 * 1024.0); results[3] /= 10 * 60 * (1024.0 * 1024.0); results[2] /= 5 * 60 * (1024.0 * 1024.0); results[1] /= 60 * (1024.0 * 1024.0); return results; } Loading Loading @@ -194,33 +233,48 @@ Stats::get_four_means(enum IOPS_OP iop) { } void Stats::dump() { Stats::dump(std::ofstream& of) { for(auto e : all_IOPS_OP) { auto tmp = get_four_means(e); std::cout << "Stats " << IOPS_OP_S[static_cast<int>(e)] << " "; of << "Stats " << IOPS_OP_S[static_cast<int>(e)] << " IOPS/s (avg, 1 min, 5 min, 10 min) \t\t"; for(auto mean : tmp) { std::cout << mean << " - "; of << std::setprecision(4) << std::setw(9) << mean << " - "; } std::cout << std::endl; of << std::endl; } for(auto e : all_SIZE_OP) { auto tmp = get_four_means(e); std::cout << "Stats " << SIZE_OP_S[static_cast<int>(e)] << " "; of << "Stats " << SIZE_OP_S[static_cast<int>(e)] << " MB/s (avg, 1 min, 5 min, 10 min) \t\t"; for(auto mean : tmp) { std::cout << mean << " - "; of << std::setprecision(4) << std::setw(9) << mean << " - "; } std::cout << std::endl; of << std::endl; } of << std::endl; } void Stats::output(std::chrono::seconds d) { Stats::output(std::chrono::seconds d, std::string file_output) { int times = 0; std::ofstream of(file_output, std::ios_base::openmode::_S_trunc); while(running) { dump(); std::this_thread::sleep_for(d); dump(of); std::chrono::seconds a = 0s; times++; #ifdef GKFS_CHUNK_STATS if(times % 4 == 0) output_map(of); #endif while(running and a < d) { a += 1s; std::this_thread::sleep_for(1s); } } } Loading src/daemon/classes/fs_data.cpp +10 −1 Original line number Diff line number Diff line Loading @@ -227,7 +227,7 @@ FsData::stats() const { void FsData::stats(const std::shared_ptr<gkfs::utils::Stats>& stats) { stats_ = stats; FsData::stats_ = stats; } void Loading @@ -246,5 +246,14 @@ FsData::output_stats(bool output_stats) { FsData::output_stats_ = output_stats; } std::string FsData::stats_file() const { return stats_file_; } void FsData::stats_file(std::string stats_file) { FsData::stats_file_ = stats_file; } } // namespace gkfs::daemon Loading
CMakeLists.txt +6 −0 Original line number Diff line number Diff line Loading @@ -195,6 +195,12 @@ if(GKFS_USE_GUIDED_DISTRIBUTION) message(STATUS "[gekkofs] Guided data distributor input file path: ${GKFS_USE_GUIDED_DISTRIBUTION_PATH}") endif() option(GKFS_CHUNK_STATS "Gather Chunk Stats " OFF) if (GKFS_CHUNK_STATS) add_definitions(-DGKFS_CHUNK_STATS) endif () message(STATUS "[gekkofs] Gather Chunk Stats: ${GKFS_CHUNK_STATS}") configure_file(include/common/cmake_configure.hpp.in include/common/cmake_configure.hpp) Loading
include/common/statistics/stats.hpp +58 −28 Original line number Diff line number Diff line Loading @@ -33,12 +33,15 @@ #include <unistd.h> #include <cassert> #include <map> #include <set> #include <vector> #include <deque> #include <chrono> #include <initializer_list> #include <thread> #include <iostream> #include <iomanip> #include <fstream> /** * Provides storage capabilities to provide stats about GekkoFS * The information is per server. Loading Loading @@ -70,27 +73,25 @@ public: IOPS_CREATE, IOPS_WRITE, IOPS_READ, IOPS_MKDIR, IOPS_RMDIR, IOPS_STATS, IOPS_DIRENTS, IOPS_REMOVE, }; enum class SIZE_OP { METADATA_SIZE, WRITE_SIZE, READ_SIZE, DATA_SIZE }; enum class SIZE_OP { WRITE_SIZE, READ_SIZE }; private: constexpr static const std::initializer_list<Stats::IOPS_OP> all_IOPS_OP = { IOPS_OP::IOPS_CREATE, IOPS_OP::IOPS_WRITE, IOPS_OP::IOPS_READ, IOPS_OP::IOPS_MKDIR, IOPS_OP::IOPS_RMDIR, IOPS_OP::IOPS_REMOVE}; IOPS_OP::IOPS_STATS, IOPS_OP::IOPS_DIRENTS, IOPS_OP::IOPS_REMOVE}; constexpr static const std::initializer_list<Stats::SIZE_OP> all_SIZE_OP = { SIZE_OP::METADATA_SIZE, SIZE_OP::DATA_SIZE, SIZE_OP::WRITE_SIZE, SIZE_OP::READ_SIZE}; SIZE_OP::WRITE_SIZE, SIZE_OP::READ_SIZE}; const std::vector<std::string> IOPS_OP_S = {"IOPS_CREATE", "IOPS_WRITE", "IOPS_READ", "IOPS_MKDIR", "IOPS_RMDIR", "IOPS_REMOVE"}; const std::vector<std::string> SIZE_OP_S = {"METADATA_SIZE", "WRITE_SIZE", "READ_SIZE", "DATA_SIZE"}; "IOPS_READ", "IOPS_STATS", "IOPS_DIRENTS", "IOPS_REMOVE"}; const std::vector<std::string> SIZE_OP_S = {"WRITE_SIZE", "READ_SIZE"}; std::chrono::time_point<std::chrono::steady_clock> last_cached; /* Measures when we started the server */ std::chrono::time_point<std::chrono::steady_clock> start; Loading @@ -108,8 +109,6 @@ private: std::map<IOPS_OP, std::deque<std::chrono::time_point<std::chrono::steady_clock>>> TIME_IOPS; // We will store 1, 5, and 10 minute mean; std::map<IOPS_OP, std::vector<double>> CACHED_IOPS; // For size operations we need to store the timestamp and // the size Loading @@ -118,8 +117,6 @@ private: std::chrono::time_point<std::chrono::steady_clock>, unsigned long long>>> TIME_SIZE; // We will store 1, 5, and 10 minute mean; std::map<enum SIZE_OP, std::vector<double>> CACHED_SIZE; // Thread that outputs stats info std::thread t_output; Loading @@ -132,16 +129,39 @@ private: * Debug Function * * @param d is the time between output * @param file_output is the output file */ void output(std::chrono::seconds d); output(std::chrono::seconds d, std::string file_output); std::map<std::pair<std::string, unsigned long long>, unsigned int> CHUNK_READ; std::map<std::pair<std::string, unsigned long long>, unsigned int> CHUNK_WRITE; /** * @brief Called by output to generate CHUNK map * * @param output is the output stream */ void output_map(std::ofstream& output); /** * @brief Dumps all the means from the stats * @param of Output stream */ void dump(std::ofstream& of); public: /** * @brief Starts the Stats module and initializes structures * * @param output_thread creates an aditional thread that outputs the stats * @param filename file where to write the output */ Stats(bool output_thread); Stats(bool output_thread, std::string filename); /** * @brief Destroys the class, and any associated thread Loading @@ -149,6 +169,24 @@ public: */ ~Stats(); /** * @brief Adds a new read access to the chunk/path specified * * @param path * @param chunk */ void add_read(std::string path, unsigned long long chunk); /** * @brief Adds a new write access to the chunk/path specified * * @param path * @param chunk */ void add_write(std::string path, unsigned long long chunk); /** * Add a new value for a IOPS, that does not involve any size * No value needed as they are simple (1 create, 1 read...) Loading Loading @@ -200,14 +238,6 @@ public: * @return std::vector< double > with 4 means */ std::vector<double> get_four_means(enum IOPS_OP); /** * @brief Dumps all the means from the stats * */ void dump(); }; } // namespace gkfs::utils Loading
include/daemon/classes/fs_data.hpp +7 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ private: // Statistics std::shared_ptr<gkfs::utils::Stats> stats_; bool output_stats_ = false; std::string stats_file_; public: static FsData* Loading Loading @@ -233,6 +234,12 @@ public: void output_stats(bool output_stats); std::string stats_file() const; void stats_file(std::string stats_file); }; Loading
src/common/statistics/stats.cpp +83 −29 Original line number Diff line number Diff line Loading @@ -33,19 +33,10 @@ using namespace std; namespace gkfs::utils { Stats::Stats(bool output_thread) { Stats::Stats(bool output_thread, std::string stats_file) { // Init clocks start = std::chrono::steady_clock::now(); last_cached = std::chrono::steady_clock::now(); // Init cached (4 mean values) for(auto e : all_IOPS_OP) for(int i = 0; i < 4; i++) CACHED_IOPS[e].push_back(0.0); for(auto e : all_SIZE_OP) for(int i = 0; i < 4; i++) CACHED_SIZE[e].push_back(0.0); // To simplify the control we add an element into the different maps // Statistaclly will be negligible... and we get a faster flow Loading @@ -63,7 +54,9 @@ Stats::Stats(bool output_thread) { output_thread_ = output_thread; if(output_thread_) { t_output = std::thread([this] { output(std::chrono::duration(10s)); }); t_output = std::thread([this, stats_file] { output(std::chrono::duration(10s), stats_file); }); } } Loading @@ -75,6 +68,52 @@ Stats::~Stats() { } } void Stats::add_read(std::string path, unsigned long long chunk) { CHUNK_READ[pair(path, chunk)]++; } void Stats::add_write(std::string path, unsigned long long chunk) { CHUNK_WRITE[pair(path, chunk)]++; } void Stats::output_map(std::ofstream& output) { // Ordering map<unsigned int, std::set<pair<std::string, unsigned long long>>> ORDER_WRITE; map<unsigned int, std::set<pair<std::string, unsigned long long>>> ORDER_READ; for(auto i : CHUNK_READ) { ORDER_READ[i.second].insert(i.first); } for(auto i : CHUNK_WRITE) { ORDER_WRITE[i.second].insert(i.first); } auto CHUNK_MAP = [](std::string caption, map<unsigned int, std::set<pair<std::string, unsigned long long>>>& ORDER, std::ofstream& output) { output << caption << std::endl; for(auto k : ORDER) { output << k.first << " -- "; for(auto v : k.second) { output << v.first << " // " << v.second << endl; } } }; CHUNK_MAP("READ CHUNK MAP", ORDER_READ, output); CHUNK_MAP("WRITE CHUNK MAP", ORDER_WRITE, output); } void Stats::add_value_iops(enum IOPS_OP iop) { IOPS[iop]++; Loading Loading @@ -155,11 +194,11 @@ Stats::get_four_means(enum SIZE_OP sop) { continue; results[1] += e.second; } results[0] = get_mean(sop); results[3] /= 10 * 60; results[2] /= 5 * 60; results[1] /= 60; // Mean in MB/s results[0] = get_mean(sop) / (1024.0 * 1024.0); results[3] /= 10 * 60 * (1024.0 * 1024.0); results[2] /= 5 * 60 * (1024.0 * 1024.0); results[1] /= 60 * (1024.0 * 1024.0); return results; } Loading Loading @@ -194,33 +233,48 @@ Stats::get_four_means(enum IOPS_OP iop) { } void Stats::dump() { Stats::dump(std::ofstream& of) { for(auto e : all_IOPS_OP) { auto tmp = get_four_means(e); std::cout << "Stats " << IOPS_OP_S[static_cast<int>(e)] << " "; of << "Stats " << IOPS_OP_S[static_cast<int>(e)] << " IOPS/s (avg, 1 min, 5 min, 10 min) \t\t"; for(auto mean : tmp) { std::cout << mean << " - "; of << std::setprecision(4) << std::setw(9) << mean << " - "; } std::cout << std::endl; of << std::endl; } for(auto e : all_SIZE_OP) { auto tmp = get_four_means(e); std::cout << "Stats " << SIZE_OP_S[static_cast<int>(e)] << " "; of << "Stats " << SIZE_OP_S[static_cast<int>(e)] << " MB/s (avg, 1 min, 5 min, 10 min) \t\t"; for(auto mean : tmp) { std::cout << mean << " - "; of << std::setprecision(4) << std::setw(9) << mean << " - "; } std::cout << std::endl; of << std::endl; } of << std::endl; } void Stats::output(std::chrono::seconds d) { Stats::output(std::chrono::seconds d, std::string file_output) { int times = 0; std::ofstream of(file_output, std::ios_base::openmode::_S_trunc); while(running) { dump(); std::this_thread::sleep_for(d); dump(of); std::chrono::seconds a = 0s; times++; #ifdef GKFS_CHUNK_STATS if(times % 4 == 0) output_map(of); #endif while(running and a < d) { a += 1s; std::this_thread::sleep_for(1s); } } } Loading
src/daemon/classes/fs_data.cpp +10 −1 Original line number Diff line number Diff line Loading @@ -227,7 +227,7 @@ FsData::stats() const { void FsData::stats(const std::shared_ptr<gkfs::utils::Stats>& stats) { stats_ = stats; FsData::stats_ = stats; } void Loading @@ -246,5 +246,14 @@ FsData::output_stats(bool output_stats) { FsData::output_stats_ = output_stats; } std::string FsData::stats_file() const { return stats_file_; } void FsData::stats_file(std::string stats_file) { FsData::stats_file_ = stats_file; } } // namespace gkfs::daemon