bzr branch
http://darksoft.org/webbzr/alps/fwbench
1
by Suren A. Chilingaryan
Initial release |
1 |
#include <stdio.h> |
2 |
#include <stdlib.h> |
|
3 |
#include <string.h> |
|
4 |
#include <errno.h> |
|
5 |
#include <fcntl.h> |
|
6 |
#include <glib.h> |
|
7 |
#include <math.h> |
|
8 |
#include <unistd.h> |
|
9 |
#include <sys/stat.h> |
|
10 |
#include <sys/time.h> |
|
11 |
||
12 |
#include <fastwriter.h> |
|
13 |
#include <ufo/ufo-graph.h> |
|
14 |
||
15 |
#include "config.h" |
|
16 |
||
17 |
#define FW_BUFFER 4096l
|
|
18 |
#define WRITE_INTERVAL 1
|
|
19 |
#define WRITE_SUMMARY 5
|
|
20 |
#define NEWFILE 10
|
|
21 |
||
22 |
||
23 |
#define run_time 3600
|
|
24 |
const char *fifo_name = ".fifo"; |
|
25 |
||
26 |
struct setup_s { |
|
27 |
size_t width; |
|
28 |
size_t height; |
|
29 |
size_t bpp; |
|
30 |
size_t fps; |
|
31 |
||
32 |
size_t iters; |
|
33 |
||
34 |
volatile int run_started; |
|
35 |
};
|
|
36 |
||
37 |
typedef struct setup_s setup_t; |
|
38 |
||
39 |
void handle_error(GError *error) { |
|
40 |
if (error != NULL) { |
|
41 |
g_print("%s\n", error->message); |
|
42 |
g_error_free(error); |
|
43 |
exit(EXIT_FAILURE); |
|
44 |
}
|
|
45 |
}
|
|
46 |
||
47 |
void set_speed(setup_t *setup, size_t speed) { |
|
48 |
setup->bpp = sizeof(float); |
|
49 |
setup->width = 1024; |
|
50 |
setup->height = 768; |
|
51 |
setup->fps = 1 + speed / setup->width / setup->height / setup->bpp; |
|
52 |
}
|
|
53 |
||
54 |
void set_size(setup_t *setup, size_t size) { |
|
55 |
setup->iters = size / setup->width / setup->height / setup->bpp; |
|
56 |
}
|
|
57 |
||
58 |
void set_time(setup_t *setup, size_t time) { |
|
59 |
setup->iters = time * setup->fps; |
|
60 |
}
|
|
61 |
||
62 |
static void *run(setup_t *setup) { |
|
63 |
GError *error = NULL; |
|
64 |
UfoGraph *graph = NULL; |
|
65 |
/* If you want to use system-wide installed filters:
|
|
66 |
* graph = ufo_graph_new(); */
|
|
67 |
||
68 |
graph = g_object_new(UFO_TYPE_GRAPH, |
|
69 |
#ifdef METABALLS_PATH
|
|
70 |
"paths", METABALLS_PATH, |
|
71 |
#endif /* METABALLS_PATH */ |
|
72 |
NULL); |
|
73 |
||
74 |
// printf("%lu %lu %lu %lu\n", setup->width, setup->height, setup->iters, setup->width * setup->height * setup->iters * sizeof(float));
|
|
75 |
UfoFilter *metaballs = ufo_graph_get_filter(graph, "metaballs", &error); |
|
76 |
handle_error(error); |
|
77 |
g_object_set(G_OBJECT(metaballs), |
|
78 |
"width", setup->width, |
|
79 |
"height", setup->height, |
|
80 |
"num-balls", 1, |
|
81 |
"num-iterations", setup->iters, |
|
82 |
"frames-per-second", setup->fps, |
|
83 |
NULL); |
|
84 |
||
85 |
UfoFilter *writer = ufo_graph_get_filter(graph, "pipeoutput", &error); |
|
86 |
handle_error(error); |
|
87 |
g_object_set(G_OBJECT(writer), |
|
88 |
"pipe-name", fifo_name, |
|
89 |
NULL); |
|
90 |
||
91 |
ufo_filter_connect_to(metaballs, writer, &error); |
|
92 |
handle_error(error); |
|
93 |
||
94 |
setup->run_started = 1; |
|
95 |
ufo_graph_run(graph, &error); |
|
96 |
handle_error(error); |
|
97 |
||
98 |
||
99 |
// g_print("Wrote %lu bytes\n", width * height * num_iterations * sizeof(float));
|
|
100 |
||
101 |
g_thread_exit(NULL); |
|
102 |
return NULL; |
|
103 |
}
|
|
104 |
||
105 |
||
106 |
||
107 |
||
108 |
int main(int argc, char const* argv[]) |
|
109 |
{
|
|
110 |
int err; |
|
111 |
GError *gerr; |
|
112 |
GThread *thr; |
|
113 |
setup_t setup; |
|
114 |
fastwriter_t *fw; |
|
115 |
fastwriter_stats_t stats; |
|
116 |
const char *out = "/dev/null"; |
|
117 |
size_t speed = 850; |
|
118 |
||
119 |
size_t num_read = 0; |
|
120 |
size_t buf_max = 0; |
|
121 |
||
122 |
int broken_frame = 0; |
|
123 |
size_t writeouts = 0; |
|
124 |
size_t duration, last_duration; |
|
125 |
struct timeval tv; |
|
126 |
struct timeval tv_started = {0}; |
|
127 |
struct timeval tv_last_written = {0}; |
|
128 |
unsigned long frames = 0, lost = 0; |
|
129 |
unsigned long delta, expected; |
|
130 |
unsigned long last_frames = 0, last_lost = 0; |
|
131 |
||
132 |
||
133 |
g_thread_init(NULL); |
|
134 |
g_type_init(); |
|
135 |
||
136 |
if (argc > 1) { |
|
137 |
out = argv[1]; |
|
138 |
}
|
|
139 |
||
140 |
if (argc > 2) { |
|
141 |
speed = atoi(argv[2]); |
|
142 |
}
|
|
143 |
||
144 |
unlink(fifo_name); |
|
145 |
g_assert(!mkfifo(fifo_name, S_IWUSR | S_IRUSR)); |
|
146 |
||
147 |
fw = fastwriter_init(out, FASTWRITER_FLAGS_OVERWRITE); |
|
148 |
g_assert(fw); |
|
149 |
||
150 |
err = fastwriter_open(fw, out, FASTWRITER_FLAGS_OVERWRITE); |
|
151 |
if (err) printf("FastWriter returned error %i\n", err); |
|
152 |
||
153 |
g_assert(!err); |
|
154 |
||
155 |
fastwriter_set_buffer_size(fw, FW_BUFFER * 1024 * 1024); |
|
156 |
||
157 |
fastwriter_get_stats(fw, &stats); |
|
158 |
printf("*** Writing to %s, speed: %lu MB/s, buffer: %lu MB\n", out, speed, stats.buffer_size); |
|
159 |
||
160 |
memset(&setup, 0, sizeof(setup_t)); |
|
161 |
set_speed(&setup, speed * 1024 * 1024); |
|
162 |
set_size(&setup, run_time * speed * 1024 * 1024); |
|
163 |
||
164 |
size_t frame_size = setup.width * setup.height * setup.bpp; |
|
165 |
void *buffer = malloc(frame_size); |
|
166 |
g_assert(buffer); |
|
167 |
||
168 |
thr = g_thread_create((GThreadFunc)run, &setup, 1, &gerr); |
|
169 |
g_assert(thr); |
|
170 |
||
171 |
while (!setup.run_started); |
|
172 |
||
173 |
int fd = open(fifo_name, O_RDONLY); |
|
174 |
g_assert(fd); |
|
175 |
||
176 |
ssize_t result = read(fd, buffer, frame_size); |
|
177 |
||
178 |
while (result > 0) { |
|
179 |
if (!broken_frame) { |
|
180 |
err = fastwriter_push(fw, result, buffer); |
|
181 |
if (err) { |
|
182 |
if (err == EWOULDBLOCK) { |
|
183 |
if (num_read) fastwriter_cancel(fw); |
|
184 |
broken_frame = 1; |
|
185 |
} else { |
|
186 |
if (err) printf("FastWriter returned error %i\n", err); |
|
187 |
g_assert(!err); |
|
188 |
}
|
|
189 |
}
|
|
190 |
}
|
|
191 |
||
192 |
num_read += result; |
|
193 |
||
194 |
if (num_read < frame_size) { |
|
195 |
result = read(fd, buffer, frame_size - num_read); |
|
196 |
continue; |
|
197 |
}
|
|
198 |
||
199 |
gettimeofday(&tv, NULL); |
|
200 |
if (!tv_started.tv_sec) { |
|
201 |
memcpy(&tv_started, &tv, sizeof(struct timeval)); |
|
202 |
if (tv_started.tv_usec >= (1000000 / setup.fps)) |
|
203 |
tv_started.tv_usec -= (1000000 / setup.fps); |
|
204 |
else { |
|
205 |
tv_started.tv_sec--; |
|
206 |
tv_started.tv_usec += 1000000 - (1000000 / setup.fps); |
|
207 |
}
|
|
208 |
memcpy(&tv_last_written, &tv_started, sizeof(struct timeval)); |
|
209 |
}
|
|
210 |
||
211 |
num_read = 0; |
|
212 |
||
213 |
if (broken_frame) { |
|
214 |
lost++; |
|
215 |
} else { |
|
216 |
err = fastwriter_commit(fw); |
|
217 |
frames++; |
|
218 |
}
|
|
219 |
||
220 |
fastwriter_get_stats(fw, &stats); |
|
221 |
if (stats.buffer_used > buf_max) buf_max = stats.buffer_used; |
|
222 |
||
223 |
if ((tv.tv_sec - tv_last_written.tv_sec) >= WRITE_INTERVAL) { |
|
224 |
last_duration = (tv.tv_sec - tv_last_written.tv_sec) * 1000000 + (tv.tv_usec - tv_last_written.tv_usec); |
|
225 |
||
226 |
/* expected = (tv.tv_sec - tv_last_summary.tv_sec) * setup.fps + (tv.tv_usec - tv_last_summary.tv_usec) * setup.fps / 1000000;
|
|
227 |
delta = expected - lost - frames;
|
|
228 |
if (delta > 0) delta--;*/
|
|
229 |
||
230 |
printf("Lost %6.2lf%% (% 8lu of % 8lu), %9.3lf GB at %8.3lf MB/s, buf:%6.2lf%%\n", 100.*(lost - last_lost) / (lost + frames - last_lost - last_frames), lost - last_lost, lost + frames - (last_lost + last_frames), 1. * frame_size * (frames - last_frames) / 1024 / 1024 / 1024, 1000000. * frame_size * (frames - last_frames) / last_duration / 1024 / 1024, 100.*buf_max/stats.buffer_size); |
|
231 |
||
232 |
if (((++writeouts)%WRITE_SUMMARY)==0) { |
|
233 |
duration = (tv.tv_sec - tv_started.tv_sec) * 1000000 + (tv.tv_usec - tv_started.tv_usec); |
|
234 |
||
235 |
expected = (tv.tv_sec - tv_started.tv_sec) * setup.fps + round(1.*(tv.tv_usec - tv_started.tv_usec)*setup.fps/1000000); |
|
236 |
||
237 |
delta = expected - lost - frames; |
|
238 |
if ((delta > 1)||(delta < 1)) |
|
239 |
printf(" *** Unexpected frame rate: %.2lf (%lu), delta: %li (%lu, %lu)\n", 1000000. * (frames + lost) / duration, setup.fps, delta, lost + frames, expected); |
|
240 |
||
241 |
printf("Total %6.2lf%% (% 8lu of % 8lu), %9.3lf GB at %8.3lf MB/s, buf:%6.2lf%%\n", 100.*lost / (lost + frames), lost, lost + frames, 1. * frames * frame_size / 1024 / 1024 / 1024, 1000000. * frames * frame_size / duration / 1024 / 1024, 100.*stats.buffer_max / stats.buffer_size); |
|
242 |
}
|
|
243 |
||
244 |
buf_max = 0; |
|
245 |
memcpy(&tv_last_written, &tv, sizeof(struct timeval)); |
|
246 |
last_frames = frames; |
|
247 |
last_lost = lost; |
|
248 |
}
|
|
249 |
||
250 |
result = read(fd, buffer, frame_size); |
|
251 |
}
|
|
252 |
||
253 |
printf("Wrote %lu GB\n", frame_size * frames / 1024 / 1024 / 1024); |
|
254 |
||
255 |
g_thread_join(thr); |
|
256 |
||
257 |
close(fd); |
|
258 |
||
259 |
free(buffer); |
|
260 |
fastwriter_close(fw); |
|
261 |
fastwriter_destroy(fw); |
|
262 |
unlink(fifo_name); |
|
263 |
||
264 |
return 0; |
|
265 |
}
|