Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <fstream>
- #include <vector>
- #include <map>
- #include <string>
- #include <string_view>
- #include <boost/algorithm/string/classification.hpp> // Include boost::for is_any_of
- #include <boost/algorithm/string/split.hpp> // Include for boost::split
- #include <boost/algorithm/string/trim.hpp>
- #include <unistd.h>
- #define LOADTHREADHOLD 2.0
- #define IOPROCTHREASHOLD 40.0
- #define IOPROCTHRESET 5.00
- #define CPUPROCTHREASHOLD 20.0
- #define CPUPROCRESET 5.0
- #define RENICETO 10
- #define SLEEP 2
- //#define DEBUG true
- std::vector<std::string> read_array(std::string delimiter, std::string input);
- auto read_file(std::string_view path) -> std::string;
- std::string exec(std::string cmd);
- int main(int argc, char** argv)
- {
- auto ionicedprocesses = std::map<int, int>{};
- auto renicedprocesses = std::vector<int>{};
- while(true)
- {
- auto loadavg = std::vector<std::string>{read_array(" ", read_file("/proc/loadavg"))}; // "cat /proc/loadavg"
- if (std::stod(loadavg[2]) >= LOADTHREADHOLD)
- {
- std::cout << "Load of " << std::stod(loadavg[2]) << " exceeds load threshold of " << LOADTHREADHOLD << std::endl;
- auto iotoplines = std::vector<std::string>{read_array("\n", exec("./iotop -P -b -q -o -n 2 -d 0.1"))};
- for(auto &iotopline: iotoplines)
- {
- #ifdef DEBUG
- std::cout << "iotop line '"<< iotopline << "'" << std::endl;
- #endif
- auto columns = std::vector<std::string>{};
- boost::trim_if(iotopline, boost::is_any_of(" "));
- boost::split(columns, iotopline, boost::is_any_of(" "), boost::token_compress_on);
- std::remove(columns[0].begin(), columns[0].end(), ' ');
- if (columns[0][0] - '0' >= 0 && columns[0][0] - '0' <= 9)
- {
- if (std::stod(columns[9]) >= IOPROCTHREASHOLD && columns[1][0] == 'b')
- {
- exec("ionice -c 3 -t -p " + columns[0]);
- ionicedprocesses[std::stoi(columns[0])] = columns[1][3] - '0';
- std::cout << "process " << columns[0] << "\"" << columns[9] << "\" reniced to idle as it was hogging io" << std::endl;
- } else {
- if (std::stod(columns[9]) <= IOPROCTHRESET && ionicedprocesses.contains(std::stoi(columns[0])))
- {
- exec("ionice -c 2 -n " + std::to_string(ionicedprocesses[std::stoi(columns[0])]) + " -t -p " +columns[0]);
- std::cout << "process " << columns[0] << "\"" << columns[0] << "\" reniced to be/4 as it stopped hogging io" << std::endl;
- ionicedprocesses.erase(std::stoi(columns[0]));
- }
- }
- }
- }
- auto toplines = std::vector<std::string>{read_array("\n", exec("top -b -d 0.1 -n 1"))};
- for(auto &topline: toplines)
- {
- #ifdef DEBUG
- std::cout << "topline: '" << topline << "'" << std::endl;
- #endif
- auto columns = std::vector<std::string>{};
- boost::trim_if(topline, boost::is_any_of(" "));
- boost::split(columns, topline, boost::is_any_of(" "), boost::token_compress_on);
- std::remove(columns[0].begin(), columns[0].end(), ' ');
- if (columns[0][0] - '0' >= 0 && columns[0][0] - '0' <= 9)
- {
- if (std::stod(columns[8]) >= CPUPROCTHREASHOLD && columns[3] == "0")
- {
- exec("renice -n " + std::to_string(RENICETO) + " -p " + columns[0]);
- std::cout << "process " << columns[0] << " reniced to " << RENICETO << " as it was hogging cpu" << std::endl;
- renicedprocesses.push_back(std::stoi(columns[0]));
- } else {
- if (std::stod(columns[8]) <= CPUPROCRESET && renicedprocesses.end() != std::find(renicedprocesses.begin(), renicedprocesses.end(), std::stoi(columns[0]))) // need an ittirator for contans
- {
- exec("renice -n 0 -p " + columns[0]);
- std::cout << "process " << columns[0] << " reniced to 0 as it stopped hogging cpu" << std::endl;
- //use std::remove algorythm to erase should work, but for some reason it isn't
- auto new_renicedprocesses = std::vector<int>{0};
- std::remove_copy(renicedprocesses.begin(), renicedprocesses.end(), new_renicedprocesses.begin(), std::stoi(columns[0]));
- renicedprocesses = new_renicedprocesses;
- #ifdef DEBUG
- for(auto &rnprocess: renicedprocesses)
- std::cout << std::to_string(rnprocess) << std::endl;
- #endif
- }
- }
- }
- }
- }
- sleep(SLEEP);
- }
- return 0;
- }
- auto read_file(std::string_view path) -> std::string {
- constexpr auto read_size = std::size_t{4096};
- auto stream = std::ifstream{path.data()};
- stream.exceptions(std::ios_base::badbit);
- auto out = std::string{};
- auto buf = std::string(read_size, '\0');
- while (stream.read(& buf[0], read_size)) {
- out.append(buf, 0, stream.gcount());
- }
- out.append(buf, 0, stream.gcount());
- return out;
- }
- std::string exec(std::string cmd)
- {
- std::array<char, 128> buffer;
- std::string result;
- auto pipe = popen(cmd.data(), "r"); // get rid of shared_ptr
- if (!pipe) throw std::runtime_error("popen() failed!");
- while (!feof(pipe)) {
- if (fgets(buffer.data(), 128, pipe) != nullptr)
- result += buffer.data();
- }
- auto rc = pclose(pipe);
- if (rc == EXIT_SUCCESS) { // == 0
- } else if (rc == EXIT_FAILURE) { // EXIT_FAILURE is not used by all programs, maybe needs some adaptation.
- }
- return result;
- }
- std::vector<std::string> read_array(std::string delimiter, std::string input)
- {
- std::vector<std::string> output;
- boost::split(output, input, boost::is_any_of(delimiter), boost::token_compress_on);
- return output;
- }
Advertisement
Add Comment
Please, Sign In to add comment