| 1 | /*
 | 
| 2 |  * Souffle - A Datalog Compiler
 | 
| 3 |  * Copyright (c) 2016, The Souffle Developers. All rights reserved
 | 
| 4 |  * Licensed under the Universal Permissive License v 1.0 as shown at:
 | 
| 5 |  * - https://opensource.org/licenses/UPL
 | 
| 6 |  * - <souffle root>/licenses/SOUFFLE-UPL.txt
 | 
| 7 |  */
 | 
| 8 | 
 | 
| 9 | #pragma once
 | 
| 10 | 
 | 
| 11 | #include "souffle/profile/Cell.h"
 | 
| 12 | #include "souffle/profile/CellInterface.h"
 | 
| 13 | #include "souffle/profile/Iteration.h"
 | 
| 14 | #include "souffle/profile/ProgramRun.h"
 | 
| 15 | #include "souffle/profile/Relation.h"
 | 
| 16 | #include "souffle/profile/Row.h"
 | 
| 17 | #include "souffle/profile/Rule.h"
 | 
| 18 | #include "souffle/profile/Table.h"
 | 
| 19 | #include <chrono>
 | 
| 20 | #include <memory>
 | 
| 21 | #include <ratio>
 | 
| 22 | #include <set>
 | 
| 23 | #include <string>
 | 
| 24 | #include <unordered_map>
 | 
| 25 | #include <utility>
 | 
| 26 | #include <vector>
 | 
| 27 | 
 | 
| 28 | namespace souffle {
 | 
| 29 | namespace profile {
 | 
| 30 | 
 | 
| 31 | /*
 | 
| 32 |  * Class to format profiler data structures into tables
 | 
| 33 |  */
 | 
| 34 | class OutputProcessor {
 | 
| 35 | private:
 | 
| 36 |     std::shared_ptr<ProgramRun> programRun;
 | 
| 37 | 
 | 
| 38 | public:
 | 
| 39 |     OutputProcessor() {
 | 
| 40 |         programRun = std::make_shared<ProgramRun>(ProgramRun());
 | 
| 41 |     }
 | 
| 42 | 
 | 
| 43 |     const std::shared_ptr<ProgramRun>& getProgramRun() const {
 | 
| 44 |         return programRun;
 | 
| 45 |     }
 | 
| 46 | 
 | 
| 47 |     Table getRelTable() const;
 | 
| 48 | 
 | 
| 49 |     Table getRulTable() const;
 | 
| 50 | 
 | 
| 51 |     Table getSubrulTable(std::string strRel, std::string strRul) const;
 | 
| 52 | 
 | 
| 53 |     Table getAtomTable(std::string strRel, std::string strRul) const;
 | 
| 54 | 
 | 
| 55 |     Table getVersions(std::string strRel, std::string strRul) const;
 | 
| 56 | 
 | 
| 57 |     Table getVersionAtoms(std::string strRel, std::string strRul, int version) const;
 | 
| 58 | };
 | 
| 59 | 
 | 
| 60 | /*
 | 
| 61 |  * rel table :
 | 
| 62 |  * ROW[0] = TOT_T
 | 
| 63 |  * ROW[1] = NREC_T
 | 
| 64 |  * ROW[2] = REC_T
 | 
| 65 |  * ROW[3] = COPY_T
 | 
| 66 |  * ROW[4] = TUPLES
 | 
| 67 |  * ROW[5] = REL NAME
 | 
| 68 |  * ROW[6] = ID
 | 
| 69 |  * ROW[7] = SRC
 | 
| 70 |  * ROW[8] = PERFOR
 | 
| 71 |  * ROW[9] = LOADTIME
 | 
| 72 |  * ROW[10] = SAVETIME
 | 
| 73 |  * ROW[11] = MAXRSSDIFF
 | 
| 74 |  * ROW[12] = READS
 | 
| 75 |  *
 | 
| 76 |  */
 | 
| 77 | Table inline OutputProcessor::getRelTable() const {
 | 
| 78 |     const std::unordered_map<std::string, std::shared_ptr<Relation>>& relationMap =
 | 
| 79 |             programRun->getRelationMap();
 | 
| 80 |     Table table;
 | 
| 81 |     for (auto& rel : relationMap) {
 | 
| 82 |         std::shared_ptr<Relation> r = rel.second;
 | 
| 83 |         Row row(13);
 | 
| 84 |         auto total_time = r->getNonRecTime() + r->getRecTime() + r->getCopyTime();
 | 
| 85 |         row[0] = std::make_shared<Cell<std::chrono::microseconds>>(total_time);
 | 
| 86 |         row[1] = std::make_shared<Cell<std::chrono::microseconds>>(r->getNonRecTime());
 | 
| 87 |         row[2] = std::make_shared<Cell<std::chrono::microseconds>>(r->getRecTime());
 | 
| 88 |         row[3] = std::make_shared<Cell<std::chrono::microseconds>>(r->getCopyTime());
 | 
| 89 |         row[4] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(r->size()));
 | 
| 90 |         row[5] = std::make_shared<Cell<std::string>>(r->getName());
 | 
| 91 |         row[6] = std::make_shared<Cell<std::string>>(r->getId());
 | 
| 92 |         row[7] = std::make_shared<Cell<std::string>>(r->getLocator());
 | 
| 93 |         if (total_time.count() != 0) {
 | 
| 94 |             row[8] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(
 | 
| 95 |                     static_cast<double>(r->size()) / (static_cast<double>(total_time.count()) / 1000000.0)));
 | 
| 96 |         } else {
 | 
| 97 |             row[8] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(r->size()));
 | 
| 98 |         }
 | 
| 99 |         row[9] = std::make_shared<Cell<std::chrono::microseconds>>(r->getLoadtime());
 | 
| 100 |         row[10] = std::make_shared<Cell<std::chrono::microseconds>>(r->getSavetime());
 | 
| 101 |         row[11] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(r->getMaxRSSDiff()));
 | 
| 102 |         row[12] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(r->getReads()));
 | 
| 103 | 
 | 
| 104 |         table.addRow(std::make_shared<Row>(row));
 | 
| 105 |     }
 | 
| 106 |     return table;
 | 
| 107 | }
 | 
| 108 | /*
 | 
| 109 |  * rul table :
 | 
| 110 |  * ROW[0] = TOT_T
 | 
| 111 |  * ROW[1] = NREC_T
 | 
| 112 |  * ROW[2] = REC_T
 | 
| 113 |  * ROW[3] = COPY_T
 | 
| 114 |  * ROW[4] = TUPLES
 | 
| 115 |  * ROW[5] = RUL NAME
 | 
| 116 |  * ROW[6] = ID
 | 
| 117 |  * ROW[7] = SRC
 | 
| 118 |  * ROW[8] = PERFOR
 | 
| 119 |  * ROW[9] = VER
 | 
| 120 |  * ROW[10]= REL_NAME
 | 
| 121 |  */
 | 
| 122 | Table inline OutputProcessor::getRulTable() const {
 | 
| 123 |     const std::unordered_map<std::string, std::shared_ptr<Relation>>& relationMap =
 | 
| 124 |             programRun->getRelationMap();
 | 
| 125 |     std::unordered_map<std::string, std::shared_ptr<Row>> ruleMap;
 | 
| 126 | 
 | 
| 127 |     for (auto& rel : relationMap) {
 | 
| 128 |         for (auto& current : rel.second->getRuleMap()) {
 | 
| 129 |             Row row(11);
 | 
| 130 |             std::shared_ptr<Rule> rule = current.second;
 | 
| 131 |             row[0] = std::make_shared<Cell<std::chrono::microseconds>>(rule->getRuntime());
 | 
| 132 |             row[1] = std::make_shared<Cell<std::chrono::microseconds>>(rule->getRuntime());
 | 
| 133 |             row[2] = std::make_shared<Cell<std::chrono::microseconds>>(std::chrono::microseconds(0));
 | 
| 134 |             row[3] = std::make_shared<Cell<std::chrono::microseconds>>(std::chrono::microseconds(0));
 | 
| 135 |             row[4] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(rule->size()));
 | 
| 136 |             row[5] = std::make_shared<Cell<std::string>>(rule->getName());
 | 
| 137 |             row[6] = std::make_shared<Cell<std::string>>(rule->getId());
 | 
| 138 |             row[7] = std::make_shared<Cell<std::string>>(rel.second->getName());
 | 
| 139 |             row[8] = std::make_shared<Cell<int64_t>>(0);
 | 
| 140 |             row[10] = std::make_shared<Cell<std::string>>(rule->getLocator());
 | 
| 141 |             ruleMap.emplace(rule->getName(), std::make_shared<Row>(row));
 | 
| 142 |         }
 | 
| 143 |         for (auto& iter : rel.second->getIterations()) {
 | 
| 144 |             for (auto& current : iter->getRules()) {
 | 
| 145 |                 std::shared_ptr<Rule> rule = current.second;
 | 
| 146 |                 if (ruleMap.find(rule->getName()) != ruleMap.end()) {
 | 
| 147 |                     Row row = *ruleMap[rule->getName()];
 | 
| 148 |                     row[2] = std::make_shared<Cell<std::chrono::microseconds>>(
 | 
| 149 |                             row[2]->getTimeVal() + rule->getRuntime());
 | 
| 150 |                     row[4] = std::make_shared<Cell<int64_t>>(
 | 
| 151 |                             row[4]->getLongVal() + static_cast<int64_t>(rule->size()));
 | 
| 152 |                     row[0] = std::make_shared<Cell<std::chrono::microseconds>>(
 | 
| 153 |                             row[0]->getTimeVal() + rule->getRuntime());
 | 
| 154 |                     ruleMap[rule->getName()] = std::make_shared<Row>(row);
 | 
| 155 |                 } else {
 | 
| 156 |                     Row row(11);
 | 
| 157 |                     row[0] = std::make_shared<Cell<std::chrono::microseconds>>(rule->getRuntime());
 | 
| 158 |                     row[1] = std::make_shared<Cell<std::chrono::microseconds>>(std::chrono::microseconds(0));
 | 
| 159 |                     row[2] = std::make_shared<Cell<std::chrono::microseconds>>(rule->getRuntime());
 | 
| 160 |                     row[3] = std::make_shared<Cell<std::chrono::microseconds>>(std::chrono::microseconds(0));
 | 
| 161 |                     row[4] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(rule->size()));
 | 
| 162 |                     row[5] = std::make_shared<Cell<std::string>>(rule->getName());
 | 
| 163 |                     row[6] = std::make_shared<Cell<std::string>>(rule->getId());
 | 
| 164 |                     row[7] = std::make_shared<Cell<std::string>>(rel.second->getName());
 | 
| 165 |                     row[8] = std::make_shared<Cell<int64_t>>(rule->getVersion());
 | 
| 166 |                     row[10] = std::make_shared<Cell<std::string>>(rule->getLocator());
 | 
| 167 |                     ruleMap[rule->getName()] = std::make_shared<Row>(row);
 | 
| 168 |                 }
 | 
| 169 |             }
 | 
| 170 |         }
 | 
| 171 |         for (auto& current : ruleMap) {
 | 
| 172 |             std::shared_ptr<Row> row = current.second;
 | 
| 173 |             Row t = *row;
 | 
| 174 |             std::chrono::microseconds val = t[1]->getTimeVal() + t[2]->getTimeVal() + t[3]->getTimeVal();
 | 
| 175 | 
 | 
| 176 |             t[0] = std::make_shared<Cell<std::chrono::microseconds>>(val);
 | 
| 177 | 
 | 
| 178 |             if (t[0]->getTimeVal().count() != 0) {
 | 
| 179 |                 t[9] = std::make_shared<Cell<double>>(t[4]->getLongVal() / (t[0]->getDoubleVal() * 1000));
 | 
| 180 |             } else {
 | 
| 181 |                 t[9] = std::make_shared<Cell<double>>(t[4]->getLongVal() / 1.0);
 | 
| 182 |             }
 | 
| 183 |             current.second = std::make_shared<Row>(t);
 | 
| 184 |         }
 | 
| 185 |     }
 | 
| 186 | 
 | 
| 187 |     Table table;
 | 
| 188 |     for (auto& current : ruleMap) {
 | 
| 189 |         table.addRow(current.second);
 | 
| 190 |     }
 | 
| 191 |     return table;
 | 
| 192 | }
 | 
| 193 | 
 | 
| 194 | /*
 | 
| 195 |  * atom table :
 | 
| 196 |  * ROW[0] = clause
 | 
| 197 |  * ROW[1] = atom
 | 
| 198 |  * ROW[2] = level
 | 
| 199 |  * ROW[3] = frequency
 | 
| 200 |  */
 | 
| 201 | Table inline OutputProcessor::getAtomTable(std::string strRel, std::string strRul) const {
 | 
| 202 |     const std::unordered_map<std::string, std::shared_ptr<Relation>>& relationMap =
 | 
| 203 |             programRun->getRelationMap();
 | 
| 204 | 
 | 
| 205 |     Table table;
 | 
| 206 |     for (auto& current : relationMap) {
 | 
| 207 |         std::shared_ptr<Relation> rel = current.second;
 | 
| 208 | 
 | 
| 209 |         if (rel->getId() != strRel) {
 | 
| 210 |             continue;
 | 
| 211 |         }
 | 
| 212 | 
 | 
| 213 |         for (auto& current : rel->getRuleMap()) {
 | 
| 214 |             std::shared_ptr<Rule> rule = current.second;
 | 
| 215 |             if (rule->getId() != strRul) {
 | 
| 216 |                 continue;
 | 
| 217 |             }
 | 
| 218 |             for (auto& atom : rule->getAtoms()) {
 | 
| 219 |                 Row row(4);
 | 
| 220 |                 row[0] = std::make_shared<Cell<std::string>>(atom.rule);
 | 
| 221 |                 row[1] = std::make_shared<Cell<std::string>>(atom.identifier);
 | 
| 222 |                 row[2] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(atom.level));
 | 
| 223 |                 row[3] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(atom.frequency));
 | 
| 224 | 
 | 
| 225 |                 table.addRow(std::make_shared<Row>(row));
 | 
| 226 |             }
 | 
| 227 |         }
 | 
| 228 |     }
 | 
| 229 |     return table;
 | 
| 230 | }
 | 
| 231 | 
 | 
| 232 | /*
 | 
| 233 |  * subrule table :
 | 
| 234 |  * ROW[0] = subrule
 | 
| 235 |  */
 | 
| 236 | Table inline OutputProcessor::getSubrulTable(std::string strRel, std::string strRul) const {
 | 
| 237 |     const std::unordered_map<std::string, std::shared_ptr<Relation>>& relationMap =
 | 
| 238 |             programRun->getRelationMap();
 | 
| 239 | 
 | 
| 240 |     Table table;
 | 
| 241 |     for (auto& current : relationMap) {
 | 
| 242 |         std::shared_ptr<Relation> rel = current.second;
 | 
| 243 | 
 | 
| 244 |         if (rel->getId() != strRel) {
 | 
| 245 |             continue;
 | 
| 246 |         }
 | 
| 247 | 
 | 
| 248 |         for (auto& current : rel->getRuleMap()) {
 | 
| 249 |             std::shared_ptr<Rule> rule = current.second;
 | 
| 250 |             if (rule->getId() != strRul) {
 | 
| 251 |                 continue;
 | 
| 252 |             }
 | 
| 253 |             for (auto& atom : rule->getAtoms()) {
 | 
| 254 |                 Row row(1);
 | 
| 255 |                 row[0] = std::make_shared<Cell<std::string>>(atom.rule);
 | 
| 256 | 
 | 
| 257 |                 table.addRow(std::make_shared<Row>(row));
 | 
| 258 |             }
 | 
| 259 |         }
 | 
| 260 |     }
 | 
| 261 |     return table;
 | 
| 262 | }
 | 
| 263 | 
 | 
| 264 | /*
 | 
| 265 |  * ver table :
 | 
| 266 |  * ROW[0] = TOT_T
 | 
| 267 |  * ROW[1] = NREC_T
 | 
| 268 |  * ROW[2] = REC_T
 | 
| 269 |  * ROW[3] = COPY_T
 | 
| 270 |  * ROW[4] = TUPLES
 | 
| 271 |  * ROW[5] = RUL NAME
 | 
| 272 |  * ROW[6] = ID
 | 
| 273 |  * ROW[7] = SRC
 | 
| 274 |  * ROW[8] = PERFOR
 | 
| 275 |  * ROW[9] = VER
 | 
| 276 |  * ROW[10]= REL_NAME
 | 
| 277 |  */
 | 
| 278 | Table inline OutputProcessor::getVersions(std::string strRel, std::string strRul) const {
 | 
| 279 |     const std::unordered_map<std::string, std::shared_ptr<Relation>>& relationMap =
 | 
| 280 |             programRun->getRelationMap();
 | 
| 281 |     Table table;
 | 
| 282 | 
 | 
| 283 |     std::shared_ptr<Relation> rel;
 | 
| 284 |     for (auto& current : relationMap) {
 | 
| 285 |         if (current.second->getId() == strRel) {
 | 
| 286 |             rel = current.second;
 | 
| 287 |             break;
 | 
| 288 |         }
 | 
| 289 |     }
 | 
| 290 |     if (rel == nullptr) {
 | 
| 291 |         return table;
 | 
| 292 |     }
 | 
| 293 | 
 | 
| 294 |     std::unordered_map<std::string, std::shared_ptr<Row>> ruleMap;
 | 
| 295 |     for (auto& iter : rel->getIterations()) {
 | 
| 296 |         for (auto& current : iter->getRules()) {
 | 
| 297 |             std::shared_ptr<Rule> rule = current.second;
 | 
| 298 |             if (rule->getId() == strRul) {
 | 
| 299 |                 std::string strTemp =
 | 
| 300 |                         rule->getName() + rule->getLocator() + std::to_string(rule->getVersion());
 | 
| 301 | 
 | 
| 302 |                 if (ruleMap.find(strTemp) != ruleMap.end()) {
 | 
| 303 |                     Row row = *ruleMap[strTemp];
 | 
| 304 |                     row[2] = std::make_shared<Cell<std::chrono::microseconds>>(
 | 
| 305 |                             row[2]->getTimeVal() + rule->getRuntime());
 | 
| 306 |                     row[4] = std::make_shared<Cell<int64_t>>(
 | 
| 307 |                             row[4]->getLongVal() + static_cast<int64_t>(rule->size()));
 | 
| 308 |                     row[0] = std::make_shared<Cell<std::chrono::microseconds>>(rule->getRuntime());
 | 
| 309 |                     ruleMap[strTemp] = std::make_shared<Row>(row);
 | 
| 310 |                 } else {
 | 
| 311 |                     Row row(10);
 | 
| 312 |                     row[1] = std::make_shared<Cell<std::chrono::microseconds>>(std::chrono::microseconds(0));
 | 
| 313 |                     row[2] = std::make_shared<Cell<std::chrono::microseconds>>(rule->getRuntime());
 | 
| 314 |                     row[3] = std::make_shared<Cell<std::chrono::microseconds>>(std::chrono::microseconds(0));
 | 
| 315 |                     row[4] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(rule->size()));
 | 
| 316 |                     row[5] = std::make_shared<Cell<std::string>>(rule->getName());
 | 
| 317 |                     row[6] = std::make_shared<Cell<std::string>>(rule->getId());
 | 
| 318 |                     row[7] = std::make_shared<Cell<std::string>>(rel->getName());
 | 
| 319 |                     row[8] = std::make_shared<Cell<int64_t>>(rule->getVersion());
 | 
| 320 |                     row[9] = std::make_shared<Cell<std::string>>(rule->getLocator());
 | 
| 321 |                     row[0] = std::make_shared<Cell<std::chrono::microseconds>>(rule->getRuntime());
 | 
| 322 |                     ruleMap[strTemp] = std::make_shared<Row>(row);
 | 
| 323 |                 }
 | 
| 324 |             }
 | 
| 325 |         }
 | 
| 326 |     }
 | 
| 327 | 
 | 
| 328 |     for (auto row : ruleMap) {
 | 
| 329 |         Row t = *row.second;
 | 
| 330 |         t[0] = std::make_shared<Cell<std::chrono::microseconds>>(
 | 
| 331 |                 t[1]->getTimeVal() + t[2]->getTimeVal() + t[3]->getTimeVal());
 | 
| 332 |         ruleMap[row.first] = std::make_shared<Row>(t);
 | 
| 333 |     }
 | 
| 334 | 
 | 
| 335 |     for (auto& current : ruleMap) {
 | 
| 336 |         table.addRow(current.second);
 | 
| 337 |     }
 | 
| 338 |     return table;
 | 
| 339 | }
 | 
| 340 | 
 | 
| 341 | /*
 | 
| 342 |  * atom table :
 | 
| 343 |  * ROW[0] = rule
 | 
| 344 |  * ROW[1] = atom
 | 
| 345 |  * ROW[2] = level
 | 
| 346 |  * ROW[3] = frequency
 | 
| 347 |  */
 | 
| 348 | Table inline OutputProcessor::getVersionAtoms(std::string strRel, std::string srcLocator, int version) const {
 | 
| 349 |     const std::unordered_map<std::string, std::shared_ptr<Relation>>& relationMap =
 | 
| 350 |             programRun->getRelationMap();
 | 
| 351 |     Table table;
 | 
| 352 |     std::shared_ptr<Relation> rel;
 | 
| 353 | 
 | 
| 354 |     for (auto& current : relationMap) {
 | 
| 355 |         if (current.second->getId() == strRel) {
 | 
| 356 |             rel = current.second;
 | 
| 357 |             break;
 | 
| 358 |         }
 | 
| 359 |     }
 | 
| 360 |     if (rel == nullptr) {
 | 
| 361 |         return table;
 | 
| 362 |     }
 | 
| 363 | 
 | 
| 364 |     for (auto& iter : rel->getIterations()) {
 | 
| 365 |         for (auto& current : iter->getRules()) {
 | 
| 366 |             std::shared_ptr<Rule> rule = current.second;
 | 
| 367 |             if (rule->getLocator() == srcLocator && rule->getVersion() == version) {
 | 
| 368 |                 for (auto& atom : rule->getAtoms()) {
 | 
| 369 |                     Row row(4);
 | 
| 370 |                     row[0] = std::make_shared<Cell<std::string>>(atom.rule);
 | 
| 371 |                     row[1] = std::make_shared<Cell<std::string>>(atom.identifier);
 | 
| 372 |                     row[2] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(atom.level));
 | 
| 373 |                     row[3] = std::make_shared<Cell<int64_t>>(static_cast<int64_t>(atom.frequency));
 | 
| 374 |                     table.addRow(std::make_shared<Row>(row));
 | 
| 375 |                 }
 | 
| 376 |             }
 | 
| 377 |         }
 | 
| 378 |     }
 | 
| 379 | 
 | 
| 380 |     return table;
 | 
| 381 | }
 | 
| 382 | 
 | 
| 383 | }  // namespace profile
 | 
| 384 | }  // namespace souffle
 |