Commit c1d961c0 authored by Ramon Nou's avatar Ramon Nou
Browse files

Added DIRENTS and STATS stats, remover mkdir, rmdir, metadata and data

Added Ifdef feature, chunk distribution statistics

Added output to file
parent 86599ac4
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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)


+58 −28
Original line number Diff line number Diff line
@@ -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.
@@ -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;
@@ -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
@@ -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;
@@ -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
@@ -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...)
@@ -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
+7 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ private:
    // Statistics
    std::shared_ptr<gkfs::utils::Stats> stats_;
    bool output_stats_ = false;
    std::string stats_file_;

public:
    static FsData*
@@ -233,6 +234,12 @@ public:

    void
    output_stats(bool output_stats);

    std::string
    stats_file() const;

    void
    stats_file(std::string stats_file);
};


+83 −29
Original line number Diff line number Diff line
@@ -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
@@ -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);
        });
    }
}

@@ -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]++;
@@ -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;
}
@@ -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);
        }
    }
}

+10 −1
Original line number Diff line number Diff line
@@ -227,7 +227,7 @@ FsData::stats() const {

void
FsData::stats(const std::shared_ptr<gkfs::utils::Stats>& stats) {
    stats_ = stats;
    FsData::stats_ = stats;
}

void
@@ -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