Blender  V2.93
deg_debug_stats_gnuplot.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2017 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "DEG_depsgraph_debug.h"
25 
26 #include <algorithm>
27 #include <cstdarg>
28 
29 #include "BLI_compiler_attrs.h"
30 #include "BLI_math_base.h"
31 
32 #include "intern/depsgraph.h"
34 
35 #include "DNA_ID.h"
36 
37 #define NL "\r\n"
38 
39 namespace deg = blender::deg;
40 
41 namespace blender::deg {
42 namespace {
43 
44 struct DebugContext {
45  FILE *file;
46  const Depsgraph *graph;
47  const char *label;
48  const char *output_filename;
49 };
50 
51 struct StatsEntry {
52  const IDNode *id_node;
53  double time;
54 };
55 
56 /* TODO(sergey): De-duplicate with graphviz relation debugger. */
57 void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...) ATTR_PRINTF_FORMAT(2, 3);
58 void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
59 {
60  va_list args;
61  va_start(args, fmt);
62  vfprintf(ctx.file, fmt, args);
63  va_end(args);
64 }
65 
66 inline double get_node_time(const DebugContext & /*ctx*/, const Node *node)
67 {
68  /* TODO(sergey): Figure out a nice way to define which exact time
69  * we want to show. */
70  return node->stats.current_time;
71 }
72 
73 bool stat_entry_comparator(const StatsEntry &a, const StatsEntry &b)
74 {
75  return a.time > b.time;
76 }
77 
78 string gnuplotify_id_code(const string &name)
79 {
80  return string("") + name[0] + name[1];
81 }
82 
83 string gnuplotify_name(const string &name)
84 {
85  string result;
86  const int length = name.length();
87  for (int i = 0; i < length; i++) {
88  const char ch = name[i];
89  if (ch == '_') {
90  result += R"(\\\)";
91  }
92  result += ch;
93  }
94  return result;
95 }
96 
97 void write_stats_data(const DebugContext &ctx)
98 {
99  /* Fill in array of all stats which are to be displayed. */
100  Vector<StatsEntry> stats;
101  stats.reserve(ctx.graph->id_nodes.size());
102  for (const IDNode *id_node : ctx.graph->id_nodes) {
103  const double time = get_node_time(ctx, id_node);
104  if (time == 0.0) {
105  continue;
106  }
107  StatsEntry entry;
108  entry.id_node = id_node;
109  entry.time = time;
110  stats.append(entry);
111  }
112  /* Sort the data. */
113  std::sort(stats.begin(), stats.end(), stat_entry_comparator);
114  /* We limit number of entries, otherwise things become unreadable. */
115  stats.resize(min_ii(stats.size(), 32));
116  std::reverse(stats.begin(), stats.end());
117  /* Print data to the file stream. */
118  deg_debug_fprintf(ctx, "$data << EOD" NL);
119  for (const StatsEntry &entry : stats) {
120  deg_debug_fprintf(ctx,
121  "\"[%s] %s\",%f" NL,
122  gnuplotify_id_code(entry.id_node->id_orig->name).c_str(),
123  gnuplotify_name(entry.id_node->id_orig->name + 2).c_str(),
124  entry.time);
125  }
126  deg_debug_fprintf(ctx, "EOD" NL);
127 }
128 
129 void deg_debug_stats_gnuplot(const DebugContext &ctx)
130 {
131  /* Data itself. */
132  write_stats_data(ctx);
133  /* Optional label. */
134  if (ctx.label && ctx.label[0]) {
135  deg_debug_fprintf(ctx, "set title \"%s\"" NL, ctx.label);
136  }
137  /* Rest of the commands.
138  * TODO(sergey): Need to decide on the resolution somehow. */
139  deg_debug_fprintf(ctx, "set terminal pngcairo size 1920,1080" NL);
140  deg_debug_fprintf(ctx, "set output \"%s\"" NL, ctx.output_filename);
141  deg_debug_fprintf(ctx, "set grid" NL);
142  deg_debug_fprintf(ctx, "set datafile separator ','" NL);
143  deg_debug_fprintf(ctx, "set style fill solid" NL);
144  deg_debug_fprintf(ctx,
145  "plot \"$data\" using "
146  "($2*0.5):0:($2*0.5):(0.2):yticlabels(1) "
147  "with boxxyerrorbars t '' lt rgb \"#406090\"" NL);
148 }
149 
150 } // namespace
151 } // namespace blender::deg
152 
154  FILE *fp,
155  const char *label,
156  const char *output_filename)
157 {
158  if (depsgraph == nullptr) {
159  return;
160  }
161  deg::DebugContext ctx;
162  ctx.file = fp;
163  ctx.graph = (deg::Depsgraph *)depsgraph;
164  ctx.label = label;
165  ctx.output_filename = output_filename;
166  deg::deg_debug_stats_gnuplot(ctx);
167 }
MINLINE int min_ii(int a, int b)
size_t ATTR_PRINTF_FORMAT(3, 4)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
ID and Library types, which are fundamental for sdna.
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
OperationNode * node
void DEG_debug_stats_gnuplot(const Depsgraph *depsgraph, FILE *fp, const char *label, const char *output_filename)
#define NL
FILE * file
const IDNode * id_node
const Depsgraph * graph
const char * output_filename
double time
const char * label
const Depsgraph * depsgraph
static unsigned a[3]
Definition: RandGen.cpp:92
Definition: node.h:98