39 #include <unordered_map>
43 #include <sys/ioctl.h>
73 std::chrono::microseconds
time;
83 Tui(std::string filename,
bool live,
bool ) {
88 this->f_name = filename;
92 this->reader = std::make_shared<Reader>(filename, run);
96 this->loaded =
reader->isLoaded();
101 this->reader = std::make_shared<Reader>(run);
105 updater = std::thread([
this]() {
107 std::chrono::milliseconds interval(30000);
110 std::this_thread::sleep_for(std::chrono::milliseconds(500));
130 std::cout <<
"Error: File cannot be loaded\n";
146 std::cout <<
"\x1b[3D";
147 std::cout <<
"\x1b[27A";
149 std::cout <<
"\x1b[B> ";
150 }
else if (c[0] ==
"top") {
152 }
else if (c[0] ==
"rel") {
155 }
else if (c.size() == 1) {
158 std::cout <<
"Invalid parameters to rel command.\n";
160 }
else if (c[0] ==
"rul") {
162 if (c.size() == 3 && c[1] ==
"id") {
165 }
else if (c.size() == 2 && c[1] ==
"id") {
167 }
else if (c.size() == 2) {
170 std::cout <<
"Invalid parameters to rul command.\n";
175 }
else if (c[0] ==
"graph") {
176 if (c.size() == 3 && c[1].find(
".") == std::string::npos) {
178 }
else if (c.size() == 3 && c[1].at(0) ==
'C') {
180 }
else if (c.size() == 4 && c[1] ==
"ver" && c[2].at(0) ==
'C') {
183 std::cout <<
"Invalid parameters to graph command.\n";
185 }
else if (c[0] ==
"memory") {
187 }
else if (c[0] ==
"usage") {
189 if (c[1][0] ==
'R') {
197 }
else if (c[0] ==
"help") {
199 }
else if (c[0] ==
"limit") {
206 std::cout <<
"Invalid parameters to limit command.\n";
209 }
else if (c[0] ==
"configuration") {
212 std::cout <<
"Unknown command. Use \"help\" for a list of commands.\n";
218 std::cout <<
"Error: File cannot be floaded\n";
222 std::cout <<
"SouffleProf\n";
233 std::cout << std::endl;
235 std::cout <<
"Unknown command. Type help for a list of commands.\n";
243 if (c[0] ==
"q" || c[0] ==
"quit") {
246 }
else if (c[0] ==
"sort") {
247 if (c.size() == 2 && std::stoi(c[1]) < 7) {
250 std::cout <<
"Invalid column, please select a number between 0 and 6.\n";
261 auto beginTime = run->getStarttime();
262 auto endTime = run->getEndtime();
263 ss << R
"_({"top":[)_" << (endTime - beginTime).count() / 1000000.0 << "," << run->getTotalSize()
264 <<
"," << run->getTotalLoadtime().count() / 1000000.0 <<
","
265 << run->getTotalSavetime().count() / 1000000.0 <<
"]";
269 std::stringstream&
genJsonRelations(std::stringstream&
ss,
const std::string& name,
size_t maxRows) {
272 auto comma = [&
ss](
bool& first,
const std::string& delimiter =
", ") {
280 ss <<
'"' << name << R
"_(":{)_";
281 bool firstRow =
true;
283 std::stable_sort(rows.begin(), rows.end(), [](std::shared_ptr<Row> left, std::shared_ptr<Row> right) {
284 return (*left)[0]->getDoubleVal() > (*right)[0]->getDoubleVal();
286 maxRows = std::min(rows.size(), maxRows);
288 for (
size_t i = 0;
i < maxRows; ++
i) {
289 comma(firstRow,
",\n");
292 ss <<
'"' << row[6]->toString(0) << R
"_(": [)_";
295 ss << row[0]->getDoubleVal() << ", ";
296 ss << row[1]->getDoubleVal() <<
", ";
297 ss << row[2]->getDoubleVal() <<
", ";
298 ss << row[3]->getDoubleVal() <<
", ";
299 ss << row[4]->getLongVal() <<
", ";
300 ss << row[12]->getLongVal() <<
", ";
303 bool firstCol =
true;
305 Row rel_row = *_rel_row;
308 ss <<
'"' << rel_row[6]->toString(0) <<
'"';
312 std::vector<std::shared_ptr<Iteration>> iter =
313 run->getRelation(row[5]->
toString(0))->getIterations();
314 ss << R
"_({"tot_t": [)_";
316 for (
auto&
i : iter) {
318 ss <<
i->getRuntime().count();
320 ss << R
"_(], "copy_t": [)_";
322 for (
auto&
i : iter) {
324 ss <<
i->getCopytime().count();
326 ss << R
"_(], "tuples": [)_";
328 for (
auto&
i : iter) {
339 std::stringstream&
genJsonRules(std::stringstream&
ss,
const std::string& name,
size_t maxRows) {
342 auto comma = [&
ss](
bool& first,
const std::string& delimiter =
", ") {
350 ss <<
'"' << name << R
"_(":{)_";
352 bool firstRow =
true;
354 std::stable_sort(rows.begin(), rows.end(), [](std::shared_ptr<Row> left, std::shared_ptr<Row> right) {
355 return (*left)[0]->getDoubleVal() > (*right)[0]->getDoubleVal();
357 maxRows = std::min(rows.size(), maxRows);
359 for (
size_t i = 0;
i < maxRows; ++
i) {
363 std::string strRel =
"R" + part[0].substr(1);
367 if (versionTable.rows.
size() > 0) {
368 if (versionTable.rows[0]->cells[9] !=
nullptr) {
369 src = (*versionTable.rows[0])[9]->
toString(0);
374 src = row[10]->toString(-1);
379 ss <<
'"' << row[6]->toString(0) << R
"_(": [)_";
382 ss << row[0]->getDoubleVal() << ", ";
383 ss << row[1]->getDoubleVal() <<
", ";
384 ss << row[2]->getDoubleVal() <<
", ";
385 ss << row[4]->getLongVal() <<
", ";
387 ss <<
'"' << src << R
"_(", )_";
390 bool has_ver =
false;
391 bool firstCol =
true;
392 for (
auto& _ver_row : versionTable.getRows()) {
395 Row ver_row = *_ver_row;
399 ss << ver_row[0]->getDoubleVal() << ", ";
400 ss << ver_row[1]->getDoubleVal() <<
", ";
401 ss << ver_row[2]->getDoubleVal() <<
", ";
402 ss << ver_row[4]->getLongVal() <<
", ";
403 ss <<
'"' << src << R
"_(", )_";
404 ss << ver_row[8]->getLongVal();
410 if (row[6]->
toString(0).at(0) !=
'C') {
413 ss << R
"_({"tot_t": [)_";
415 std::vector<uint64_t> iteration_tuples;
416 bool firstCol =
true;
417 for (
auto&
i : run->getRelation(row[7]->toString(0))->getIterations()) {
419 std::chrono::microseconds totalTime{};
420 uint64_t totalSize = 0L;
421 for (
auto&
rul :
i->getRules()) {
422 if (
rul.second->getId() == row[6]->toString(0)) {
423 totalTime +=
rul.second->getRuntime();
425 totalSize +=
rul.second->size();
431 ss << totalTime.count();
432 iteration_tuples.push_back(totalSize);
435 ss << R
"_(], "tuples": [)_";
437 for (
auto&
i : iteration_tuples) {
445 ss << R
"_("tot_t": [)_";
448 for (
auto& row : versionTable.rows) {
450 ss << (*row)[0]->getDoubleVal();
452 ss << R
"_(], "tuples": [)_";
455 for (
auto& row : versionTable.rows) {
457 ss << (*row)[4]->getLongVal();
471 auto comma = [&
ss](
bool& first,
const std::string& delimiter =
", ") {
480 std::string source_file_loc =
Tools::split(source_loc,
" ").at(0);
481 std::ifstream source_file(source_file_loc);
482 if (!source_file.is_open()) {
483 std::cout <<
"Error opening \"" << source_file_loc <<
"\", creating GUI without source locator."
487 ss << R
"_("code": [)_";
488 bool firstCol =
true;
489 while (getline(source_file,
str)) {
490 comma(firstCol,
",\n");
499 auto beginTime = run->getStarttime();
501 ss << R
"_("usage": [)_";
502 bool firstRow =
true;
503 Usage previousUsage = *usages.begin();
504 previousUsage.time = beginTime;
505 for (
auto usage : usages) {
508 ss << (
usage.time - beginTime).
count() / 1000000.0 <<
", ";
509 ss << 100.0 * (
usage.usertime - previousUsage.usertime) / (
usage.time - previousUsage.time)
511 ss << 100.0 * (
usage.systemtime - previousUsage.systemtime) / (
usage.time - previousUsage.time)
513 ss <<
usage.maxRSS * 1024 <<
", ";
515 bool firstCol =
true;
518 ss << cur->getName();
522 previousUsage =
usage;
529 auto comma = [&
ss](
bool& first,
const std::string& delimiter =
", ") {
538 ss << R
"_("configuration": {)_";
539 bool firstRow =
true;
552 auto comma = [&
ss](
bool& first,
const std::string& delimiter =
", ") {
560 ss << R
"_("atoms": {)_";
562 bool firstRow =
true;
563 for (
auto&
relation : run->getRelationMap()) {
566 comma(firstRow,
", \n");
567 ss <<
'"' <<
rule.second->getId() << R
"_(": [)_";
568 bool firstCol =
true;
569 for (
auto& atom :
rule.second->getAtoms()) {
571 std::string relationName = atom.identifier;
572 relationName = relationName.substr(0, relationName.find(
'('));
574 std::string relationSize =
relation ==
nullptr ?
"" : std::to_string(
relation->size());
578 ss << relationSize << ", ";
579 ss << atom.frequency <<
']';
586 comma(firstRow,
", \n");
587 ss <<
'"' <<
rule.second->getId() << R
"_(": [)_";
588 bool firstCol =
true;
589 for (
auto& atom :
rule.second->getAtoms()) {
591 std::string relationName = atom.identifier;
592 relationName = relationName.substr(0, relationName.find(
'('));
594 std::string relationSize =
599 ss << relationSize << ", ";
600 ss << atom.frequency <<
']';
612 std::stringstream
ss;
637 std::cout <<
"SouffleProf\n";
638 std::cout <<
"Generating HTML files...\n";
643 if (filename.find(
'/') != std::string::npos) {
644 std::string path = filename.substr(0, filename.find(
'/'));
645 if ((dir = opendir(path.c_str())) !=
nullptr) {
652 nError = mkdir(path.c_str(), nMode);
654 std::cerr <<
"directory " << path
655 <<
" could not be created. Please create it and try again.";
660 std::string filetype =
".html";
661 std::string newFile = filename;
663 if (filename.size() <= filetype.size() ||
664 !std::equal(filetype.rbegin(), filetype.rend(), filename.rbegin())) {
668 newFile = filename + std::to_string(
i) +
".html";
672 std::ofstream outfile(newFile);
676 std::cout <<
"file output to: " << newFile << std::endl;
686 std::cout <<
"\nAvailable profiling commands:" << std::endl;
687 std::printf(
" %-30s%-5s %s\n",
"rel",
"-",
"display relation table.");
688 std::printf(
" %-30s%-5s %s\n",
"rel <relation id>",
"-",
"display all rules of a given relation.");
689 std::printf(
" %-30s%-5s %s\n",
"rul",
"-",
"display rule table");
690 std::printf(
" %-30s%-5s %s\n",
"rul <rule id>",
"-",
"display all version of given rule.");
691 std::printf(
" %-30s%-5s %s\n",
"rul id",
"-",
"display all rules names and ids.");
693 " %-30s%-5s %s\n",
"rul id <rule id>",
"-",
"display the rule name for the given rule id.");
694 std::printf(
" %-30s%-5s %s\n",
"graph <relation id> <type>",
"-",
695 "graph a relation by type: (tot_t/copy_t/tuples).");
696 std::printf(
" %-30s%-5s %s\n",
"graph <rule id> <type>",
"-",
697 "graph recursive(C) rule by type(tot_t/tuples).");
698 std::printf(
" %-30s%-5s %s\n",
"graph ver <rule id> <type>",
"-",
699 "graph recursive(C) rule versions by type(tot_t/copy_t/tuples).");
700 std::printf(
" %-30s%-5s %s\n",
"top",
"-",
"display top-level summary of program run.");
701 std::printf(
" %-30s%-5s %s\n",
"configuration",
"-",
"display configuration settings for this run.");
702 std::printf(
" %-30s%-5s %s\n",
"usage [relation id|rule id]",
"-",
703 "display CPU usage graphs for a relation or rule.");
704 std::printf(
" %-30s%-5s %s\n",
"memory",
"-",
"display memory usage.");
705 std::printf(
" %-30s%-5s %s\n",
"help",
"-",
"print this.");
707 std::cout <<
"\nInteractive mode only commands:" << std::endl;
710 std::printf(
" %-30s%-5s %s\n",
"limit <row count>",
"-",
"limit number of results shown.");
711 std::printf(
" %-30s%-5s %s\n",
"sort <col number>",
"-",
"sort tables by given column number.");
712 std::printf(
" %-30s%-5s %s\n",
"q",
"-",
"exit program.");
716 std::vector<std::vector<std::string>> formattedRelationTable =
718 std::string name =
"";
720 for (
auto& row : formattedRelationTable) {
721 if (row[5] ==
id || row[6] ==
id) {
728 std::cout <<
"Relation does not exist.\n";
738 std::string relName =
"";
739 std::string srcLocator =
"";
741 for (
auto& row : formattedRuleTable) {
742 if (row[5] ==
id || row[6] ==
id) {
744 srcLocator = row[10];
750 std::cout <<
"Rule does not exist.\n";
755 if (
rel ==
nullptr) {
756 std::cout <<
"Relation ceased to exist. Odd." << std::endl;
759 if (
rel->getRuleMap().count(srcLocator) == 0) {
760 std::cout <<
"Rule ceased to exist. Odd." << std::endl;
764 auto&
rul =
rel->getRuleMap().at(srcLocator);
769 std::set<Usage> usages;
770 DirectoryEntry* usageStats =
dynamic_cast<DirectoryEntry*
>(
772 if (usageStats ==
nullptr || usageStats->getKeys().size() < 2) {
775 std::chrono::microseconds endTime{};
776 std::chrono::microseconds startTime{};
777 std::chrono::microseconds timeStep{};
779 std::set<Usage> allUsages;
780 for (
auto& currentKey : usageStats->getKeys()) {
781 Usage currentUsage{};
782 uint64_t cur = std::stoul(currentKey);
783 currentUsage.time = std::chrono::duration<uint64_t, std::micro>(cur);
784 cur =
dynamic_cast<SizeEntry*
>(
785 usageStats->readDirectoryEntry(currentKey)->readEntry(
"systemtime"))
787 currentUsage.systemtime = std::chrono::duration<uint64_t, std::micro>(cur);
788 cur =
dynamic_cast<SizeEntry*
>(usageStats->readDirectoryEntry(currentKey)->readEntry(
"usertime"))
790 currentUsage.usertime = std::chrono::duration<uint64_t, std::micro>(cur);
791 currentUsage.maxRSS =
792 dynamic_cast<SizeEntry*
>(usageStats->readDirectoryEntry(currentKey)->readEntry(
"maxRSS"))
796 if (allUsages.find(currentUsage) != allUsages.end()) {
797 auto& existing = *allUsages.find(currentUsage);
798 currentUsage.systemtime = std::max(existing.systemtime, currentUsage.systemtime);
799 currentUsage.usertime = std::max(existing.usertime, currentUsage.usertime);
800 currentUsage.maxRSS = std::max(existing.maxRSS, currentUsage.maxRSS);
801 allUsages.erase(currentUsage);
803 allUsages.insert(currentUsage);
807 for (
auto it = ++allUsages.begin(); it != allUsages.end(); ++it) {
808 auto previous = std::prev(it);
809 if (it->usertime < previous->usertime || it->systemtime < previous->systemtime ||
810 it->time == previous->time) {
811 it = allUsages.erase(it);
817 startTime = allUsages.begin()->time;
818 endTime = allUsages.rbegin()->time;
821 if (allUsages.size() < width) {
825 timeStep = (endTime - startTime) / width;
828 for (uint32_t
i = 1;
i <= width; ++
i) {
829 auto it = allUsages.upper_bound(Usage{startTime + timeStep *
i, 0, {}, {}});
830 if (it != allUsages.begin()) {
840 usage({}, {}, height);
843 void usage(std::chrono::microseconds endTime, std::chrono::microseconds startTime, uint32_t height = 20) {
848 if (usages.size() < 2) {
849 for (uint8_t
i = 0;
i < height + 2; ++
i) {
850 std::cout << std::endl;
852 std::cout <<
"Insufficient data for usage statistics." << std::endl;
856 double maxIntervalUsage = 0;
859 if (startTime.count() == 0) {
860 startTime = usages.begin()->time;
862 if (endTime.count() == 0) {
863 endTime = usages.rbegin()->time;
866 if (usages.size() < width) {
867 width = usages.size();
871 Usage previousUsage{{}, 0, {}, {}};
872 for (
auto& currentUsage : usages) {
873 double usageDiff = (currentUsage.systemtime - previousUsage.systemtime + currentUsage.usertime -
874 previousUsage.usertime)
876 usageDiff /= (currentUsage.time - previousUsage.time).
count();
877 if (usageDiff > maxIntervalUsage) {
878 maxIntervalUsage = usageDiff;
881 previousUsage = currentUsage;
884 double intervalUsagePercent = 100.0 * maxIntervalUsage;
889 char grid[height][width];
890 for (uint32_t
i = 0;
i < height; ++
i) {
891 for (uint32_t
j = 0;
j < width; ++
j) {
896 previousUsage = {{}, 0, {}, {}};
898 for (
const Usage& currentUsage : usages) {
899 uint64_t curHeight = 0;
900 uint64_t curSystemHeight = 0;
902 if (maxIntervalUsage != 0) {
903 curHeight = (currentUsage.systemtime - previousUsage.systemtime + currentUsage.usertime -
904 previousUsage.usertime)
906 curHeight /= (currentUsage.time - previousUsage.time).
count();
907 curHeight *= height / maxIntervalUsage;
909 curSystemHeight = (currentUsage.systemtime - previousUsage.systemtime).
count();
910 curSystemHeight /= (currentUsage.time - previousUsage.time).
count();
911 curSystemHeight *= height / maxIntervalUsage;
913 for (uint32_t row = 0; row < curHeight; ++row) {
914 grid[row][col] =
'*';
916 for (uint32_t row = curHeight - curSystemHeight; row < curHeight; ++row) {
917 grid[row][col] =
'+';
919 previousUsage = currentUsage;
924 for (int32_t row = height - 1; row >= 0; --row) {
925 printf(
"%6d%% ", uint32_t(intervalUsagePercent * (row + 1) / height));
926 for (uint32_t col = 0; col < width; ++col) {
927 std::cout << grid[row][col];
929 std::cout << std::endl;
931 for (uint32_t col = 0; col < 8; ++col) {
934 for (uint32_t col = 0; col < width; ++col) {
937 std::cout << std::endl;
944 void memoryUsage(std::chrono::microseconds , std::chrono::microseconds ,
945 uint32_t height = 20) {
947 uint64_t maxMaxRSS = 0;
950 char grid[height][width];
951 for (uint32_t
i = 0;
i < height; ++
i) {
952 for (uint32_t
j = 0;
j < width; ++
j) {
957 for (
auto&
usage : usages) {
958 maxMaxRSS = std::max(maxMaxRSS,
usage.maxRSS);
961 for (
const Usage& currentUsage : usages) {
962 uint64_t curHeight = height * currentUsage.maxRSS / maxMaxRSS;
963 for (uint32_t row = 0; row < curHeight; ++row) {
964 grid[row][col] =
'*';
970 for (int32_t row = height - 1; row >= 0; --row) {
972 for (uint32_t col = 0; col < width; ++col) {
973 std::cout << grid[row][col];
975 std::cout << std::endl;
977 for (uint32_t col = 0; col < 8; ++col) {
980 for (uint32_t col = 0; col < width; ++col) {
983 std::cout << std::endl;
1010 std::cout <<
"Configuration" <<
'\n';
1011 printf(
"%30s %s",
"Key",
"Value\n\n");
1014 if (kvp.first ==
"") {
1015 printf(
"%30s %s\n",
"Datalog input file", kvp.second.c_str());
1018 printf(
"%30s %s\n", kvp.first.c_str(), kvp.second.c_str());
1020 std::cout << std::endl;
1025 auto* totalRelationsEntry =
1027 {
"program",
"configuration",
"relationCount"}));
1028 auto* totalRulesEntry =
1030 {
"program",
"configuration",
"ruleCount"}));
1031 size_t totalRelations = 0;
1032 if (totalRelationsEntry !=
nullptr) {
1033 totalRelations = std::stoul(totalRelationsEntry->getText());
1035 totalRelations = run->getRelationMap().size();
1037 size_t totalRules = 0;
1038 if (totalRulesEntry !=
nullptr) {
1039 totalRules = std::stoul(totalRulesEntry->getText());
1043 std::printf(
"%11s%10s%10s%10s%10s%20s\n",
"runtime",
"loadtime",
"savetime",
"relations",
"rules",
1044 "tuples generated");
1046 std::printf(
"%11s%10s%10s%10s%10s%14s\n", run->getRuntime().c_str(),
1047 run->formatTime(run->getTotalLoadtime()).c_str(),
1048 run->formatTime(run->getTotalSavetime()).c_str(), run->formatNum(0, totalRelations).c_str(),
1049 run->formatNum(0, totalRules).c_str(),
1050 run->formatNum(
precision, run->getTotalSize()).c_str());
1054 size_t processedRelations = run->getRelationMap().size();
1056 if (
alive && totalRelationsEntry !=
nullptr) {
1057 std::cout <<
"Progress ";
1058 for (
size_t i = 0;
i < screenWidth; ++
i) {
1059 if (screenWidth * processedRelations / totalRelations >
i) {
1066 std::cout << std::endl;
1068 std::cout <<
"Slowest relations to fully evaluate\n";
1073 std::cout <<
"Slowest rules to fully evaluate\n";
1086 void rel(
size_t limit,
bool showLimit =
true) {
1088 std::cout <<
" ----- Relation Table -----\n";
1089 std::printf(
"%8s%8s%8s%8s%8s%8s%8s%8s%8s%6s %s\n\n",
"TOT_T",
"NREC_T",
"REC_T",
"COPY_T",
"LOAD_T",
1090 "SAVE_T",
"TUPLES",
"READS",
"TUP/s",
"ID",
"NAME");
1093 if (++
count > limit) {
1100 std::printf(
"%8s%8s%8s%8s%8s%8s%8s%8s%8s%6s %s\n", row[0].c_str(), row[1].c_str(), row[2].c_str(),
1101 row[3].c_str(), row[9].c_str(), row[10].c_str(), row[4].c_str(), row[12].c_str(),
1102 row[8].c_str(), row[6].c_str(), row[5].c_str());
1106 void rul(
size_t limit,
bool showLimit =
true) {
1108 std::cout <<
" ----- Rule Table -----\n";
1110 "%8s%8s%8s%8s%8s%8s %s\n\n",
"TOT_T",
"NREC_T",
"REC_T",
"TUPLES",
"TUP/s",
"ID",
"RELATION");
1113 if (++
count > limit) {
1119 std::printf(
"%8s%8s%8s%8s%8s%8s %s\n", row[0].c_str(), row[1].c_str(), row[2].c_str(),
1120 row[4].c_str(), row[9].c_str(), row[6].c_str(), row[7].c_str());
1124 void id(std::string col) {
1130 for (
auto& row : table) {
1131 std::printf(
"%7s%2s%s\n", row[6].c_str(),
"", row[5].c_str());
1134 for (
auto& row : table) {
1135 if (row[6] == col) {
1136 std::printf(
"%7s%2s%s\n", row[6].c_str(),
"", row[5].c_str());
1146 std::vector<std::vector<std::string>> formattedRelationTable =
1149 std::cout <<
" ----- Rules of a Relation -----\n";
1150 std::printf(
"%8s%8s%8s%8s%8s %s\n\n",
"TOT_T",
"NREC_T",
"REC_T",
"TUPLES",
"ID",
"NAME");
1151 std::string name =
"";
1152 for (
auto& row : formattedRelationTable) {
1154 if (row[5] ==
str || row[6] ==
str) {
1155 std::printf(
"%8s%8s%8s%8s%8s %s\n", row[0].c_str(), row[1].c_str(), row[2].c_str(),
1156 row[4].c_str(), row[6].c_str(), row[5].c_str());
1161 std::cout <<
" ---------------------------------------------------------\n";
1162 for (
auto& row : formattedRuleTable) {
1163 if (row[7] == name) {
1164 std::printf(
"%8s%8s%8s%8s%8s %s\n", row[0].c_str(), row[1].c_str(), row[2].c_str(),
1165 row[4].c_str(), row[6].c_str(), row[7].c_str());
1168 std::string src =
"";
1170 if (run->getRelation(name) !=
nullptr) {
1171 src = run->getRelation(name)->getLocator();
1173 std::cout <<
"\nSrc locator: " << src <<
"\n\n";
1174 for (
auto& row : formattedRuleTable) {
1175 if (row[7] == name) {
1176 std::printf(
"%7s%2s%s\n", row[6].c_str(),
"", row[5].c_str());
1182 if (
str.find(
".") == std::string::npos) {
1183 std::cout <<
"Rule does not exist\n";
1187 std::string strRel =
"R" + part[0].substr(1);
1197 std::string ruleName;
1198 std::string srcLocator;
1200 for (
auto& row : formattedRuleTable) {
1201 if (row[6] ==
str) {
1202 std::cout << row[5] << std::endl;
1205 srcLocator = row[10];
1211 if (versionTable.rows.size() > 0) {
1212 if (versionTable.rows[0]->cells[9] !=
nullptr) {
1213 std::cout <<
"Src locator-: " << (*versionTable.rows[0])[9]->getStringVal() <<
"\n\n";
1215 std::cout <<
"Src locator-: -\n\n";
1217 }
else if (formattedRuleTable.size() > 0) {
1218 std::cout <<
"Src locator-: " << formattedRuleTable[0][10] <<
"\n\n";
1223 std::cout <<
" ----- Rule Versions Table -----\n";
1224 std::printf(
"%8s%8s%8s%16s%6s\n\n",
"TOT_T",
"NREC_T",
"REC_T",
"TUPLES",
"VER");
1225 for (
auto& row : formattedRuleTable) {
1226 if (row[6] ==
str) {
1227 std::printf(
"%8s%8s%8s%16s%6s\n", row[0].c_str(), row[1].c_str(), row[2].c_str(),
1228 row[4].c_str(),
"");
1231 std::cout <<
" ---------------------------------------------\n";
1232 for (
auto& _row : versionTable.rows) {
1242 if (!versionTable.rows.empty()) {
1253 std::vector<std::shared_ptr<Iteration>> iter;
1254 for (
auto& row : table) {
1256 std::printf(
"%4s%2s%s\n\n", row[6].c_str(),
"", row[5].c_str());
1257 iter = run->getRelation(row[5])->getIterations();
1258 if (col ==
"tot_t") {
1259 std::vector<std::chrono::microseconds> list;
1260 for (
auto&
i : iter) {
1261 list.emplace_back(
i->getRuntime());
1265 }
else if (col ==
"copy_t") {
1266 std::vector<std::chrono::microseconds> list;
1267 for (
auto&
i : iter) {
1268 list.emplace_back(
i->getCopytime());
1272 }
else if (col ==
"tuples") {
1273 std::vector<size_t> list;
1274 for (
auto&
i : iter) {
1275 list.emplace_back(
i->size());
1283 for (
auto& row : table) {
1285 std::printf(
"%4s%2s%s\n\n", row[6].c_str(),
"", row[5].c_str());
1287 iter = run->getRelation(row[5])->getIterations();
1288 if (col ==
"tot_t") {
1289 std::vector<std::chrono::microseconds> list;
1290 for (
auto&
i : iter) {
1291 list.emplace_back(
i->getRuntime());
1295 }
else if (col ==
"copy_t") {
1296 std::vector<std::chrono::microseconds> list;
1297 for (
auto&
i : iter) {
1298 list.emplace_back(
i->getCopytime());
1302 }
else if (col ==
"tuples") {
1303 std::vector<size_t> list;
1304 for (
auto&
i : iter) {
1305 list.emplace_back(
i->size());
1317 std::vector<std::shared_ptr<Iteration>> iter;
1318 for (
auto& row : table) {
1320 std::printf(
"%6s%2s%s\n\n", row[6].c_str(),
"", row[5].c_str());
1322 iter = run->getRelation(row[7])->getIterations();
1323 if (col ==
"tot_t") {
1324 std::vector<std::chrono::microseconds> list;
1325 for (
auto&
i : iter) {
1327 std::chrono::microseconds totalTime{};
1328 for (
auto&
rul :
i->getRules()) {
1329 if (
rul.second->getId() == c) {
1330 totalTime +=
rul.second->getRuntime();
1335 list.emplace_back(totalTime);
1340 }
else if (col ==
"tuples") {
1341 std::vector<size_t> list;
1342 for (
auto&
i : iter) {
1344 size_t totalSize = 0L;
1345 for (
auto&
rul :
i->getRules()) {
1346 if (
rul.second->getId() == c) {
1347 totalSize +=
rul.second->size();
1352 list.emplace_back(totalSize);
1364 if (c.find(
'.') == std::string::npos) {
1365 std::cout <<
"Rule does not exist";
1370 std::string strRel =
"R" + part[0].substr(1);
1373 std::printf(
"%6s%2s%s\n\n", (*versionTable.rows[0])[6]->toString(0).c_str(),
"",
1374 (*versionTable.rows[0])[5]->toString(0).c_str());
1375 if (col ==
"tot_t") {
1376 std::vector<std::chrono::microseconds> list;
1377 for (
auto& row : versionTable.rows) {
1378 list.emplace_back((*row)[0]->getTimeVal());
1382 }
else if (col ==
"copy_t") {
1383 std::vector<std::chrono::microseconds> list;
1384 for (
auto& row : versionTable.rows) {
1385 list.emplace_back((*row)[3]->getTimeVal());
1389 }
else if (col ==
"tuples") {
1390 std::vector<size_t> list;
1391 for (
auto& row : versionTable.rows) {
1392 list.emplace_back((*row)[4]->getLongVal());
1400 std::chrono::microseconds max{};
1401 for (
auto&
d : list) {
1407 std::sort(list.begin(), list.end());
1408 std::reverse(list.begin(), list.end());
1410 for (
auto&
d : list) {
1411 uint32_t len = 67.0 *
d.count() / max.count();
1412 std::string bar =
"";
1413 for (uint32_t
j = 0;
j < len;
j++) {
1417 std::printf(
"%4d %10.8f | %s\n",
i++, (
d.count() / 1000000.0), bar.c_str());
1423 for (
auto&
l : list) {
1428 std::sort(list.begin(), list.end());
1429 std::reverse(list.begin(), list.end());
1431 for (
auto&
l : list) {
1432 size_t len = max == 0 ? 0 : 64.0 *
l / max;
1433 std::string bar =
"";
1434 for (uint32_t
j = 0;
j < len;
j++) {
1443 void verAtoms(Table& atomTable,
const std::string& ruleName =
"") {
1446 if (atomTable.rows.empty()) {
1449 bool firstRun =
true;
1450 std::string lastRule = ruleName;
1451 for (
auto& _row : atomTable.rows) {
1454 if (
rule != lastRule) {
1456 std::cout <<
" " << row[0]->toString(
precision) << std::endl;
1460 std::printf(
" %-16s%-16s%s\n",
"FREQ",
"RELSIZE",
"ATOM");
1463 std::string relationName = row[1]->getStringVal();
1464 relationName = relationName.substr(0, relationName.find(
'('));
1466 std::string relationSize =
relation ==
nullptr ?
"--" : std::to_string(
relation->size());
1468 row[1]->getStringVal().c_str());
1479 struct winsize w {};
1480 ioctl(0, TIOCGWINSZ, &w);
1481 uint32_t width = w.ws_col > 0 ? w.ws_col : 80;