Skip to content

Commit 6ae8b75

Browse files
committed
Add graph plotting for dudect analysis
Implement graph generation using "gnuplot" for dudect to visualize t-statistic measurements. - Add "plot.c" and "plot.h" files to support graphing, "plot.c" stores each measurements execution time in "data_buffer". When plot_graph() is called, stores the data to file and generates a "gnuplot" script. I try to replicate the graph shown in "dudect's" paper "Dude, is my code constant time?". - Modify "fixture.c" to integrate with new plotting functionality. - Move definition of ENOUGH_MEASURE and TEST_TRIES from "fixture.c" to "fixture.h" for "plot.c" to access and specify size of "data_buffer" - Update "Makefile" to include plot.o in build This enhancement allows visual representation of constant-time analysis results, making it easier to interpret dudect test outcomes. Change-Id: I94387b44010e4b410475c346864d784bdb75251d
1 parent b36c6b1 commit 6ae8b75

File tree

6 files changed

+154
-4
lines changed

6 files changed

+154
-4
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,8 @@ GPATH
2525
GRTAGS
2626
GSYMS
2727
GTAGS
28+
29+
# gnuplot files
30+
gnuplot_script.gnu
31+
data.txt
32+
*.png

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ $(GIT_HOOKS):
3838
@echo
3939

4040
OBJS := qtest.o report.o console.o harness.o queue.o \
41-
random.o dudect/constant.o dudect/fixture.o dudect/ttest.o \
41+
random.o dudect/constant.o dudect/fixture.o dudect/ttest.o dudect/plot.o \
4242
shannon_entropy.o \
4343
linenoise.o web.o
4444

dudect/fixture.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,9 @@
3838

3939
#include "constant.h"
4040
#include "fixture.h"
41+
#include "plot.h"
4142
#include "ttest.h"
4243

43-
#define ENOUGH_MEASURE 10000
44-
#define TEST_TRIES 10
45-
4644
static t_context_t *t;
4745

4846
/* threshold values for Welch's t-test */
@@ -83,6 +81,8 @@ static bool report(void)
8381
double number_traces_max_t = t->n[0] + t->n[1];
8482
double max_tau = max_t / sqrt(number_traces_max_t);
8583

84+
add_data(max_t);
85+
8686
printf("\033[A\033[2K");
8787
printf("meas: %7.2lf M, ", (number_traces_max_t / 1e6));
8888
if (number_traces_max_t < ENOUGH_MEASURE) {
@@ -156,16 +156,19 @@ static bool test_const(char *text, int mode)
156156
bool result = false;
157157
t = malloc(sizeof(t_context_t));
158158

159+
init_data_buffer();
159160
for (int cnt = 0; cnt < TEST_TRIES; ++cnt) {
160161
printf("Testing %s...(%d/%d)\n\n", text, cnt, TEST_TRIES);
161162
init_once();
162163
for (int i = 0; i < ENOUGH_MEASURE / (N_MEASURES - DROP_SIZE * 2) + 1;
163164
++i)
164165
result = doit(mode);
165166
printf("\033[A\033[2K\033[A\033[2K");
167+
next_try();
166168
if (result)
167169
break;
168170
}
171+
plot_graph(t_threshold_moderate, text);
169172
free(t);
170173
return result;
171174
}

dudect/fixture.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
#include <stdbool.h>
55
#include "constant.h"
66

7+
#define ENOUGH_MEASURE 10000
8+
#define TEST_TRIES 10
9+
710
/* Interface to test if function is constant */
811
#define _(x) bool is_##x##_const(void);
912
DUT_FUNCS

dudect/plot.c

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#include <math.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
#include "fixture.h"
6+
7+
#define GNUPLOT_SCRIPT "gnuplot_script.gnu"
8+
#define DATA_FILE "data.txt"
9+
10+
int n_tries = 0;
11+
12+
struct {
13+
double y[ENOUGH_MEASURE];
14+
int n_measures;
15+
} data_buffer[TEST_TRIES];
16+
17+
static double max_data_value()
18+
{
19+
double mx = 0;
20+
for (int i = 0; i < TEST_TRIES; i++) {
21+
double value = data_buffer[i].y[data_buffer[i].n_measures - 1];
22+
if (value > mx)
23+
mx = value;
24+
}
25+
return mx;
26+
}
27+
28+
void init_data_buffer()
29+
{
30+
n_tries = 0;
31+
for (int i = 0; i < TEST_TRIES; i++) {
32+
data_buffer[i].n_measures = 0;
33+
}
34+
}
35+
36+
void next_try()
37+
{
38+
n_tries++;
39+
}
40+
41+
void add_data(double y)
42+
{
43+
if (n_tries >= TEST_TRIES) {
44+
fprintf(stderr, "Buffer overflow\n");
45+
exit(1);
46+
}
47+
data_buffer[n_tries].y[data_buffer[n_tries].n_measures++] = y;
48+
}
49+
50+
void save_data()
51+
{
52+
FILE *fp = fopen(DATA_FILE, "w");
53+
if (!fp) {
54+
perror("Error opening file");
55+
exit(1);
56+
}
57+
fprintf(fp, "# X ");
58+
for (int i = 0; i < TEST_TRIES; i++) {
59+
fprintf(fp, "t%d ", i);
60+
}
61+
fprintf(fp, "\n");
62+
for (int i = 0; i < data_buffer[0].n_measures; i++) {
63+
fprintf(fp, "%d ", (int) i);
64+
for (int j = 0; j < TEST_TRIES; j++) {
65+
fprintf(fp, "%lf ", data_buffer[j].y[i]);
66+
}
67+
fprintf(fp, "\n");
68+
}
69+
fclose(fp);
70+
}
71+
72+
void generate_gnuplot_script(double threshold,
73+
const char *title,
74+
const char *output_file)
75+
{
76+
FILE *gp = fopen(GNUPLOT_SCRIPT, "w");
77+
if (!gp) {
78+
perror("Error opening Gnuplot script file");
79+
exit(1);
80+
}
81+
82+
int mx_val = (int) max_data_value();
83+
int y_range = mx_val < 25 ? 50 : mx_val * 2;
84+
85+
86+
fprintf(gp,
87+
"set terminal pngcairo enhanced size 800,400\n"
88+
"set output '%s'\n"
89+
"set title '%s'\n"
90+
"set xlabel '# measurements'\n"
91+
"set ylabel '|t| statistic'\n"
92+
"set grid front\n"
93+
"set xrange [0:%d]\n"
94+
"set yrange [0:%d]\n"
95+
96+
// #Define the threshold as a function
97+
"f(x) = %lf\n"
98+
99+
// #Fill the lower part(green) and upper part(red)
100+
"set style fill solid 0.3\n"
101+
"plot '%s' using 1:(f($1)) with filledcurves y1=0 lc rgb 'green' "
102+
"notitle, \\\n"
103+
" '%s' using 1:(f($1)) with filledcurves y1=%d lc rgb 'red' "
104+
"notitle, \\\n"
105+
" for [i=2:%d] '%s' using 1:i:(i) with lines lw 2 lc variable "
106+
"title sprintf('Test %%d', i-1)\n",
107+
output_file, title, data_buffer[0].n_measures, y_range, threshold,
108+
DATA_FILE, DATA_FILE, y_range, n_tries + 1, DATA_FILE);
109+
110+
fclose(gp);
111+
}
112+
113+
void plot_graph(double threshold, const char *title)
114+
{
115+
save_data();
116+
char *output_file = malloc(strlen(title) + 5);
117+
if (!output_file) {
118+
perror("Error allocating memory");
119+
exit(1);
120+
}
121+
strncpy(output_file, title, strlen(title) + 1);
122+
strcat(output_file, ".png");
123+
generate_gnuplot_script(threshold, title, output_file);
124+
int ret = system("gnuplot " GNUPLOT_SCRIPT);
125+
if (ret != 0) {
126+
fprintf(stderr, "Error generating graph\n");
127+
exit(1);
128+
}
129+
printf("Graph generated: %s\n", output_file);
130+
free(output_file);
131+
}

dudect/plot.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef DUDECT_PLOT_H
2+
#define DUDECT_PLOT_H
3+
4+
void init_data_buffer();
5+
void next_try();
6+
void add_data(double y);
7+
void plot_graph(double threshold, char *title);
8+
#endif

0 commit comments

Comments
 (0)