use realpath to get the absolute pathname, fixes some forgotten cases, especially...
[lttv.git] / ltt / branches / poly / lttv / modules / text / batchtest.c
CommitLineData
08b1c66e 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
19/* This module inserts a hook in the program main loop. This hook processes
20 all the events in the main tracefile while testing the speed and
21 functionality of the state and stats computations. */
22
23
24#include <lttv/lttv.h>
25#include <lttv/attribute.h>
26#include <lttv/hook.h>
27#include <lttv/option.h>
28#include <lttv/module.h>
29#include <lttv/processTrace.h>
30#include <lttv/state.h>
31#include <lttv/stats.h>
32#include <ltt/trace.h>
33#include <ltt/event.h>
338d4282 34#include <ltt/type.h>
08b1c66e 35
36static LttvTraceset *traceset;
37
38static LttvHooks
39 *before_traceset,
40 *after_traceset,
41 *before_trace,
42 *after_trace,
43 *before_tracefile,
44 *after_tracefile,
45 *before_event,
46 *after_event,
47 *main_hooks;
48
49static char *a_trace;
50
51static char *a_dump_tracefiles;
52
53static char *a_save_sample;
54
55static int
56 a_sample_interval,
57 a_sample_number,
58 a_save_interval;
59
60static gboolean
61 a_test1,
62 a_test2,
63 a_test3,
64 a_test4,
65 a_test5,
66 a_test6,
67 a_test7,
68 a_test_all;
69
70typedef struct _save_state {
71 guint count;
72 FILE *fp;
73 guint interval;
74 guint position;
75 guint size;
76 LttTime *write_time;
77 guint version;
78} SaveState;
79
80
81static void lttv_trace_option(void *hook_data)
82{
83 LttTrace *trace;
84
85 trace = ltt_trace_open(a_trace);
86 if(trace == NULL) g_critical("cannot open trace %s", a_trace);
87 lttv_traceset_add(traceset, lttv_trace_new(trace));
88}
89
90static double get_time()
91{
92 GTimeVal gt;
93
94 g_get_current_time(&gt);
95 return gt.tv_sec + (double)gt.tv_usec / (double)1000000.0;
96}
97
98static double run_one_test(LttvTracesetState *ts, LttTime start, LttTime end)
99{
100 double t0, t1;
101
102 lttv_traceset_context_add_hooks(&ts->parent,
103 before_traceset, after_traceset, NULL, before_trace, after_trace,
104 NULL, before_tracefile, after_tracefile, NULL, before_event, after_event);
105
106 t0 = get_time();
107 lttv_state_traceset_seek_time_closest(ts, start);
108 lttv_process_traceset(&ts->parent, end, G_MAXULONG);
109 t1 = get_time();
110
111 lttv_traceset_context_remove_hooks(&ts->parent,
112 before_traceset, after_traceset, NULL, before_trace, after_trace,
113 NULL, before_tracefile, after_tracefile, NULL, before_event, after_event);
114
115 return t1 - t0;
116}
117
118
119gboolean count_event(void *hook_data, void *call_data)
120{
121 guint *pcount = (guint *)hook_data;
122
123 (*pcount)++;
124 return FALSE;
125}
126
127
128gboolean save_state_event(void *hook_data, void *call_data)
129{
130 SaveState *save_state = (SaveState *)hook_data;
131
132 LttvTracefileState *tfs = (LttvTracefileState *)call_data;
133
134 LttvTraceState *ts = (LttvTraceState *)tfs->parent.t_context;
135
136 GString *filename;
137
138 FILE *fp;
139
140 (save_state->count)++;
141 if(save_state->count % save_state->interval == 0 &&
142 save_state->position < save_state->size) {
143 if(a_save_sample != NULL) {
144 filename = g_string_new("");
145 g_string_printf(filename, "%s.%u.xml.%u", a_save_sample,
146 save_state->position, save_state->version);
147 fp = fopen(filename->str, "w");
148 if(fp == NULL) g_error("Cannot open %s", filename->str);
149 g_string_free(filename, TRUE);
150 lttv_state_write(ts, tfs->parent.timestamp, fp);
151 fclose(fp);
152 } else lttv_state_write(ts, tfs->parent.timestamp, save_state->fp);
153
154 save_state->write_time[save_state->position] = tfs->parent.timestamp;
155 save_state->position++;
156 }
157 return FALSE;
158}
159
160
161static gboolean process_traceset(void *hook_data, void *call_data)
162{
163 LttvTracesetStats *tscs;
164
165 LttvTracesetState *ts;
166
167 LttvTracesetContext *tc;
168
169 GString *filename;
170
171 FILE *fp;
172
173 double t;
174
175 guint i, j, count, nb_control, nb_tracefile, nb_block, nb_event, nb_equal;
176
177 LttTrace *trace;
178
179 LttTracefile *tracefile, *tf;
180
181 LttEvent *event;
182
183 LttFacility *facility;
184
185 LttType *type;
186
187 LttEventType *event_type;
188
189 LttTime time, previous_time;
190
338d4282 191 long long unsigned cycle_count, start_count, delta_cycle;
192
193 long long unsigned start_nsec, end_nsec, delta_nsec, added_nsec, added_nsec2;
194
195 double cycle_per_nsec, nsec_per_cycle;
196
197 long long interpolated_nsec, interpolated_nsec2, end_nsec_sec, end_nsec_nsec;
198
199 LttTime start_time;
200
08b1c66e 201 LttEventPosition *event_position;
202
203 LttTime zero_time = ltt_time_zero;
204
205 LttTime max_time = { G_MAXULONG, G_MAXULONG };
206
207 if(a_dump_tracefiles != NULL) {
208 event_position = ltt_event_position_new();
209 for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) {
210 trace = lttv_trace(lttv_traceset_get(traceset, i));
211 nb_control = ltt_trace_control_tracefile_number(trace);
212 nb_tracefile = nb_control + ltt_trace_per_cpu_tracefile_number(trace);
213 for(j = 0 ; j < nb_tracefile ; j++) {
214 if(j < nb_control) {
215 tracefile = ltt_trace_control_tracefile_get(trace,j);
216 }
217 else {
218 tracefile = ltt_trace_per_cpu_tracefile_get(trace,j - nb_control);
219 }
220
221 filename = g_string_new("");
222 g_string_printf(filename, "%s.%u.%u.trace", a_dump_tracefiles, i, j);
223 fp = fopen(filename->str, "w");
224 if(fp == NULL) g_error("Cannot open %s", filename->str);
225 g_string_free(filename, TRUE);
226 ltt_tracefile_seek_time(tracefile, zero_time);
227 previous_time = zero_time;
228 nb_equal = 0;
229 while((event = ltt_tracefile_read(tracefile)) != NULL) {
230 facility = ltt_event_facility(event);
231 event_type = ltt_event_eventtype(event);
232 time = ltt_event_time(event);
338d4282 233 cycle_count = ltt_event_cycle_count(event);
08b1c66e 234 ltt_event_position(event, event_position);
235 ltt_event_position_get(event_position, &nb_block, &nb_event, &tf);
338d4282 236 fprintf(fp,"%s.%s: %llu %lu.%09lu position %u/%u\n",
08b1c66e 237 ltt_facility_name(facility), ltt_eventtype_name(event_type),
338d4282 238 cycle_count, (unsigned long)time.tv_sec,
239 (unsigned long)time.tv_nsec,
240 nb_block, nb_event);
08b1c66e 241
242 if(ltt_time_compare(time, previous_time) < 0) {
243 g_warning("Time decreasing trace %d tracefile %d position %u/%u",
244 i, j, nb_block, nb_event);
245 }
338d4282 246
247 if(strcmp(ltt_eventtype_name(event_type),"block_start") == 0) {
248 start_count = cycle_count;
249 start_time = time;
250 }
251 else if(strcmp(ltt_eventtype_name(event_type),"block_end") == 0) {
252 delta_cycle = cycle_count - start_count;
253 end_nsec_sec = (long long unsigned)time.tv_sec * (long long unsigned)1000000000;
254 end_nsec_nsec = time.tv_nsec;
255 end_nsec = end_nsec_sec + end_nsec_nsec;
256 start_nsec = (long long unsigned)start_time.tv_sec * (long long unsigned)1000000000 + (long long unsigned)start_time.tv_nsec;
257 delta_nsec = end_nsec - start_nsec;
258 cycle_per_nsec = (double)delta_cycle / (double)delta_nsec;
259 nsec_per_cycle = (double)delta_nsec / (double)delta_cycle;
260 added_nsec = (double)delta_cycle * nsec_per_cycle;
261 interpolated_nsec = start_nsec + added_nsec;
262 added_nsec2 = (double)delta_cycle / cycle_per_nsec;
263 interpolated_nsec2 = start_nsec + added_nsec2;
264
265 fprintf(fp,"Time: start_count %llu, end_count %llu, delta_cycle %llu, start_nsec %llu, end_nsec_sec %llu, end_nsec_nsec %llu, end_nsec %llu, delta_nsec %llu, cycle_per_nsec %.25f, nsec_per_cycle %.25f, added_nsec %llu, added_nsec2 %llu, interpolated_nsec %llu, interpolated_nsec2 %llu\n", start_count, cycle_count, delta_cycle, start_nsec, end_nsec_sec, end_nsec_nsec, end_nsec, delta_nsec, cycle_per_nsec, nsec_per_cycle, added_nsec, added_nsec2, interpolated_nsec, interpolated_nsec2);
266 }
267 else {
268 if(ltt_time_compare(time, previous_time) == 0) nb_equal++;
269 else if(nb_equal > 0) {
270 g_warning("Consecutive %d events with time %lu.%09lu",
271 nb_equal + 1, previous_time.tv_sec, previous_time.tv_nsec);
272 nb_equal = 0;
273 }
274 previous_time = time;
275 }
08b1c66e 276 }
277 fclose(fp);
278 }
279 }
280 g_free(event_position);
281 }
282
283 tscs = g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
284 ts = &tscs->parent;
285 tc = &tscs->parent.parent;
286
287 lttv_context_init(tc, traceset);
288 for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) {
289 ((LttvTraceState *)(tc->traces[i]))->save_interval = a_save_interval;
290 }
291
292 /* For each case compute and print the elapsed time.
293 The first case is simply to run through all events with a
294 simple counter. */
295
296 if(a_test1 || a_test_all) {
297 count = 0;
298 lttv_hooks_add(after_event, count_event, &count);
299 t = run_one_test(ts, zero_time, max_time);
300 lttv_hooks_remove_data(after_event, count_event, &count);
301 g_warning(
302 "Processing trace while counting events (%u events in %g seconds)",
303 count, t);
304 }
305
306 /* Run through all events computing the state. */
307
308 if(a_test2 || a_test_all) {
309 lttv_state_add_event_hooks(ts);
310 t = run_one_test(ts, zero_time, max_time);
311 lttv_state_remove_event_hooks(ts);
312 g_warning("Processing trace while updating state (%g seconds)", t);
313 }
314
315 /* Run through all events computing the state and writing it out
316 periodically. */
317
318 SaveState save_state;
319
320 save_state.interval = a_sample_interval;
321 save_state.size = a_sample_number;
322 save_state.fp = stderr;
323 save_state.write_time = g_new(LttTime, a_sample_number);
324
325
326 if(a_test3 || a_test_all) {
327 for(i = 0 ; i < 2 ; i++) {
328 save_state.count = 0;
329 save_state.position = 0;
330 save_state.version = i;
331 lttv_state_add_event_hooks(ts);
332 lttv_hooks_add(after_event, save_state_event, &save_state);
333 t = run_one_test(ts, zero_time, max_time);
334 lttv_state_remove_event_hooks(ts);
335 lttv_hooks_remove_data(after_event, save_state_event, &save_state);
336 g_warning("Processing while updating/writing state (%g seconds)", t);
337 }
338 }
339
340 /* Run through all events computing the stats. */
341
342 if(a_test4 || a_test_all) {
343 if(lttv_profile_memory) {
344 g_message("Memory summary before computing stats");
345 g_mem_profile();
346 }
347
348 lttv_stats_add_event_hooks(tscs);
349 t = run_one_test(ts, zero_time, max_time);
350 lttv_stats_remove_event_hooks(tscs);
351 g_warning("Processing trace while counting stats (%g seconds)", t);
352
353 if(lttv_profile_memory) {
354 g_message("Memory summary after computing stats");
355 g_mem_profile();
356 }
357 }
358
359 /* Run through all events computing the state and stats. */
360
361 if(a_test5 || a_test_all) {
362 if(lttv_profile_memory) {
363 g_message("Memory summary before computing state and stats");
364 g_mem_profile();
365 }
366
367 lttv_state_add_event_hooks(ts);
368 lttv_stats_add_event_hooks(tscs);
369 t = run_one_test(ts, zero_time, max_time);
370 lttv_state_remove_event_hooks(ts);
371 lttv_stats_remove_event_hooks(tscs);
372 g_warning(
373 "Processing trace while counting state and stats (%g seconds)", t);
374
375 if(lttv_profile_memory) {
376 g_message("Memory summary after computing and state and stats");
377 g_mem_profile();
378 }
379 }
380
381 /* Run through all events computing and saving the state. */
382
383 if(a_test6 || a_test_all) {
384 if(lttv_profile_memory) {
385 g_message("Memory summary before computing and saving state");
386 g_mem_profile();
387 }
388
389 lttv_state_add_event_hooks(ts);
390 lttv_state_save_add_event_hooks(ts);
391 t = run_one_test(ts, zero_time, max_time);
392 lttv_state_remove_event_hooks(ts);
393 lttv_state_save_remove_event_hooks(ts);
394 g_warning("Processing trace while updating/saving state (%g seconds)", t);
395
396 if(lttv_profile_memory) {
397 g_message("Memory summary after computing/saving state");
398 g_mem_profile();
399 }
400 }
401
402 /* Seek a few times to each saved position */
403
404 if((a_test7 && a_test3) || a_test_all) {
405 int i, j;
406
407 for(i = 0 ; i < 2 ; i++) {
408 for(j = save_state.position - 1 ; j >= 0 ; j--) {
409 lttv_state_add_event_hooks(ts);
410 t = run_one_test(ts, save_state.write_time[j],
411 save_state.write_time[j]);
412 lttv_state_remove_event_hooks(ts);
413 g_warning("Seeking to %lu.%lu (%g seconds)",
414 save_state.write_time[j].tv_sec, save_state.write_time[j].tv_nsec,
415 t);
416
417 if(a_save_sample != NULL) {
418 filename = g_string_new("");
419 g_string_printf(filename, "%s.%d.xml.bak%d", a_save_sample, j, i);
420 fp = fopen(filename->str, "w");
421 if(fp == NULL) g_error("Cannot open %s", filename->str);
422 g_string_free(filename, TRUE);
423 lttv_state_write((LttvTraceState *)tc->traces[0],
424 save_state.write_time[j], fp);
425 fclose(fp);
426 }
427 else lttv_state_write((LttvTraceState *)tc->traces[0],
428 save_state.write_time[j], save_state.fp);
429 }
430 }
431 }
432
433 g_free(save_state.write_time);
434 lttv_context_fini(tc);
435 g_object_unref(tscs);
436
437 g_info("BatchTest end process traceset");
438}
439
440
441static void init()
442{
443 LttvAttributeValue value;
444
445 LttvIAttribute *attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
446
447 g_info("Init batchtest.c");
448
449 lttv_option_add("trace", 't',
450 "add a trace to the trace set to analyse",
451 "pathname of the directory containing the trace",
452 LTTV_OPT_STRING, &a_trace, lttv_trace_option, NULL);
453
454 a_dump_tracefiles = NULL;
455 lttv_option_add("dump-tracefiles", 'D',
456 "Write event by event the content of tracefiles",
457 "basename for the files where to dump events",
458 LTTV_OPT_STRING, &a_dump_tracefiles, NULL, NULL);
459
460 a_save_sample = NULL;
461 lttv_option_add("save-sample", 's',
462 "Save state samples to multiple files",
463 "basename for the files containing the state samples",
464 LTTV_OPT_STRING, &a_save_sample, NULL, NULL);
465
466 a_save_interval = 100000;
467 lttv_option_add("save-interval", 'i',
468 "Interval between saving state",
469 "number of events before a block start triggers saving state",
470 LTTV_OPT_INT, &a_save_interval, NULL, NULL);
471
472 a_sample_interval = 100000;
473 lttv_option_add("sample-interval", 'S',
474 "Interval between sampling state",
475 "number of events before sampling and writing state",
476 LTTV_OPT_INT, &a_sample_interval, NULL, NULL);
477
478 a_sample_number = 20;
479 lttv_option_add("sample-number", 'N',
480 "Number of state samples",
481 "maximum number",
482 LTTV_OPT_INT, &a_sample_number, NULL, NULL);
483
484 a_test1 = FALSE;
485 lttv_option_add("test1", '1', "Test just counting events", "",
486 LTTV_OPT_NONE, &a_test1, NULL, NULL);
487
488 a_test2 = FALSE;
489 lttv_option_add("test2", '2', "Test computing the state", "",
490 LTTV_OPT_NONE, &a_test2, NULL, NULL);
491
492 a_test3 = FALSE;
493 lttv_option_add("test3", '3', "Test computing the state, writing out a few",
494 "", LTTV_OPT_NONE, &a_test3, NULL, NULL);
495
496 a_test4 = FALSE;
497 lttv_option_add("test4", '4', "Test computing the stats", "",
498 LTTV_OPT_NONE, &a_test4, NULL, NULL);
499
500 a_test5 = FALSE;
501 lttv_option_add("test5", '5', "Test computing the state and stats", "",
502 LTTV_OPT_NONE, &a_test5, NULL, NULL);
503
504 a_test6 = FALSE;
505 lttv_option_add("test6", '6', "Test computing and saving the state", "",
506 LTTV_OPT_NONE, &a_test6, NULL, NULL);
507
508 a_test7 = FALSE;
509 lttv_option_add("test7", '7', "Test seeking to positions written out in 3",
510 "", LTTV_OPT_NONE, &a_test7, NULL, NULL);
511
512 a_test_all = FALSE;
513 lttv_option_add("testall", 'a', "Run all tests ", "",
514 LTTV_OPT_NONE, &a_test_all, NULL, NULL);
515
516 traceset = lttv_traceset_new();
517
518 before_traceset = lttv_hooks_new();
519 after_traceset = lttv_hooks_new();
520 before_trace = lttv_hooks_new();
521 after_trace = lttv_hooks_new();
522 before_tracefile = lttv_hooks_new();
523 after_tracefile = lttv_hooks_new();
524 before_event = lttv_hooks_new();
525 after_event = lttv_hooks_new();
526
527 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/before",
528 LTTV_POINTER, &value));
529 *(value.v_pointer) = before_traceset;
530 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/traceset/after",
531 LTTV_POINTER, &value));
532 *(value.v_pointer) = after_traceset;
533 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/before",
534 LTTV_POINTER, &value));
535 *(value.v_pointer) = before_trace;
536 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/trace/after",
537 LTTV_POINTER, &value));
538 *(value.v_pointer) = after_trace;
539 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/before",
540 LTTV_POINTER, &value));
541 *(value.v_pointer) = before_tracefile;
542 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/tracefile/after",
543 LTTV_POINTER, &value));
544 *(value.v_pointer) = after_tracefile;
545 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/before",
546 LTTV_POINTER, &value));
547 *(value.v_pointer) = before_event;
548 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/event/after",
549 LTTV_POINTER, &value));
550 *(value.v_pointer) = after_event;
551
552 g_assert(lttv_iattribute_find_by_path(attributes, "hooks/main/before",
553 LTTV_POINTER, &value));
554 g_assert((main_hooks = *(value.v_pointer)) != NULL);
555 lttv_hooks_add(main_hooks, process_traceset, NULL);
556}
557
558
559static void destroy()
560{
561 guint i, nb;
562
563 LttvTrace *trace;
564
565 g_info("Destroy batchAnalysis.c");
566
567 lttv_option_remove("trace");
568 lttv_option_remove("dump-tracefiles");
569 lttv_option_remove("save-sample");
570 lttv_option_remove("sample-interval");
571 lttv_option_remove("sample-number");
572 lttv_option_remove("save-interval");
573 lttv_option_remove("test1");
574 lttv_option_remove("test2");
575 lttv_option_remove("test3");
576 lttv_option_remove("test4");
577 lttv_option_remove("test5");
578 lttv_option_remove("test6");
579 lttv_option_remove("test7");
580 lttv_option_remove("testall");
581
582 lttv_hooks_destroy(before_traceset);
583 lttv_hooks_destroy(after_traceset);
584 lttv_hooks_destroy(before_trace);
585 lttv_hooks_destroy(after_trace);
586 lttv_hooks_destroy(before_tracefile);
587 lttv_hooks_destroy(after_tracefile);
588 lttv_hooks_destroy(before_event);
589 lttv_hooks_destroy(after_event);
590 lttv_hooks_remove_data(main_hooks, process_traceset, NULL);
591
592 nb = lttv_traceset_number(traceset);
593 for(i = 0 ; i < nb ; i++) {
594 trace = lttv_traceset_get(traceset, i);
595 ltt_trace_close(lttv_trace(trace));
596 lttv_trace_destroy(trace);
597 }
598
599 lttv_traceset_destroy(traceset);
600}
601
602
603LTTV_MODULE("batchtest", "Batch processing of a trace for tests", \
604 "Run through a trace calling all the registered hooks for tests", \
605 init, destroy, "state", "stats", "option" )
This page took 0.045109 seconds and 4 git commands to generate.