Hedgehog  0.0.0
A library to generate hybrid pipeline workflow systems
dot_printer.h
1 // NIST-developed software is provided by NIST as a public service. You may use, copy and distribute copies of the
2 // software in any medium, provided that you keep intact this entire notice. You may improve, modify and create
3 // derivative works of the software or any portion of the software, and you may copy and distribute such modifications
4 // or works. Modified works should carry a notice stating that you changed the software and should note the date and
5 // nature of any such change. Please explicitly acknowledge the National Institute of Standards and Technology as the
6 // source of the software. NIST-developed software is expressly provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND,
7 // EXPRESS, IMPLIED, IN FACT OR ARISING BY OPERATION OF LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
8 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT AND DATA ACCURACY. NIST NEITHER REPRESENTS NOR
9 // WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE
10 // CORRECTED. NIST DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE SOFTWARE OR THE RESULTS
11 // THEREOF, INCLUDING BUT NOT LIMITED TO THE CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE. You
12 // are solely responsible for determining the appropriateness of using and distributing the software and you assume
13 // all risks associated with its use, including but not limited to the risks and costs of program errors, compliance
14 // with applicable laws, damage to or loss of data, programs or equipment, and the unavailability or interruption of
15 // operation. This software is not intended to be used in any situation where a failure could cause risk of injury or
16 // damage to property. The software developed by NIST employees is not subject to copyright protection within the
17 // United States.
18 
19 
20 #ifndef HEDGEHOG_DOT_PRINTER_H
21 #define HEDGEHOG_DOT_PRINTER_H
22 
23 #include <filesystem>
24 #include <fstream>
25 #include <string>
26 #include <vector>
27 #include <iostream>
28 #include <iomanip>
29 #include <iterator>
30 
31 #include "abstract_printer.h"
32 #include "../../core/io/base/receiver/core_slot.h"
33 
35 namespace hh {
37 enum class ColorScheme {
38  NONE,
39  EXECUTION,
40  WAIT
41 };
42 
44 enum class StructureOptions {
45  NONE,
46  ALLTHREADING,
47  QUEUE,
48  ALL
49 };
50 
52 enum class DebugOptions {
53  NONE,
54  DEBUG
55 };
56 
59 class DotPrinter : public AbstractPrinter {
60  private:
61  std::vector<std::string> edges_ = {};
62  std::ofstream outputFile_ = {};
63 
64  ColorScheme colorScheme_ = {};
65  StructureOptions structureOptions_ = {};
66  DebugOptions debugOptions_ = {};
67 
68  uint64_t
69  maxExecutionTime_ = {},
70  minExecutionTime_ = {},
71  rangeExecutionTime_ = {},
72  maxWaitTime_ = {},
73  minWaitTime_ = {},
74  rangeWaitTime_ = {},
75  graphExecutionDuration_ = {};
76 
77  public:
84  explicit DotPrinter(std::filesystem::path const &dotFilePath,
85  ColorScheme colorScheme, StructureOptions structureOptions, DebugOptions debugOptions,
86  core::CoreNode *graph)
87  : AbstractPrinter(), edges_({}),
88  colorScheme_(colorScheme), structureOptions_(structureOptions), debugOptions_(debugOptions) {
89  assert(graph != nullptr);
90  auto directoryPath = dotFilePath.parent_path();
91  if (dotFilePath.has_filename()) {
92  if (std::filesystem::exists(directoryPath)) {
93  if (std::filesystem::exists(dotFilePath)) {
94  std::cout
95  << "The file " << dotFilePath.filename() << " will be overwritten." << std::endl;
96  } else {
97  std::cout
98  << "The file " << dotFilePath.filename() << " will be created." << std::endl;
99  }
100  outputFile_ = std::ofstream(dotFilePath);
101 
102  } else {
103  std::ostringstream oss;
104  oss << "The file " << dotFilePath.filename() << " can not be store in " << directoryPath
105  << " because the directory does not exist.";
106  HLOG_SELF(0, oss.str())
107  throw (std::runtime_error(oss.str()));
108  }
109  } else {
110  std::ostringstream oss;
111  oss << "The path: " << dotFilePath << " does not represent a file.";
112  HLOG_SELF(0, oss.str())
113  throw (std::runtime_error(oss.str()));
114  }
115  minExecutionTime_ = graph->minExecutionTime().count();
116  maxExecutionTime_ = graph->maxExecutionTime().count();
117  minWaitTime_ = graph->minWaitTime().count();
118  maxWaitTime_ = graph->maxWaitTime().count();
119  // Compute range
120  rangeExecutionTime_ = ((maxExecutionTime_ - minExecutionTime_) == 0 ? 1 : maxExecutionTime_ - minExecutionTime_);
121  rangeWaitTime_ = ((maxWaitTime_ - minWaitTime_) == 0 ? 1 : maxWaitTime_ - minWaitTime_);
122  graphExecutionDuration_ =
123  graph->executionDuration().count() == 0 ?
124  std::chrono::duration_cast<std::chrono::microseconds>(
125  std::chrono::high_resolution_clock::now() - graph->startExecutionTimeStamp()).count()
126  : graph->executionDuration().count();
127  }
128 
130  ~DotPrinter() override { outputFile_.close(); }
131 
135  // If the node is not a graph
136  if (node->type() != core::NodeType::Graph) {
137  //If all cluster node to be printed
138  if (this->structureOptions_ == StructureOptions::ALL
139  || this->structureOptions_ == StructureOptions::ALLTHREADING) {
140  // Get and print the node information
141  outputFile_ << getNodeInformation(node);
142  // If only one node per cluster need to be printed with gathered information
143  } else {
144  // If the node is the cluster main node
145  if (node->id() == node->coreClusterNode()->id()) {
146  // Get and print the node information
147  outputFile_ << getNodeInformation(node);
148  }
149  }
150  }
151  outputFile_.flush();
152  }
153 
156  void printGraphHeader(core::CoreNode const *node) final {
157  // If the graph is the outer graph, i.e. the main graph
158  if (!node->isInside()) {
159  outputFile_
160  << "digraph " << node->id()
161  << " {\nlabel=\"" << node->name();
162  if (debugOptions_ == DebugOptions::DEBUG) {
163  outputFile_ << " " << node->id();
164  }
165  outputFile_ << "\\nExecution time:" << this->durationPrinter(this->graphExecutionDuration_)
166  << "\\nCreation time:" << this->durationPrinter(node->creationDuration().count())
167  << "\"; fontsize=25; penwidth=5; ranksep=0; labelloc=top; labeljust=left; \n";
168  // If the graph is an inner graph, i.e. a node of the outer graph
169  } else {
170  outputFile_ << "subgraph cluster" << node->id() << " {\nlabel=\"" << node->name();
171  if (debugOptions_ == DebugOptions::DEBUG) {
172  outputFile_ << " " << node->id();
173  }
174  outputFile_ << "\"; fontsize=25; penwidth=5; fillcolor=white;\n";
175  }
176  outputFile_.flush();
177  }
178 
181  void printClusterHeader(core::CoreNode const *clusterNode) final {
182  //If all cluster node to be printed
183  if (this->structureOptions_ == StructureOptions::ALLTHREADING || this->structureOptions_ == StructureOptions::ALL) {
184  // Create a dot subgraph for the task cluster
185  outputFile_ << "subgraph cluster" << clusterNode->id()
186  << " {\nlabel=\"\"; penwidth=3; style=filled; fillcolor=\"#4e78cf63\"; color=\"#4e78cf\";\n";
187  // Add an "egg" node to represent the entry point of cluster
188  outputFile_ << "box" << clusterNode->id() << "[label=\"\", shape=egg];\n";
189  outputFile_.flush();
190  }
191  }
192 
194  void printClusterFooter() final {
195  //If all cluster node to be printed
196  if (this->structureOptions_ == StructureOptions::ALLTHREADING || this->structureOptions_ == StructureOptions::ALL) {
197  // Close the subgraph
198  outputFile_ << "}\n";
199  outputFile_.flush();
200  }
201  }
202 
205  void printGraphFooter(core::CoreNode const *graph) final {
206  // If the graph is the outer graph
207  if (!graph->isInside()) {
208  // Print all the stored edges
209  std::copy(edges_.begin(), edges_.end(), std::ostream_iterator<std::string>(outputFile_, "\n"));
210  }
211  // Close the dot subgraph
212  outputFile_ << "}\n";
213  outputFile_.flush();
214  }
215 
218  void printClusterEdge(core::CoreNode const *clusterNode) final {
219  //If all cluster node to be printed
220  if (this->structureOptions_ == StructureOptions::ALLTHREADING || this->structureOptions_ == StructureOptions::ALL) {
221  // Print an edge from the cluster "egg" node to the task
222  std::ostringstream ss;
223  ss << "box" << clusterNode->coreClusterNode()->id() << " -> " << clusterNode->id();
224  edges_.push_back(ss.str());
225  }
226  }
227 
231  void printExecutionPipelineHeader(core::CoreNode *epNode, core::CoreNode *switchNode) override {
232  //Print the dot subgraph header
233  outputFile_ << "subgraph cluster" << epNode->id() << " {\nlabel=\"" << epNode->name();
234  if (debugOptions_ == DebugOptions::DEBUG) { outputFile_ << " " << epNode->id() << " / " << switchNode->id(); }
235  // Print a "triangle" node to represent the execution pipeline switch
236  outputFile_ << "\"; penwidth=1; style=dotted; style=filled; fillcolor=gray80;\n "
237  << switchNode->id() << "[label=\"\", shape=triangle];\n";
238  outputFile_.flush();
239  }
240 
243  outputFile_ << "}\n";
244  outputFile_.flush();
245  }
246 
255  std::string const &idSwitch,
256  std::string_view const &edgeType,
257  size_t const &queueSize,
258  size_t const &maxQueueSize,
259  bool isMemoryManaged) override {
260  std::ostringstream
261  oss;
262 
263  std::string
264  idDest,
265  headLabel,
266  penWidth = ",penwidth=1",
267  queueStr;
268 
269 
270 
271  // If the queue information need to be printed
272  if (this->structureOptions_ == StructureOptions::QUEUE || this->structureOptions_ == StructureOptions::ALL) {
273  oss << " QS:" << queueSize << " MQS:" << maxQueueSize;
274  queueStr = oss.str();
275  oss.str("");
276  }
277 
278  // Change the width of the edge if the data is memory managed
279  if (isMemoryManaged) { penWidth = ",penwidth=3"; }
280 
281  // If all nodes in a cluster need to be printed
282  if (this->structureOptions_ == StructureOptions::ALLTHREADING || this->structureOptions_ == StructureOptions::ALL) {
283  // If the node is part of a cluster
284  if (to->isInCluster()) {
285  // Loop over all input node of the current node
286  // (could be simply itself or, all input nodes in the case of graph)
287  for (auto &dest: to->ids()) {
288  // Create cluster id (dest.first is the input node, dest.second is the reference to the cluster main node)
289  idDest = "box" + dest.second;
290  // Create the edge
291  oss << idSwitch << " -> " << idDest << "[label=\"" << edgeType << queueStr << "\""
292  << penWidth << "];";
293  }
294  // If the node is not part of a cluster
295  } else {
296  // Crete the edge
297  oss << idSwitch << " -> " << to->id() << "[label=\"" << edgeType << queueStr << "\"" << penWidth << "];";
298  }
299  // If all nodes should not be printed but node is the main cluster node
300  } else if (to->id() == to->coreClusterNode()->id()) {
301  // Create the edge
302  oss << idSwitch << " -> " << to->id() << "[label=\"" << edgeType << queueStr << "\"" << penWidth << "];";
303  }
304  edges_.push_back(oss.str());
305  }
306 
314  void printEdge(core::CoreNode const *from, core::CoreNode const *to, std::string_view const &edgeType,
315  size_t const &queueSize, size_t const &maxQueueSize,
316  bool isMemoryManaged) final {
317  std::ostringstream
318  oss;
319 
320  std::string
321  headLabel,
322  tailLabel,
323  idDest,
324  queueStr,
325  penWidth = ",penwidth=1";
326 
327  // Change the width of the edge if the data is memory managed
328  if (isMemoryManaged) { penWidth = ",penwidth=3"; }
329 
330  // If the queue information need to be printed, add queue information
331  if (this->structureOptions_ == StructureOptions::QUEUE || this->structureOptions_ == StructureOptions::ALL) {
332  oss << " QS:" << queueSize << " MQS:" << maxQueueSize;
333  queueStr = oss.str();
334  oss.str("");
335  }
336 
337  // If all nodes in a cluster need to be printed
338  if (this->structureOptions_ == StructureOptions::ALLTHREADING || this->structureOptions_ == StructureOptions::ALL) {
339  // If the source node is in a cluster
340  if (from->isInCluster()) {
341  // Loop over all source node of the current node
342  // (could be simply itself or, all input nodes in the case of graph)
343  for (auto &source: from->ids()) {
344  headLabel = ",ltail=cluster" + source.second;
345  // If the destination node is in a cluster
346  if (to->isInCluster()) {
347  // Loop over all destination node of the current node
348  // (could be simply itself or, all input nodes in the case of graph)
349  for (auto &dest : to->ids()) {
350  tailLabel = ",lhead=cluster" + dest.second;
351  idDest = "box" + dest.second;
352  oss << source.first << " -> " << idDest << "[label=\"" << edgeType << queueStr << "\"" << headLabel
353  << tailLabel << penWidth << "];";
354  }
355  // If the destination node is NOT in a cluster
356  } else {
357  oss << source.first << " -> " << to->id() << "[label=\"" << edgeType << queueStr << "\"" << headLabel
358  << penWidth
359  << "];";
360  }
361  }
362  // If the source node is NOT in a cluster
363  } else {
364  // If the destination node is in a cluster
365  if (to->isInCluster()) {
366  // Loop over all destination node of the current node
367  // (could be simply itself or, all input nodes in the case of graph)
368  for (auto &dest : to->ids()) {
369  tailLabel = ",lhead=cluster" + dest.second;
370  idDest = "box" + dest.second;
371  oss << from->id() << " -> " << idDest << "[label=\"" << edgeType << queueStr << "\"" << headLabel
372  << tailLabel << penWidth << "];";
373  }
374  // If the destination node is NOT in a cluster
375  } else {
376  oss << from->id() << " -> " << to->id() << "[label=\"" << edgeType << queueStr << "\"" << headLabel
377  << penWidth
378  << "];";
379  }
380  }
381  edges_.push_back(oss.str());
382  // If all nodes should NOT be printed and, from and to are the main nodes of their cluster
383  } else if (from->id() == from->coreClusterNode()->id() && to->id() == to->coreClusterNode()->id()) {
384  oss << from->id() << " -> " << to->id() << "[label=\"" << edgeType << queueStr << "\"" << penWidth << "];";
385  edges_.push_back(oss.str());
386  }
387  }
388 
389  private:
393  std::string getNodeInformation(core::CoreNode *node) {
394  std::stringstream ss;
395 
396  // Print the name
397  ss << node->id() << " [label=\"" << node->name();
398  // Print the id (adress) in case of debug
399  if (debugOptions_ == DebugOptions::DEBUG) {
400  ss << " " << node->id() << " \\(" << node->threadId() << ", " << node->graphId() << "\\)";
401  }
402 
403  switch (node->type()) {
404  // Set a specific shape for the source
405  case core::NodeType::Source:ss << "\", shape=doublecircle";
406  break;
407  // Set a specific shape for the sink
408  case core::NodeType::Sink:ss << "\",shape=point";
409  break;
410  // For the execution task
411  case core::NodeType::Task:
412  // If the cluster has to be presented as a single dot node
413  if (!(this->structureOptions_ == StructureOptions::ALLTHREADING
414  || this->structureOptions_ == StructureOptions::ALL)) {
415  if(node->isInCluster()){
416  ss << " x " << node->numberThreads();
417  }
418  }
419  // If debug information printed
420  if (debugOptions_ == DebugOptions::DEBUG) {
421  // Print number of active input connection
422  ss << "\\nActive input connection: " << dynamic_cast<core::CoreSlot *>(node)->numberInputNodes();
423  // If all nodes in a cluster need to be printed
424  if (this->structureOptions_ == StructureOptions::ALLTHREADING
425  || this->structureOptions_ == StructureOptions::ALL) {
426  ss << "\\nThread Active?: " << std::boolalpha << dynamic_cast<core::CoreSlot *>(node)->isActive();
427  // If all nodes in a cluster should NOT be printed
428  } else {
429  ss << "\\nActive threads: " << dynamic_cast<core::CoreSlot *>(node)->numberActiveThreadInCluster();
430  }
431  }
432  // If all nodes in a cluster need to be printed
433  if (this->structureOptions_ == StructureOptions::ALLTHREADING
434  || this->structureOptions_ == StructureOptions::ALL) {
435  ss << "\\nWait Time: " << this->durationPrinter(node->waitTime().count());
436  ss << "\\nExecution Time: " << this->durationPrinter(node->executionTime().count());
437  ss << "\\nMemory Wait Time: " << this->durationPrinter(node->memoryWaitTime().count());
438  // If all nodes in a cluster should NOT be printed
439  } else {
440  //Get the time in the clusters
441  auto minmaxWait = node->minmaxWaitTimeCluster();
442  auto minmaxExec = node->minmaxExecTimeCluster();
443  auto minmaxMemoryWait = node->minmaxMemoryWaitTimeCluster();
444  // Print the wait time
445  ss << "\\nWait Time: ";
446  if (node->numberThreads() > 1) {
447  ss << "\\n"
448  << " Min: " << this->durationPrinter(minmaxWait.first) << "\\n"
449  << " Avg: " << this->durationPrinter(node->meanWaitTimeCluster().count()) << " +- "
450  << this->durationPrinter(node->stdvWaitTimeCluster()) << "\\n"
451  << " Max: " << this->durationPrinter(minmaxWait.second) << "\\n\\n";
452  } else {
453  ss << this->durationPrinter(node->meanWaitTimeCluster().count()) << "\\n";
454  }
455  // Print the execution time
456  ss << "Execution Time: ";
457  if (node->numberThreads() > 1) {
458  ss << "\\n"
459  << " Min: " << this->durationPrinter(minmaxExec.first) << "\\n"
460  << " Avg: " << this->durationPrinter(node->meanExecTimeCluster().count()) << " +- "
461  << this->durationPrinter(node->stdvExecTimeCluster()) << "\\n"
462  << " Max: " << this->durationPrinter(minmaxExec.second) << "\\n\\n";
463  } else {
464  ss << this->durationPrinter(node->meanExecTimeCluster().count()) << "\\n";
465  }
466 
467  // Print the memory wait time
468  if (node->meanMemoryWaitTimeCluster().count() > 0) {
469  ss << "Memory Wait Time: ";
470  if (node->numberThreads() > 1) {
471  ss << "\\n"
472  << " Min: " << this->durationPrinter(minmaxMemoryWait.first) << "\\n"
473  << " Avg: " << this->durationPrinter(node->meanMemoryWaitTimeCluster().count()) << " +-"
474  << this->durationPrinter(node->stdvMemoryWaitTimeCluster()) << "\\n"
475  << " Max: " << this->durationPrinter(minmaxMemoryWait.second) << "\\n\\n";
476  } else {
477  ss << this->durationPrinter(node->meanMemoryWaitTimeCluster().count()) << "\\n";
478  }
479  }
480  }
481  // If extra information has been defined by the user, print it
482  if (!node->extraPrintingInformation().empty()) {
483  ss << "\\n" << node->extraPrintingInformation();
484  }
485  ss << "\"";
486  ss << ",shape=circle";
487  // Change the color of the circle depending on the user choice
488  switch (this->colorScheme_) {
489  case ColorScheme::EXECUTION:ss << ",color=" << this->getExecRGB(node->executionTime().count()) << ", penwidth=3";
490  break;
491  case ColorScheme::WAIT:ss << ",color=" << this->getWaitRGB(node->waitTime().count()) << ", penwidth=3";
492  break;
493  default:break;
494  }
495 
496  if (node->isCudaRelated()) { ss << R"(, style=filled, fillcolor="#76b900", fontcolor="#8946ff")"; }
497  break;
498  // Print state manager
499  case core::NodeType::StateManager:
500  if (debugOptions_ == DebugOptions::DEBUG) {
501  ss << "\\nActive input connection: " << dynamic_cast<core::CoreSlot *>(node)->numberInputNodes();
502  ss << "\\nActive threads: " << dynamic_cast<core::CoreSlot *>(node)->numberActiveThreadInCluster();
503  }
504  ss << "\\nWait Time: " << this->durationPrinter(node->waitTime().count());
505  ss << "\\nExecution Time: " << this->durationPrinter(node->executionTime().count());
506  ss << "\"";
507  ss << ",shape=diamond";
508  // Change the color of the circle depending on the user choice
509  switch (this->colorScheme_) {
510  case ColorScheme::EXECUTION:ss << ",color=" << this->getExecRGB(node->executionTime().count()) << ", penwidth=3";
511  break;
512  case ColorScheme::WAIT:ss << ",color=" << this->getWaitRGB(node->waitTime().count()) << ", penwidth=3";
513  break;
514  default:break;
515  }
516  break;
517  default:break;
518  }
519  ss << "];\n";
520 
521  return ss.str();
522  }
523 
529  std::string getRGBFromRange(uint64_t const &val, uint64_t const &min, uint64_t const &range) {
530 
531  uint64_t posRedToBlue = (std::abs((int64_t) val - (int64_t) min)) * 255 / range;
532  posRedToBlue = posRedToBlue > 255 ? 255 : posRedToBlue;
533  std::stringstream ss;
534  ss << "\"#"
535  << std::setfill('0') << std::setw(2) << std::hex << posRedToBlue
536  << "00"
537  << std::setfill('0') << std::setw(2) << std::hex << 255 - posRedToBlue
538  << "\"";
539 
540  HLOG(0, "PRINT RGB RANGE " << val << " " << min << " " << range << " " << posRedToBlue)
541  return ss.str();
542  }
543 
547  std::string getExecRGB(uint64_t val) {
548  return getRGBFromRange(val, this->minExecutionTime_, this->rangeExecutionTime_);
549  }
550 
554  std::string getWaitRGB(uint64_t val) {
555  return getRGBFromRange(val, this->minWaitTime_, this->rangeWaitTime_);
556  }
557 
561  std::string durationPrinter(uint64_t duration) {
562  std::ostringstream oss;
563  uint64_t
564  s = (duration % 1000000000) / 1000000,
565  mS = (duration % 1000000) / 1000,
566  uS = (duration % 1000);
567 
568  if (s > 0) {
569  oss << s << "." << std::setfill('0') << std::setw(3) << mS << "s";
570  } else if (mS > 0) {
571  oss << mS << "." << std::setfill('0') << std::setw(3) << uS << "ms";
572  } else {
573  oss << duration << "us";
574  }
575  return oss.str();
576  }
577 };
578 }
579 #endif //HEDGEHOG_DOT_PRINTER_H
NodeType type() const
Node type accessor.
Definition: core_node.h:132
std::pair< uint64_t, uint64_t > minmaxWaitTimeCluster() const
Compute and return the min and max wait time for all tasks in the node cluster.
Definition: core_node.h:343
std::chrono::duration< uint64_t, std::micro > meanMemoryWaitTimeCluster() const
Compute and return the mean memory wait time for all tasks in the node cluster.
Definition: core_node.h:280
std::string durationPrinter(uint64_t duration)
Print a duration with the good unit.
Definition: dot_printer.h:561
void printGraphFooter(core::CoreNode const *graph) final
Print the graph footer.
Definition: dot_printer.h:205
void printClusterEdge(core::CoreNode const *clusterNode) final
Print the inside edges of a cluster for a task.
Definition: dot_printer.h:218
std::pair< uint64_t, uint64_t > minmaxMemoryWaitTimeCluster() const
Compute and return the min and max memory wait time for all tasks in the node cluster.
Definition: core_node.h:363
virtual std::string extraPrintingInformation()
Extra printing information accessor.
Definition: core_node.h:419
bool isCudaRelated() const
Is related to CUDA, used to have a green background on the dot file.
Definition: core_node.h:195
Printer to produce a dot representation of the current state of the graph.
Definition: dot_printer.h:59
void printEdge(core::CoreNode const *from, core::CoreNode const *to, std::string_view const &edgeType, size_t const &queueSize, size_t const &maxQueueSize, bool isMemoryManaged) final
Create an edge between from and to.
Definition: dot_printer.h:314
Displays all tasks in clusters.
void printGraphHeader(core::CoreNode const *node) final
Print header for the graph.
Definition: dot_printer.h:156
std::string getWaitRGB(uint64_t val)
Get the rgb color for the wait time value.
Definition: dot_printer.h:554
StructureOptions
Enum structural options.
Definition: dot_printer.h:44
DotPrinter(std::filesystem::path const &dotFilePath, ColorScheme colorScheme, StructureOptions structureOptions, DebugOptions debugOptions, core::CoreNode *graph)
DotPrinter constructor, opens the file for writing.
Definition: dot_printer.h:84
std::chrono::duration< uint64_t, std::micro > meanExecTimeCluster() const
Compute and return the mean execution time for all tasks in the node cluster.
Definition: core_node.h:250
Hedgehog main namespace.
uint64_t stdvMemoryWaitTimeCluster() const
Compute and return the standard deviation memory wait time for all tasks in the node cluster...
Definition: core_node.h:327
DebugOptions
Enum to enable debug printing.
Definition: dot_printer.h:52
void printExecutionPipelineFooter() override
Print the footer for the execution pipeline.
Definition: dot_printer.h:242
Printer interface.
Colors nodes based on execution time.
void printNodeInformation(core::CoreNode *node) final
Print node main information.
Definition: dot_printer.h:134
Slot interface, receive notification from CoreNotifier.
Definition: core_slot.h:34
Displays both ALLTHREADING and QUEUE.
int threadId() const
Thread id accessor.
Definition: core_node.h:148
virtual int graphId()
Graph id accessor.
Definition: core_node.h:199
Shows debug information such as pointer addresses for nodes and edges.
uint64_t stdvWaitTimeCluster() const
Compute and return the standard deviation wait time for all tasks in the node cluster.
Definition: core_node.h:311
std::pair< uint64_t, uint64_t > minmaxExecTimeCluster() const
Compute and return the min and max execution time for all tasks in the node cluster.
Definition: core_node.h:383
void printEdgeSwitchGraphs(core::CoreNode *to, std::string const &idSwitch, std::string_view const &edgeType, size_t const &queueSize, size_t const &maxQueueSize, bool isMemoryManaged) override
Print an edge between the switch and a graph&#39;s input node.
Definition: dot_printer.h:254
CoreNode * coreClusterNode() const
Main cluster core node link to this node accessor.
Definition: core_node.h:144
std::string getRGBFromRange(uint64_t const &val, uint64_t const &min, uint64_t const &range)
Return a RGB color for a value knowing the minimum value and the range, blue least, red highest.
Definition: dot_printer.h:529
Main Hedgehog core abstraction.
Definition: core_node.h:48
uint64_t stdvExecTimeCluster() const
Compute and return the standard deviation execution time for all tasks in the node cluster...
Definition: core_node.h:295
void printExecutionPipelineHeader(core::CoreNode *epNode, core::CoreNode *switchNode) override
Print the execution pipeline header.
Definition: dot_printer.h:231
std::chrono::duration< uint64_t, std::micro > meanWaitTimeCluster() const
Compute and return the mean wait time for all tasks in the node cluster.
Definition: core_node.h:265
bool isInCluster() const
In cluster property accessor.
Definition: core_node.h:187
~DotPrinter() override
Destructor, close the file.
Definition: dot_printer.h:130
std::string_view const & name() const
Node name accessor.
Definition: core_node.h:128
std::chrono::duration< uint64_t, std::micro > const & memoryWaitTime() const
Memory wait time accessor.
Definition: core_node.h:181
Displays queue details (max queue size and queue size along edges)
size_t numberThreads() const
Number of threads associated accessor.
Definition: core_node.h:152
void printClusterHeader(core::CoreNode const *clusterNode) final
Print the header of a cluster.
Definition: dot_printer.h:181
No added coloration.
ColorScheme
Enum color options.
Definition: dot_printer.h:37
std::string getExecRGB(uint64_t val)
Get the rgb color for the execution time value.
Definition: dot_printer.h:547
void printClusterFooter() final
Print the footer of a task cluster.
Definition: dot_printer.h:194
std::chrono::duration< uint64_t, std::micro > const & executionTime() const
Execution time accessor.
Definition: core_node.h:173
Colors nodes based on wait time.
virtual std::vector< std::pair< std::string, std::string > > ids() const
Input node ids [nodeId, nodeIdCluster] accessor.
Definition: core_node.h:122
virtual std::string id() const
Unique Id accessor.
Definition: core_node.h:114
std::chrono::duration< uint64_t, std::micro > const & waitTime() const
Wait time accessor.
Definition: core_node.h:177
std::string getNodeInformation(core::CoreNode *node)
Extract and create node information.
Definition: dot_printer.h:393