From bfe7bfefb11b63b9dabe9c8f5872a85bdec3bf3a Mon Sep 17 00:00:00 2001 From: Quentin Sabah Date: Wed, 24 May 2023 09:09:27 +0200 Subject: [PATCH] fixes souffleprof and enable build on Windows - report relation with load time in the CPU usage chart - report true source file path - populate the "code" tab (although only one file is reported at the moment) - and more fixes --- src/CMakeLists.txt | 22 +++-- src/LogStatement.h | 31 +++--- src/ast/QualifiedName.h | 1 + src/ast/Term.h | 5 +- src/include/souffle/profile/Cell.h | 16 +-- src/include/souffle/profile/CellInterface.h | 2 +- src/include/souffle/profile/Cli.h | 17 +++- src/include/souffle/profile/OutputProcessor.h | 37 +++---- src/include/souffle/profile/ProgramRun.h | 4 +- src/include/souffle/profile/Reader.h | 3 +- src/include/souffle/profile/Relation.h | 18 +++- src/include/souffle/profile/Tui.h | 99 +++++++++++-------- src/include/souffle/profile/UserInputReader.h | 12 +++ src/include/souffle/profile/htmlJsMain.h | 13 ++- src/souffle_prof.cpp | 4 +- 15 files changed, 175 insertions(+), 109 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 68f045fbb2b..946a1f898fc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -367,16 +367,15 @@ endif () # Souffle's profiler binary # -------------------------------------------------- -if (NOT WIN32) - add_executable(souffleprof - souffle_prof.cpp) - target_include_directories(souffleprof PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) - install(TARGETS souffleprof DESTINATION bin) - - # Set C++ standard to C++17 - target_compile_features(souffleprof - PUBLIC cxx_std_17) -endif() + +add_executable(souffleprof + souffle_prof.cpp) +target_include_directories(souffleprof PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) +install(TARGETS souffleprof DESTINATION bin) + +# Set C++ standard to C++17 +target_compile_features(souffleprof + PUBLIC cxx_std_17) if (MSVC) target_compile_options(libsouffle PUBLIC /bigobj) @@ -403,12 +402,15 @@ if (MSVC) target_compile_options(libsouffle PUBLIC /Zc:preprocessor) target_compile_options(compiled PUBLIC /Zc:preprocessor) + target_compile_options(souffleprof PUBLIC /Zc:preprocessor) target_compile_options(libsouffle PUBLIC /EHsc) target_compile_options(compiled PUBLIC /EHsc) + target_compile_options(souffleprof PUBLIC /EHsc) target_compile_definitions(libsouffle PUBLIC USE_CUSTOM_GETOPTLONG) target_compile_definitions(compiled PUBLIC USE_CUSTOM_GETOPTLONG) + target_compile_definitions(souffleprof PUBLIC USE_CUSTOM_GETOPTLONG) endif (MSVC) diff --git a/src/LogStatement.h b/src/LogStatement.h index 498d9d8dd8d..1a84c0884de 100644 --- a/src/LogStatement.h +++ b/src/LogStatement.h @@ -21,19 +21,26 @@ namespace souffle { class LogStatement { +private: + static std::string str(const SrcLocation& loc) { + return loc.getReportedPath() + " [" + std::to_string(loc.start.line) + ":" + + std::to_string(loc.start.column) + "-" + std::to_string(loc.end.line) + ":" + + std::to_string(loc.end.column) + "]"; + } + public: static const std::string tNonrecursiveRelation( const std::string& relationName, const SrcLocation& srcLocation) { const char* messageType = "@t-nonrecursive-relation"; std::stringstream line; - line << messageType << ";" << relationName << ";" << srcLocation << ";"; + line << messageType << ";" << relationName << ";" << str(srcLocation) << ";"; return line.str(); } static const std::string tRelationLoadTime( const std::string& relationName, const SrcLocation& srcLocation) { const char* messageType = "@t-relation-loadtime"; std::stringstream line; - line << messageType << ";" << relationName << ";" << srcLocation << ";loadtime;"; + line << messageType << ";" << relationName << ";" << str(srcLocation) << ";loadtime;"; return line.str(); } @@ -41,7 +48,7 @@ class LogStatement { const std::string& relationName, const SrcLocation& srcLocation) { const char* messageType = "@t-relation-savetime"; std::stringstream line; - line << messageType << ";" << relationName << ";" << srcLocation << ";savetime;"; + line << messageType << ";" << relationName << ";" << str(srcLocation) << ";savetime;"; return line.str(); } @@ -49,7 +56,7 @@ class LogStatement { const std::string& relationName, const SrcLocation& srcLocation) { const char* messageType = "@n-nonrecursive-relation"; std::stringstream line; - line << messageType << ";" << relationName << ";" << srcLocation << ";"; + line << messageType << ";" << relationName << ";" << str(srcLocation) << ";"; return line.str(); } @@ -57,7 +64,7 @@ class LogStatement { const std::string& relationName, const SrcLocation& srcLocation, const std::string& datalogText) { const char* messageType = "@t-nonrecursive-rule"; std::stringstream line; - line << messageType << ";" << relationName << ";" << srcLocation << ";" << datalogText << ";"; + line << messageType << ";" << relationName << ";" << str(srcLocation) << ";" << datalogText << ";"; return line.str(); } @@ -65,7 +72,7 @@ class LogStatement { const std::string& relationName, const SrcLocation& srcLocation, const std::string& datalogText) { const char* messageType = "@n-nonrecursive-rule"; std::stringstream line; - line << messageType << ";" << relationName << ";" << srcLocation << ";" << datalogText << ";"; + line << messageType << ";" << relationName << ";" << str(srcLocation) << ";" << datalogText << ";"; return line.str(); } @@ -73,7 +80,7 @@ class LogStatement { const SrcLocation& srcLocation, const std::string& datalogText) { const char* messageType = "@t-recursive-rule"; std::stringstream line; - line << messageType << ";" << relationName << ";" << version << ";" << srcLocation << ";" + line << messageType << ";" << relationName << ";" << version << ";" << str(srcLocation) << ";" << datalogText << ";"; return line.str(); } @@ -82,7 +89,7 @@ class LogStatement { const SrcLocation& srcLocation, const std::string& datalogText) { const char* messageType = "@n-recursive-rule"; std::stringstream line; - line << messageType << ";" << relationName << ";" << version << ";" << srcLocation << ";" + line << messageType << ";" << relationName << ";" << version << ";" << str(srcLocation) << ";" << datalogText << ";"; return line.str(); } @@ -91,7 +98,7 @@ class LogStatement { const std::string& relationName, const SrcLocation& srcLocation) { const char* messageType = "@t-recursive-relation"; std::stringstream line; - line << messageType << ";" << relationName << ";" << srcLocation << ";"; + line << messageType << ";" << relationName << ";" << str(srcLocation) << ";"; return line.str(); } @@ -99,7 +106,7 @@ class LogStatement { const std::string& relationName, const SrcLocation& srcLocation) { const char* messageType = "@n-recursive-relation"; std::stringstream line; - line << messageType << ";" << relationName << ";" << srcLocation << ";"; + line << messageType << ";" << relationName << ";" << str(srcLocation) << ";"; return line.str(); } @@ -107,7 +114,7 @@ class LogStatement { const std::string& relationName, const SrcLocation& srcLocation) { const char* messageType = "@c-recursive-relation"; std::stringstream line; - line << messageType << ";" << relationName << ";" << srcLocation << ";"; + line << messageType << ";" << relationName << ";" << str(srcLocation) << ";"; return line.str(); } @@ -117,7 +124,7 @@ class LogStatement { // messages are ignored const char* messageType = "#p-proof-counter"; std::stringstream line; - line << messageType << ";" << relationName << ";" << srcLocation << ";" << datalogText << ";"; + line << messageType << ";" << relationName << ";" << str(srcLocation) << ";" << datalogText << ";"; // TODO (#590): the additional semicolon is added to maintain backwards compatibility and should // eventually be removed line << ";"; diff --git a/src/ast/QualifiedName.h b/src/ast/QualifiedName.h index 85f5e816e70..fb85cfcc3e1 100644 --- a/src/ast/QualifiedName.h +++ b/src/ast/QualifiedName.h @@ -16,6 +16,7 @@ #pragma once +#include #include #include #include diff --git a/src/ast/Term.h b/src/ast/Term.h index d2896058b76..d3ba591ea63 100644 --- a/src/ast/Term.h +++ b/src/ast/Term.h @@ -56,11 +56,8 @@ class Term : public Argument { template static VecOwn asVec(Operands... ops) { - Own ary[] = {std::move(ops)...}; VecOwn xs; - for (auto&& x : ary) { - xs.push_back(std::move(x)); - } + (xs.emplace_back(std::move(std::forward(ops))), ...); return xs; } diff --git a/src/include/souffle/profile/Cell.h b/src/include/souffle/profile/Cell.h index a759495be29..0ebd83ea059 100644 --- a/src/include/souffle/profile/Cell.h +++ b/src/include/souffle/profile/Cell.h @@ -37,7 +37,7 @@ class Cell : public CellInterface { double getDoubleVal() const override { return value.count() / 1000000.0; } - long getLongVal() const override { + int64_t getLongVal() const override { std::cerr << "getting long on time cell\n"; throw this; } @@ -62,7 +62,7 @@ class Cell : public CellInterface { double getDoubleVal() const override { return value; } - long getLongVal() const override { + int64_t getLongVal() const override { std::cerr << "getting long on double cell\n"; throw this; } @@ -89,7 +89,7 @@ class Cell : public CellInterface { std::cerr << "getting double on string cell\n"; throw this; } - long getLongVal() const override { + int64_t getLongVal() const override { std::cerr << "getting long on string cell\n"; throw this; } @@ -106,11 +106,11 @@ class Cell : public CellInterface { }; template <> -class Cell : public CellInterface { - const long value; +class Cell : public CellInterface { + const int64_t value; public: - Cell(long value) : value(value){}; + Cell(int64_t value) : value(value){}; double getDoubleVal() const override { std::cerr << "getting double on long cell\n"; throw this; @@ -119,7 +119,7 @@ class Cell : public CellInterface { std::cerr << "getting string on long cell\n"; throw this; } - long getLongVal() const override { + int64_t getLongVal() const override { return value; } std::chrono::microseconds getTimeVal() const override { @@ -139,7 +139,7 @@ class Cell : public CellInterface, std::false_type { std::cerr << "getting double on void cell"; throw this; } - long getLongVal() const override { + int64_t getLongVal() const override { std::cerr << "getting long on void cell"; throw this; } diff --git a/src/include/souffle/profile/CellInterface.h b/src/include/souffle/profile/CellInterface.h index 38cc8eb5b83..8194b770015 100644 --- a/src/include/souffle/profile/CellInterface.h +++ b/src/include/souffle/profile/CellInterface.h @@ -20,7 +20,7 @@ class CellInterface { virtual double getDoubleVal() const = 0; - virtual long getLongVal() const = 0; + virtual int64_t getLongVal() const = 0; virtual std::string getStringVal() const = 0; diff --git a/src/include/souffle/profile/Cli.h b/src/include/souffle/profile/Cli.h index 45a5c1eb136..055832430a2 100644 --- a/src/include/souffle/profile/Cli.h +++ b/src/include/souffle/profile/Cli.h @@ -15,7 +15,12 @@ #include #include #include + +#ifdef USE_CUSTOM_GETOPTLONG +#include "souffle/utility/GetOptLongImpl.h" +#else #include +#endif namespace souffle { namespace profile { @@ -52,10 +57,10 @@ class Cli { } } - void parse() { + int parse() { if (args.size() == 0) { std::cout << "No arguments provided.\nTry souffleprof -h for help.\n"; - exit(EXIT_FAILURE); + return (EXIT_FAILURE); } if (args.count('h') != 0 || args.count('f') == 0) { @@ -70,7 +75,7 @@ class Cli { << std::endl << " Default filename is profiler_html/[num].html" << std::endl << "-h Print this help message." << std::endl; - exit(0); + return (0); } std::string filename = args['f']; @@ -81,13 +86,15 @@ class Cli { } } else if (args.count('j') != 0) { if (args['j'] == "j") { - Tui(filename, false, true).outputHtml(); + return Tui(filename, false, true).outputHtml(); } else { - Tui(filename, false, true).outputHtml(args['j']); + return Tui(filename, false, true).outputHtml(args['j']); } } else { Tui(filename, true, false).runProf(); } + + return 0; } }; diff --git a/src/include/souffle/profile/OutputProcessor.h b/src/include/souffle/profile/OutputProcessor.h index 745a3d7dcb3..09a1c6d4448 100644 --- a/src/include/souffle/profile/OutputProcessor.h +++ b/src/include/souffle/profile/OutputProcessor.h @@ -86,19 +86,20 @@ Table inline OutputProcessor::getRelTable() const { row[1] = std::make_shared>(r->getNonRecTime()); row[2] = std::make_shared>(r->getRecTime()); row[3] = std::make_shared>(r->getCopyTime()); - row[4] = std::make_shared>(r->size()); + row[4] = std::make_shared>(static_cast(r->size())); row[5] = std::make_shared>(r->getName()); row[6] = std::make_shared>(r->getId()); row[7] = std::make_shared>(r->getLocator()); if (total_time.count() != 0) { - row[8] = std::make_shared>(r->size() / (total_time.count() / 1000000.0)); + row[8] = std::make_shared>(static_cast( + static_cast(r->size()) / (static_cast(total_time.count()) / 1000000.0))); } else { - row[8] = std::make_shared>(r->size()); + row[8] = std::make_shared>(static_cast(r->size())); } row[9] = std::make_shared>(r->getLoadtime()); row[10] = std::make_shared>(r->getSavetime()); - row[11] = std::make_shared>(r->getMaxRSSDiff()); - row[12] = std::make_shared>(r->getReads()); + row[11] = std::make_shared>(static_cast(r->getMaxRSSDiff())); + row[12] = std::make_shared>(static_cast(r->getReads())); table.addRow(std::make_shared(row)); } @@ -131,11 +132,11 @@ Table inline OutputProcessor::getRulTable() const { row[1] = std::make_shared>(rule->getRuntime()); row[2] = std::make_shared>(std::chrono::microseconds(0)); row[3] = std::make_shared>(std::chrono::microseconds(0)); - row[4] = std::make_shared>(rule->size()); + row[4] = std::make_shared>(static_cast(rule->size())); row[5] = std::make_shared>(rule->getName()); row[6] = std::make_shared>(rule->getId()); row[7] = std::make_shared>(rel.second->getName()); - row[8] = std::make_shared>(0); + row[8] = std::make_shared>(0); row[10] = std::make_shared>(rule->getLocator()); ruleMap.emplace(rule->getName(), std::make_shared(row)); } @@ -146,7 +147,8 @@ Table inline OutputProcessor::getRulTable() const { Row row = *ruleMap[rule->getName()]; row[2] = std::make_shared>( row[2]->getTimeVal() + rule->getRuntime()); - row[4] = std::make_shared>(row[4]->getLongVal() + rule->size()); + row[4] = std::make_shared>( + row[4]->getLongVal() + static_cast(rule->size())); row[0] = std::make_shared>( row[0]->getTimeVal() + rule->getRuntime()); ruleMap[rule->getName()] = std::make_shared(row); @@ -156,11 +158,11 @@ Table inline OutputProcessor::getRulTable() const { row[1] = std::make_shared>(std::chrono::microseconds(0)); row[2] = std::make_shared>(rule->getRuntime()); row[3] = std::make_shared>(std::chrono::microseconds(0)); - row[4] = std::make_shared>(rule->size()); + row[4] = std::make_shared>(static_cast(rule->size())); row[5] = std::make_shared>(rule->getName()); row[6] = std::make_shared>(rule->getId()); row[7] = std::make_shared>(rel.second->getName()); - row[8] = std::make_shared>(rule->getVersion()); + row[8] = std::make_shared>(rule->getVersion()); row[10] = std::make_shared>(rule->getLocator()); ruleMap[rule->getName()] = std::make_shared(row); } @@ -217,8 +219,8 @@ Table inline OutputProcessor::getAtomTable(std::string strRel, std::string strRu Row row(4); row[0] = std::make_shared>(atom.rule); row[1] = std::make_shared>(atom.identifier); - row[2] = std::make_shared>(atom.level); - row[3] = std::make_shared>(atom.frequency); + row[2] = std::make_shared>(static_cast(atom.level)); + row[3] = std::make_shared>(static_cast(atom.frequency)); table.addRow(std::make_shared(row)); } @@ -301,7 +303,8 @@ Table inline OutputProcessor::getVersions(std::string strRel, std::string strRul Row row = *ruleMap[strTemp]; row[2] = std::make_shared>( row[2]->getTimeVal() + rule->getRuntime()); - row[4] = std::make_shared>(row[4]->getLongVal() + rule->size()); + row[4] = std::make_shared>( + row[4]->getLongVal() + static_cast(rule->size())); row[0] = std::make_shared>(rule->getRuntime()); ruleMap[strTemp] = std::make_shared(row); } else { @@ -309,11 +312,11 @@ Table inline OutputProcessor::getVersions(std::string strRel, std::string strRul row[1] = std::make_shared>(std::chrono::microseconds(0)); row[2] = std::make_shared>(rule->getRuntime()); row[3] = std::make_shared>(std::chrono::microseconds(0)); - row[4] = std::make_shared>(rule->size()); + row[4] = std::make_shared>(static_cast(rule->size())); row[5] = std::make_shared>(rule->getName()); row[6] = std::make_shared>(rule->getId()); row[7] = std::make_shared>(rel->getName()); - row[8] = std::make_shared>(rule->getVersion()); + row[8] = std::make_shared>(rule->getVersion()); row[9] = std::make_shared>(rule->getLocator()); row[0] = std::make_shared>(rule->getRuntime()); ruleMap[strTemp] = std::make_shared(row); @@ -366,8 +369,8 @@ Table inline OutputProcessor::getVersionAtoms(std::string strRel, std::string sr Row row(4); row[0] = std::make_shared>(atom.rule); row[1] = std::make_shared>(atom.identifier); - row[2] = std::make_shared>(atom.level); - row[3] = std::make_shared>(atom.frequency); + row[2] = std::make_shared>(static_cast(atom.level)); + row[3] = std::make_shared>(static_cast(atom.frequency)); table.addRow(std::make_shared(row)); } } diff --git a/src/include/souffle/profile/ProgramRun.h b/src/include/souffle/profile/ProgramRun.h index a2e2e7f512b..b4422a9c2fe 100644 --- a/src/include/souffle/profile/ProgramRun.h +++ b/src/include/souffle/profile/ProgramRun.h @@ -138,6 +138,8 @@ class ProgramRun { for (auto& cur : relationMap) { if (cur.second->getStarttime() <= end && cur.second->getEndtime() >= start) { result.insert(cur.second); + } else if (cur.second->getLoadStarttime() <= end && cur.second->getLoadEndtime() >= start) { + result.insert(cur.second); } } return result; @@ -147,7 +149,7 @@ class ProgramRun { return Tools::formatTime(runtime); } - inline std::string formatNum(int precision, long number) const { + inline std::string formatNum(int precision, int64_t number) const { return Tools::formatNum(precision, number); } diff --git a/src/include/souffle/profile/Reader.h b/src/include/souffle/profile/Reader.h index f293d9d25cf..5d8cc363187 100644 --- a/src/include/souffle/profile/Reader.h +++ b/src/include/souffle/profile/Reader.h @@ -230,8 +230,7 @@ class RelationVisitor : public DSNVisitor { RelationVisitor(Relation& relation) : DSNVisitor(relation) {} void visit(DurationEntry& duration) override { if (duration.getKey() == "loadtime") { - auto loadtime = (duration.getEnd() - duration.getStart()); - base.setLoadtime(loadtime); + base.setLoadtime(duration.getStart(), duration.getEnd()); } else if (duration.getKey() == "savetime") { auto savetime = (duration.getEnd() - duration.getStart()); base.setSavetime(savetime); diff --git a/src/include/souffle/profile/Relation.h b/src/include/souffle/profile/Relation.h index b0bffd148a9..0a16d96dd7a 100644 --- a/src/include/souffle/profile/Relation.h +++ b/src/include/souffle/profile/Relation.h @@ -31,7 +31,8 @@ class Relation { const std::string name; std::chrono::microseconds starttime{}; std::chrono::microseconds endtime{}; - std::chrono::microseconds loadtime{}; + std::chrono::microseconds loadstarttime{}; + std::chrono::microseconds loadendtime{}; std::chrono::microseconds savetime{}; std::size_t nonRecTuples = 0; std::size_t preMaxRSS = 0; @@ -70,7 +71,15 @@ class Relation { } std::chrono::microseconds getLoadtime() const { - return loadtime; + return loadendtime - loadstarttime; + } + + std::chrono::microseconds getLoadStarttime() const { + return loadstarttime; + } + + std::chrono::microseconds getLoadEndtime() const { + return loadendtime; } std::chrono::microseconds getSavetime() const { @@ -127,8 +136,9 @@ class Relation { return result; } - void setLoadtime(std::chrono::microseconds loadtime) { - this->loadtime = loadtime; + void setLoadtime(std::chrono::microseconds loadstarttime, std::chrono::microseconds loadendtime) { + this->loadstarttime = loadstarttime; + this->loadendtime = loadendtime; } void setSavetime(std::chrono::microseconds savetime) { diff --git a/src/include/souffle/profile/Tui.h b/src/include/souffle/profile/Tui.h index 8ef1210166e..6de9147c364 100644 --- a/src/include/souffle/profile/Tui.h +++ b/src/include/souffle/profile/Tui.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -39,9 +40,11 @@ #include #include #include +#ifndef _MSC_VER #include #include #include +#endif namespace souffle { namespace profile { @@ -213,10 +216,11 @@ class Tui { } } - void runProf() { + /// Return an exit status equal to 0 on success. + int runProf() { if (!loaded && !f_name.empty()) { std::cout << "Error: File cannot be loaded\n"; - return; + return 1; } if (loaded) { std::cout << "SouffleProf\n"; @@ -253,6 +257,8 @@ class Tui { runCommand(c); } } + + return 0; } std::stringstream& genJsonTop(std::stringstream& ss) { @@ -633,47 +639,50 @@ class Tui { return ss.str(); } - void outputHtml(std::string filename = "profiler_html/") { + /// Return an exit status equal to 0 on success. + int outputHtml(std::string filename = "profiler_html/") { std::cout << "SouffleProf\n"; std::cout << "Generating HTML files...\n"; - DIR* dir; - bool exists = false; - - if (filename.find('/') != std::string::npos) { - std::string path = filename.substr(0, filename.find('/')); - if ((dir = opendir(path.c_str())) != nullptr) { - exists = true; - closedir(dir); - } - if (!exists) { - mode_t nMode = 0733; // UNIX style permissions - int nError = 0; - nError = mkdir(path.c_str(), nMode); - if (nError != 0) { - std::cerr << "directory " << path - << " could not be created. Please create it and try again."; - exit(2); + std::filesystem::path filepath(filename); + if (filepath.has_parent_path()) { + std::error_code ec; + std::filesystem::create_directories(filepath.parent_path(), ec); + if (ec != std::error_code{}) { + std::cerr << "directory " << filepath.parent_path() + << " could not be created. Please create it and try again.\n"; + return 2; + } + } + + if (!filepath.has_filename()) { + // create a fresh filename + bool notfound = true; + unsigned i = 1; + while (i < 1000) { + std::filesystem::path freshPath = filepath; + freshPath /= std::to_string(i); + freshPath.replace_extension(".html"); + if (!std::filesystem::exists(freshPath)) { + filepath = freshPath; + notfound = false; + break; } - } - } - std::string filetype = ".html"; - std::string newFile = filename; - - if (filename.size() <= filetype.size() || - !std::equal(filetype.rbegin(), filetype.rend(), filename.rbegin())) { - int i = 0; - do { ++i; - newFile = filename + std::to_string(i) + ".html"; - } while (Tools::file_exists(newFile)); + } + if (notfound) { + std::cerr << "Could not generate a fresh file name (1000 tested).\n"; + return 2; + } } - std::ofstream outfile(newFile); + std::ofstream outfile(filepath); outfile << HtmlGenerator::getHtml(genJson()); - std::cout << "file output to: " << newFile << std::endl; + std::cout << "file output to: " << filepath << std::endl; + + return 0; } void quit() { @@ -883,11 +892,13 @@ class Tui { std::printf("%11s\n", Tools::formatTime(usages.rbegin()->usertime).c_str()); // Add columns to the graph - char grid[height][width]; + // char grid[height][width]; + std::vector> grid; + grid.reserve(height); + grid.resize(height); for (uint32_t i = 0; i < height; ++i) { - for (uint32_t j = 0; j < width; ++j) { - grid[i][j] = ' '; - } + grid[i].reserve(width); + grid[i].resize(width, ' '); } previousUsage = {{}, 0, {}, {}}; @@ -944,11 +955,13 @@ class Tui { uint64_t maxMaxRSS = 0; std::set usages = getUsageStats(width); - char grid[height][width]; + // char grid[height][width]; + std::vector> grid; + grid.reserve(height); + grid.resize(height); for (uint32_t i = 0; i < height; ++i) { - for (uint32_t j = 0; j < width; ++j) { - grid[i][j] = ' '; - } + grid[i].reserve(width); + grid[i].resize(width, ' '); } for (auto& usage : usages) { @@ -1471,10 +1484,14 @@ class Tui { } uint32_t getTermWidth() { +#ifdef _MSC_VER + return 80; +#else struct winsize w {}; ioctl(0, TIOCGWINSZ, &w); uint32_t width = w.ws_col > 0 ? w.ws_col : 80; return width; +#endif } }; diff --git a/src/include/souffle/profile/UserInputReader.h b/src/include/souffle/profile/UserInputReader.h index 0130e25c9e5..767f612be94 100644 --- a/src/include/souffle/profile/UserInputReader.h +++ b/src/include/souffle/profile/UserInputReader.h @@ -12,8 +12,11 @@ #include // for end, begin #include #include + +#ifndef _MSC_VER #include // for termios, tcsetattr, tcgetattr, ECHO, ICANON, cc_t #include // for read +#endif namespace souffle { namespace profile { @@ -54,6 +57,7 @@ class InputReader { } void readchar() { +#ifndef _MSC_VER char buf = 0; struct termios old = {}; if (tcgetattr(0, &old) < 0) { @@ -76,6 +80,13 @@ class InputReader { } current_char = buf; +#else + char buf = 0; + if (_read(0, &buf, 1) < 0) { + perror("read()"); + } + current_char = buf; +#endif } std::string getInput() { output = ""; @@ -139,6 +150,7 @@ class InputReader { return output; } + void setPrompt(std::string prompt) { this->prompt = prompt; } diff --git a/src/include/souffle/profile/htmlJsMain.h b/src/include/souffle/profile/htmlJsMain.h index 01aa7bb7c41..e1ce7b7a0ce 100644 --- a/src/include/souffle/profile/htmlJsMain.h +++ b/src/include/souffle/profile/htmlJsMain.h @@ -157,7 +157,7 @@ function drawGraph() { height: "calc((100vh - 167px) / 2)", axisY: { labelInterpolationFnc: function (value) { - return humanise_time(value); + return humanise_time(value/1000000.0); } }, axisX: { @@ -172,7 +172,11 @@ function drawGraph() { return value; } }, - plugins: [Chartist.plugins.tooltip()] + plugins: [Chartist.plugins.tooltip({ + tooltipFnc: function(meta, value) { + return humanise_time(value / 1000000.0); + } + })] }; new Chartist.Bar(".ct-chart1", { @@ -185,6 +189,11 @@ function drawGraph() { return minify_numbers(value); } }; + options.plugins = [Chartist.plugins.tooltip({ + tooltipFnc: function(meta, value) { + return minify_numbers(value) + " tuples"; + } + })] new Chartist.Bar(".ct-chart2", { labels: graph_vals.labels, diff --git a/src/souffle_prof.cpp b/src/souffle_prof.cpp index 06a77490af7..be9fd2be5b5 100644 --- a/src/souffle_prof.cpp +++ b/src/souffle_prof.cpp @@ -20,7 +20,7 @@ int main(int argc, char* argv[]) { souffle::profile::Cli cli_obj(argc, argv); - cli_obj.parse(); + const int status = cli_obj.parse(); std::cout << "\n"; - return 0; + return status; }