Blender V4.3
deg_debug_stats_gnuplot.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2017 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <algorithm>
12#include <cstdarg>
13
14#include "BLI_compiler_attrs.h"
15#include "BLI_math_base.h"
16
17#include "intern/depsgraph.hh"
19
20#include "DNA_ID.h"
21
22#define NL "\r\n"
23
24namespace deg = blender::deg;
25
26namespace blender::deg {
27namespace {
28
29struct DebugContext {
30 FILE *file;
31 const Depsgraph *graph;
32 const char *label;
33 const char *output_filename;
34};
35
36struct StatsEntry {
37 const IDNode *id_node;
38 double time;
39};
40
41/* TODO(sergey): De-duplicate with graphviz relation debugger. */
42void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...) ATTR_PRINTF_FORMAT(2, 3);
43void deg_debug_fprintf(const DebugContext &ctx, const char *fmt, ...)
44{
45 va_list args;
46 va_start(args, fmt);
47 vfprintf(ctx.file, fmt, args);
48 va_end(args);
49}
50
51inline double get_node_time(const DebugContext & /*ctx*/, const Node *node)
52{
53 /* TODO(sergey): Figure out a nice way to define which exact time
54 * we want to show. */
55 return node->stats.current_time;
56}
57
58bool stat_entry_comparator(const StatsEntry &a, const StatsEntry &b)
59{
60 return a.time > b.time;
61}
62
63string gnuplotify_id_code(const string &name)
64{
65 return string("") + name[0] + name[1];
66}
67
68string gnuplotify_name(const string &name)
69{
70 string result;
71 const int length = name.length();
72 for (int i = 0; i < length; i++) {
73 const char ch = name[i];
74 if (ch == '_') {
75 result += R"(\\\)";
76 }
77 result += ch;
78 }
79 return result;
80}
81
82void write_stats_data(const DebugContext &ctx)
83{
84 /* Fill in array of all stats which are to be displayed. */
85 Vector<StatsEntry> stats;
86 stats.reserve(ctx.graph->id_nodes.size());
87 for (const IDNode *id_node : ctx.graph->id_nodes) {
88 const double time = get_node_time(ctx, id_node);
89 if (time == 0.0) {
90 continue;
91 }
92 StatsEntry entry;
93 entry.id_node = id_node;
94 entry.time = time;
95 stats.append(entry);
96 }
97 /* Sort the data. */
98 std::sort(stats.begin(), stats.end(), stat_entry_comparator);
99 /* We limit number of entries, otherwise things become unreadable. */
100 stats.resize(min_ii(stats.size(), 32));
101 std::reverse(stats.begin(), stats.end());
102 /* Print data to the file stream. */
103 deg_debug_fprintf(ctx, "$data << EOD" NL);
104 for (const StatsEntry &entry : stats) {
105 deg_debug_fprintf(ctx,
106 "\"[%s] %s\",%f" NL,
107 gnuplotify_id_code(entry.id_node->id_orig->name).c_str(),
108 gnuplotify_name(entry.id_node->id_orig->name + 2).c_str(),
109 entry.time);
110 }
111 deg_debug_fprintf(ctx, "EOD" NL);
112}
113
114void deg_debug_stats_gnuplot(const DebugContext &ctx)
115{
116 /* Data itself. */
117 write_stats_data(ctx);
118 /* Optional label. */
119 if (ctx.label && ctx.label[0]) {
120 deg_debug_fprintf(ctx, "set title \"%s\"" NL, ctx.label);
121 }
122 /* Rest of the commands.
123 * TODO(sergey): Need to decide on the resolution somehow. */
124 deg_debug_fprintf(ctx, "set terminal pngcairo size 1920,1080" NL);
125 deg_debug_fprintf(ctx, "set output \"%s\"" NL, ctx.output_filename);
126 deg_debug_fprintf(ctx, "set grid" NL);
127 deg_debug_fprintf(ctx, "set datafile separator ','" NL);
128 deg_debug_fprintf(ctx, "set style fill solid" NL);
129 deg_debug_fprintf(ctx,
130 "plot \"$data\" using "
131 "($2*0.5):0:($2*0.5):(0.2):yticlabels(1) "
132 "with boxxyerrorbars t '' lt rgb \"#406090\"" NL);
133}
134
135} // namespace
136} // namespace blender::deg
137
138void DEG_debug_stats_gnuplot(const Depsgraph *depsgraph,
139 FILE *fp,
140 const char *label,
141 const char *output_filename)
142{
143 if (depsgraph == nullptr) {
144 return;
145 }
146 deg::DebugContext ctx;
147 ctx.file = fp;
148 ctx.graph = (deg::Depsgraph *)depsgraph;
149 ctx.label = label;
150 ctx.output_filename = output_filename;
151 deg::deg_debug_stats_gnuplot(ctx);
152}
#define ATTR_PRINTF_FORMAT(format_param, dots_param)
MINLINE int min_ii(int a, int b)
ID and Library types, which are fundamental for SDNA.
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
local_group_size(16, 16) .push_constant(Type b
void DEG_debug_stats_gnuplot(const Depsgraph *depsgraph, FILE *fp, const char *label, const char *output_filename)
#define NL
const IDNode * id_node
const char * output_filename
double time
const char * label
const Depsgraph * depsgraph