/alps/fwbench

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