From f95bc8309fe113855266f4445874248b6a285062 Mon Sep 17 00:00:00 2001 From: dagenais Date: Wed, 14 Apr 2004 18:35:19 +0000 Subject: [PATCH] Add reference counts to state and stats saved attributes. This way, the information can be shared among several contexts using the same trace but is freed when all contexts are "finished". Summing statistics is now done separately to permit more reuse for trace statistics (same trace in several tracesets). The statistics viewer does not yet call this. Use a more generic lttv_attribute_write_xml xml writer to save stats. Place the .h files along with their base package instead of in a separate include tree. git-svn-id: http://ltt.polymtl.ca/svn@500 04897980-b3bd-0310-b5e0-8ef037075253 --- ltt/branches/poly/configure.in | 1 - ltt/branches/poly/include/Makefile.am | 2 +- ltt/branches/poly/include/ltt/Makefile.am | 7 - ltt/branches/poly/include/lttv/attribute.h | 6 + ltt/branches/poly/include/lttv/gtktraceset.h | 32 + ltt/branches/poly/include/lttv/state.h | 2 +- ltt/branches/poly/include/lttv/stats.h | 4 +- ltt/branches/poly/ltt/Makefile.am | 7 + ltt/branches/poly/{include => }/ltt/event.h | 0 .../poly/{include => }/ltt/facility.h | 0 ltt/branches/poly/{include => }/ltt/ltt.h | 0 ltt/branches/poly/{include => }/ltt/time.h | 0 ltt/branches/poly/{include => }/ltt/trace.h | 0 ltt/branches/poly/{include => }/ltt/type.h | 0 ltt/branches/poly/lttv/main/attribute.c | 161 +++++ ltt/branches/poly/lttv/main/processTrace.c | 22 +- ltt/branches/poly/lttv/main/state.c | 236 +++++-- ltt/branches/poly/lttv/main/stats.c | 608 +++++------------- .../lttv/modules/gui/statistics/statistics.c | 6 +- .../poly/lttv/modules/text/batchtest.c | 121 +++- .../poly/lttv/modules/text/textDump.c | 1 + 21 files changed, 704 insertions(+), 512 deletions(-) delete mode 100644 ltt/branches/poly/include/ltt/Makefile.am rename ltt/branches/poly/{include => }/ltt/event.h (100%) rename ltt/branches/poly/{include => }/ltt/facility.h (100%) rename ltt/branches/poly/{include => }/ltt/ltt.h (100%) rename ltt/branches/poly/{include => }/ltt/time.h (100%) rename ltt/branches/poly/{include => }/ltt/trace.h (100%) rename ltt/branches/poly/{include => }/ltt/type.h (100%) diff --git a/ltt/branches/poly/configure.in b/ltt/branches/poly/configure.in index 47baf9d2..193f3414 100644 --- a/ltt/branches/poly/configure.in +++ b/ltt/branches/poly/configure.in @@ -109,7 +109,6 @@ AC_CONFIG_FILES([Makefile lttd/Makefile ltt/Makefile include/Makefile - include/ltt/Makefile ltt/convert/Makefile include/lttv/Makefile]) AC_OUTPUT diff --git a/ltt/branches/poly/include/Makefile.am b/ltt/branches/poly/include/Makefile.am index fdd2bdb6..1a1d52d1 100644 --- a/ltt/branches/poly/include/Makefile.am +++ b/ltt/branches/poly/include/Makefile.am @@ -1 +1 @@ -SUBDIRS = ltt lttv +SUBDIRS = lttv diff --git a/ltt/branches/poly/include/ltt/Makefile.am b/ltt/branches/poly/include/ltt/Makefile.am deleted file mode 100644 index 2ffd9244..00000000 --- a/ltt/branches/poly/include/ltt/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -lttinclude_HEADERS = \ - event.h\ - facility.h\ - ltt.h\ - time.h\ - trace.h\ - type.h diff --git a/ltt/branches/poly/include/lttv/attribute.h b/ltt/branches/poly/include/lttv/attribute.h index dedae373..e721b3bf 100644 --- a/ltt/branches/poly/include/lttv/attribute.h +++ b/ltt/branches/poly/include/lttv/attribute.h @@ -21,6 +21,7 @@ #include #include +#include #define LTTV_ATTRIBUTE_TYPE (lttv_attribute_get_type ()) #define LTTV_ATTRIBUTE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), LTTV_ATTRIBUTE_TYPE, LttvAttribute)) @@ -112,4 +113,9 @@ void lttv_attribute_recursive_free(LttvAttribute *self); void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src); +void +lttv_attribute_write_xml(LttvAttribute *self, FILE *fp, int pos, int indent); + +void lttv_attribute_read_xml(LttvAttribute *self, FILE *fp); + #endif // ATTRIBUTE_H diff --git a/ltt/branches/poly/include/lttv/gtktraceset.h b/ltt/branches/poly/include/lttv/gtktraceset.h index 392e3205..19035482 100644 --- a/ltt/branches/poly/include/lttv/gtktraceset.h +++ b/ltt/branches/poly/include/lttv/gtktraceset.h @@ -16,6 +16,34 @@ * MA 02111-1307, USA. */ +/* +CHECK Rename to viewer.h + +Things that can happen to a viewer: + +update_time_window +update_current_time +update_traceset +update_filter +show_viewer +update_dividor +?? Reshape, damage ?? + +Things that a viewer can do: + +update_status +set_time_window +set_current_time +update_traceset? +update_filter? +show_viewer? +set_focused_pane +set_hpane_dividor +*/ + + + + /*! \file gtktraceset.h * \brief API used by the graphical viewers to interact with their top window. * @@ -350,6 +378,10 @@ void unreg_update_dividor(LttvHook hook, gpointer hook_data, void set_hpane_dividor(MainWindow *main_win, gint position); +/* +CHECK These functions really should not appear here. Directr calls would +be OK unless there is a linker problem. +*/ /** * Function to process traceset. It will call lttv_process_trace, * each view will call this api to get events. diff --git a/ltt/branches/poly/include/lttv/state.h b/ltt/branches/poly/include/lttv/state.h index fb2fa998..85b90498 100644 --- a/ltt/branches/poly/include/lttv/state.h +++ b/ltt/branches/poly/include/lttv/state.h @@ -214,7 +214,7 @@ void lttv_state_save(LttvTraceState *self, LttvAttribute *container); void lttv_state_restore(LttvTraceState *self, LttvAttribute *container); -void lttv_state_saved_state_free(LttvTraceState *self, +void lttv_state_state_saved_free(LttvTraceState *self, LttvAttribute *container); diff --git a/ltt/branches/poly/include/lttv/stats.h b/ltt/branches/poly/include/lttv/stats.h index ad941ad3..37d36945 100644 --- a/ltt/branches/poly/include/lttv/stats.h +++ b/ltt/branches/poly/include/lttv/stats.h @@ -150,9 +150,9 @@ gboolean lttv_stats_add_event_hooks(LttvTracesetStats *self); gboolean lttv_stats_remove_event_hooks(LttvTracesetStats *self); -void lttv_stats_save_statistics(LttvTracesetStats *self); +void lttv_stats_sum_traceset(LttvTracesetStats *self); -gboolean lttv_stats_load_statistics(LttvTracesetStats *self); +void lttv_stats_sum_trace(LttvTraceStats *self); /* The LttvTracesetStats, LttvTraceStats and LttvTracefileStats types diff --git a/ltt/branches/poly/ltt/Makefile.am b/ltt/branches/poly/ltt/Makefile.am index 92e4dcef..cc5eed55 100644 --- a/ltt/branches/poly/ltt/Makefile.am +++ b/ltt/branches/poly/ltt/Makefile.am @@ -15,5 +15,12 @@ lib_LTLIBRARIES = libtraceread.la libtraceread_la_SOURCES = event.c facility.c parser.c tracefile.c type.c noinst_HEADERS = parser.h ltt-private.h +lttinclude_HEADERS = \ + event.h\ + facility.h\ + ltt.h\ + time.h\ + trace.h\ + type.h EXTRA_DIST = crc32.tab diff --git a/ltt/branches/poly/include/ltt/event.h b/ltt/branches/poly/ltt/event.h similarity index 100% rename from ltt/branches/poly/include/ltt/event.h rename to ltt/branches/poly/ltt/event.h diff --git a/ltt/branches/poly/include/ltt/facility.h b/ltt/branches/poly/ltt/facility.h similarity index 100% rename from ltt/branches/poly/include/ltt/facility.h rename to ltt/branches/poly/ltt/facility.h diff --git a/ltt/branches/poly/include/ltt/ltt.h b/ltt/branches/poly/ltt/ltt.h similarity index 100% rename from ltt/branches/poly/include/ltt/ltt.h rename to ltt/branches/poly/ltt/ltt.h diff --git a/ltt/branches/poly/include/ltt/time.h b/ltt/branches/poly/ltt/time.h similarity index 100% rename from ltt/branches/poly/include/ltt/time.h rename to ltt/branches/poly/ltt/time.h diff --git a/ltt/branches/poly/include/ltt/trace.h b/ltt/branches/poly/ltt/trace.h similarity index 100% rename from ltt/branches/poly/include/ltt/trace.h rename to ltt/branches/poly/ltt/trace.h diff --git a/ltt/branches/poly/include/ltt/type.h b/ltt/branches/poly/ltt/type.h similarity index 100% rename from ltt/branches/poly/include/ltt/type.h rename to ltt/branches/poly/ltt/type.h diff --git a/ltt/branches/poly/lttv/main/attribute.c b/ltt/branches/poly/lttv/main/attribute.c index fcdc8329..a3f8ab9a 100644 --- a/ltt/branches/poly/lttv/main/attribute.c +++ b/ltt/branches/poly/lttv/main/attribute.c @@ -307,6 +307,167 @@ void lttv_attribute_recursive_add(LttvAttribute *dest, LttvAttribute *src) } +static void +print_indent(FILE *fp, int pos) +{ + int i; + + for(i = 0 ; i < pos ; i++) putc(' ', fp); +} + + +void +lttv_attribute_write_xml(LttvAttribute *self, FILE *fp, int pos, int indent) +{ + int i, nb; + + Attribute *a; + + nb = self->attributes->len; + + fprintf(fp,"\n"); + for(i = 0 ; i < nb ; i++) { + a = &g_array_index(self->attributes, Attribute, i); + print_indent(fp, pos); + fprintf(fp, "name); + if(a->type == LTTV_GOBJECT && LTTV_IS_ATTRIBUTE(a->value.dv_gobject)) { + fprintf(fp, "TYPE=ATTRS>"); + lttv_attribute_write_xml((LttvAttribute *)(a->value.dv_gobject), fp, + pos + indent, indent); + } + else { + switch(a->type) { + case LTTV_INT: + fprintf(fp, "TYPE=INT VALUE=%d/>\n", a->value.dv_int); + break; + case LTTV_UINT: + fprintf(fp, "TYPE=UINT VALUE=%u/>\n", a->value.dv_uint); + break; + case LTTV_LONG: + fprintf(fp, "TYPE=LONG VALUE=%ld/>\n", a->value.dv_long); + break; + case LTTV_ULONG: + fprintf(fp, "TYPE=ULONG VALUE=%lu/>\n", a->value.dv_ulong); + break; + case LTTV_FLOAT: + fprintf(fp, "TYPE=FLOAT VALUE=%f/>\n", a->value.dv_float); + break; + case LTTV_DOUBLE: + fprintf(fp, "TYPE=DOUBLE VALUE=%f/>\n", a->value.dv_double); + break; + case LTTV_TIME: + fprintf(fp, "TYPE=TIME SEC=%u NSEC=%u/>\n", a->value.dv_time.tv_sec, + a->value.dv_time.tv_nsec); + break; + case LTTV_POINTER: + fprintf(fp, "TYPE=POINTER VALUE=%p/>\n", a->value.dv_pointer); + break; + case LTTV_STRING: + fprintf(fp, "TYPE=STRING VALUE=\"%s\"/>\n", a->value.dv_string); + break; + case LTTV_GOBJECT: + fprintf(fp, "TYPE=GOBJECT VALUE=%p/>\n", a->value.dv_gobject); + break; + case LTTV_NONE: + fprintf(fp, "TYPE=NONE/>\n"); + break; + } + } + } + print_indent(fp, pos); + fprintf(fp,"\n"); +} + + +void +lttv_attribute_read_xml(LttvAttribute *self, FILE *fp) +{ + int i, nb, res; + + Attribute *a; + + char buffer[256], type[10]; + + LttvAttributeName name; + + LttvAttributeValue value; + + LttvAttribute *subtree; + + fscanf(fp,""); + while(1) { + res = fscanf(fp, "]", buffer, type); + g_assert(res == 2); + name = g_quark_from_string(buffer); + if(strcmp(type, "ATTRS") == 0) { + fscanf(fp, ">"); + subtree = lttv_attribute_find_subdir(self, name); + lttv_attribute_read_xml(subtree, fp); + } + else if(strcmp(type, "INT") == 0) { + value = lttv_attribute_add(self, name, LTTV_INT); + res = fscanf(fp, " VALUE=%d/>", value.v_int); + g_assert(res == 1); + } + else if(strcmp(type, "UINT") == 0) { + value = lttv_attribute_add(self, name, LTTV_UINT); + res = fscanf(fp, " VALUE=%u/>", value.v_uint); + g_assert(res == 1); + } + else if(strcmp(type, "LONG") == 0) { + value = lttv_attribute_add(self, name, LTTV_LONG); + res = fscanf(fp, " VALUE=%ld/>", value.v_long); + g_assert(res == 1); + } + else if(strcmp(type, "ULONG") == 0) { + value = lttv_attribute_add(self, name, LTTV_ULONG); + res = fscanf(fp, " VALUE=%lu/>", value.v_ulong); + g_assert(res == 1); + } + else if(strcmp(type, "FLOAT") == 0) { + float d; + value = lttv_attribute_add(self, name, LTTV_FLOAT); + res = fscanf(fp, " VALUE=%f/>", &d); + *(value.v_float) = d; + g_assert(res == 1); + } + else if(strcmp(type, "DOUBLE") == 0) { + value = lttv_attribute_add(self, name, LTTV_DOUBLE); + res = fscanf(fp, " VALUE=%f/>", value.v_double); + g_assert(res == 1); + } + else if(strcmp(type, "TIME") == 0) { + value = lttv_attribute_add(self, name, LTTV_TIME); + res = fscanf(fp, " SEC=%u NSEC=%u/>", &(value.v_time->tv_sec), + &(value.v_time->tv_nsec)); + g_assert(res == 2); + } + else if(strcmp(type, "POINTER") == 0) { + value = lttv_attribute_add(self, name, LTTV_POINTER); + res = fscanf(fp, " VALUE=%p/>", value.v_pointer); + g_error("Cannot read a pointer"); + } + else if(strcmp(type, "STRING") == 0) { + value = lttv_attribute_add(self, name, LTTV_STRING); + res = fscanf(fp, " VALUE=\"%256[^\"]\"/>", buffer); + *(value.v_string) = g_strdup(buffer); + g_assert(res == 1); + } + else if(strcmp(type, "GOBJECT") == 0) { + value = lttv_attribute_add(self, name, LTTV_GOBJECT); + res = fscanf(fp, " VALUE=%p/>", value.v_gobject); + g_error("Cannot read a pointer"); + } + else if(strcmp(type, "NONE") == 0) { + value = lttv_attribute_add(self, name, LTTV_NONE); + fscanf(fp, "/>"); + } + else g_error("Unknown type to read"); + } + fscanf(fp,""); +} + + static void attribute_interface_init (gpointer g_iface, gpointer iface_data) { diff --git a/ltt/branches/poly/lttv/main/processTrace.c b/ltt/branches/poly/lttv/main/processTrace.c index c811da0e..cb50c0a3 100644 --- a/ltt/branches/poly/lttv/main/processTrace.c +++ b/ltt/branches/poly/lttv/main/processTrace.c @@ -564,7 +564,20 @@ lttv_tracefile_context_get_type(void) gint compare_tracefile(gconstpointer a, gconstpointer b) { - return ltt_time_compare(*((LttTime *)a), *((LttTime *)b)); + gint comparison; + + LttvTracefileContext *trace_a = (LttvTracefileContext *)a; + + LttvTracefileContext *trace_b = (LttvTracefileContext *)b; + + if(trace_a == trace_b) return 0; + comparison = ltt_time_compare(trace_a->timestamp, trace_b->timestamp); + if(comparison != 0) return comparison; + if(trace_a->index < trace_b->index) return -1; + else if(trace_a->index > trace_b->index) return 1; + if(trace_a->t_context->index < trace_b->t_context->index) return -1; + else if(trace_a->t_context->index > trace_b->t_context->index) return 1; + g_assert(FALSE); } @@ -608,7 +621,7 @@ void lttv_process_traceset_begin(LttvTracesetContext *self, LttTime end) if(tfc->timestamp.tv_sec < end.tv_sec || (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec)) { - g_tree_insert(self->pqueue, &(tfc->timestamp), tfc); + g_tree_insert(self->pqueue, tfc, tfc); } } } @@ -660,8 +673,7 @@ guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end, or more tracefiles have events for the same time, hope that lookup and remove are consistent. */ - tfc = g_tree_lookup(pqueue, &(tfc->timestamp)); - g_tree_remove(pqueue, &(tfc->timestamp)); + g_tree_remove(pqueue, tfc); count++; if(!lttv_hooks_call(tfc->check_event, tfc)) { @@ -678,7 +690,7 @@ guint lttv_process_traceset_middle(LttvTracesetContext *self, LttTime end, tfc->timestamp = ltt_event_time(event); if(tfc->timestamp.tv_sec < end.tv_sec || (tfc->timestamp.tv_sec == end.tv_sec && tfc->timestamp.tv_nsec <= end.tv_nsec)) - g_tree_insert(pqueue, &(tfc->timestamp), tfc); + g_tree_insert(pqueue, tfc, tfc); } } } diff --git a/ltt/branches/poly/lttv/main/state.c b/ltt/branches/poly/lttv/main/state.c index c69d6a6a..0624fe4b 100644 --- a/ltt/branches/poly/lttv/main/state.c +++ b/ltt/branches/poly/lttv/main/state.c @@ -24,6 +24,7 @@ #include #include #include +#include LttvExecutionMode LTTV_STATE_MODE_UNKNOWN, @@ -52,13 +53,25 @@ static GQuark LTTV_STATE_SAVED_STATES, LTTV_STATE_SAVED_STATES_TIME, LTTV_STATE_TIME, - LTTV_STATE_HOOKS; + LTTV_STATE_HOOKS, + LTTV_STATE_NAME_TABLES, + LTTV_STATE_TRACE_STATE_USE_COUNT; -static void fill_name_tables(LttvTraceState *tcs); +static void create_max_time(LttvTraceState *tcs); + +static void get_max_time(LttvTraceState *tcs); + +static void free_max_time(LttvTraceState *tcs); + +static void create_name_tables(LttvTraceState *tcs); + +static void get_name_tables(LttvTraceState *tcs); static void free_name_tables(LttvTraceState *tcs); +static void free_saved_state(LttvTraceState *tcs); + static void lttv_state_free_process_table(GHashTable *processes); @@ -74,10 +87,10 @@ void lttv_state_restore(LttvTraceState *self, LttvAttribute *container) } -void lttv_state_saved_state_free(LttvTraceState *self, +void lttv_state__state_saved_free(LttvTraceState *self, LttvAttribute *container) { - LTTV_TRACE_STATE_GET_CLASS(self)->state_restore(self, container); + LTTV_TRACE_STATE_GET_CLASS(self)->state_saved_free(self, container); } @@ -150,15 +163,16 @@ init(LttvTracesetState *self, LttvTraceset *ts) tc = self->parent.traces[i]; tcs = (LttvTraceState *)tc; tcs->save_interval = 50000; - lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, - LTTV_POINTER, &v); - if(*(v.v_pointer) == NULL) { - *(v.v_pointer) = g_new(LttTime,1); - *((LttTime *)*(v.v_pointer)) = time_zero; - } - tcs->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer); + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT, + LTTV_UINT, &v); + (*v.v_uint)++; - fill_name_tables(tcs); + if(*(v.v_uint) == 1) { + create_name_tables(tcs); + create_max_time(tcs); + } + get_name_tables(tcs); + get_max_time(tcs); nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + ltt_trace_per_cpu_tracefile_number(tc->t); @@ -182,12 +196,23 @@ fini(LttvTracesetState *self) LttvTracefileState *tfcs; + LttvAttributeValue v; + nb_trace = lttv_traceset_number(LTTV_TRACESET_CONTEXT(self)->ts); for(i = 0 ; i < nb_trace ; i++) { tcs = (LttvTraceState *)(LTTV_TRACESET_CONTEXT(self)->traces[i]); + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_TRACE_STATE_USE_COUNT, + LTTV_UINT, &v); + (*v.v_uint)--; + + g_assert(*(v.v_uint) >= 0); + if(*(v.v_uint) == 0) { + free_name_tables(tcs); + free_max_time(tcs); + free_saved_state(tcs); + } lttv_state_free_process_table(tcs->processes); tcs->processes = NULL; - free_name_tables(tcs); } LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_CONTEXT_TYPE))-> fini((LttvTracesetContext *)self); @@ -230,8 +255,8 @@ static void write_process_state(gpointer key, gpointer value, process = (LttvProcessState *)value; fprintf(fp, -" \n", - process->pid, process->ppid, process->creation_time.tv_sec, +" \n", + process, process->pid, process->ppid, process->creation_time.tv_sec, process->creation_time.tv_nsec, g_quark_to_string(process->name), g_quark_to_string(process->last_cpu)); @@ -476,8 +501,80 @@ static void state_saved_free(LttvTraceState *self, LttvAttribute *container) } +static void free_saved_state(LttvTraceState *self) +{ + guint i, nb; + + LttvAttributeType type; + + LttvAttributeValue value; + + LttvAttributeName name; + + LttvAttribute *saved_states; + + saved_states = lttv_attribute_find_subdir(self->parent.t_a, + LTTV_STATE_SAVED_STATES); + + nb = lttv_attribute_get_number(saved_states); + for(i = 0 ; i < nb ; i++) { + type = lttv_attribute_get(saved_states, i, &name, &value); + g_assert(type == LTTV_GOBJECT); + state_saved_free(self, *((LttvAttribute **)value.v_gobject)); + } + + lttv_attribute_remove_by_name(self->parent.t_a, LTTV_STATE_SAVED_STATES); + lttv_attribute_recursive_free(saved_states); +} + + +static void +create_max_time(LttvTraceState *tcs) +{ + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, + LTTV_POINTER, &v); + g_assert(*(v.v_pointer) == NULL); + *(v.v_pointer) = g_new(LttTime,1); + *((LttTime *)*(v.v_pointer)) = time_zero; +} + + +static void +get_max_time(LttvTraceState *tcs) +{ + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, + LTTV_POINTER, &v); + g_assert(*(v.v_pointer) != NULL); + tcs->max_time_state_recomputed_in_seek = (LttTime *)*(v.v_pointer); +} + + +static void +free_max_time(LttvTraceState *tcs) +{ + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_SAVED_STATES_TIME, + LTTV_POINTER, &v); + g_free(*(v.v_pointer)); + *(v.v_pointer) = NULL; +} + + +typedef struct _LttvNameTables { + GQuark *eventtype_names; + GQuark *syscall_names; + GQuark *trap_names; + GQuark *irq_names; +} LttvNameTables; + + static void -fill_name_tables(LttvTraceState *tcs) +create_name_tables(LttvTraceState *tcs) { int i, nb; @@ -491,14 +588,23 @@ fill_name_tables(LttvTraceState *tcs) GString *fe_name = g_string_new(""); + LttvNameTables *name_tables = g_new(LttvNameTables, 1); + + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + LTTV_POINTER, &v); + g_assert(*(v.v_pointer) == NULL); + *(v.v_pointer) = name_tables; + nb = ltt_trace_eventtype_number(tcs->parent.t); - tcs->eventtype_names = g_new(GQuark, nb); + name_tables->eventtype_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { et = ltt_trace_eventtype_get(tcs->parent.t, i); e_name = ltt_eventtype_name(et); f_name = ltt_facility_name(ltt_eventtype_facility(et)); g_string_printf(fe_name, "%s.%s", f_name, e_name); - tcs->eventtype_names[i] = g_quark_from_string(fe_name->str); + name_tables->eventtype_names[i] = g_quark_from_string(fe_name->str); } lttv_trace_find_hook(tcs->parent.t, "core", "syscall_entry", @@ -507,17 +613,18 @@ fill_name_tables(LttvTraceState *tcs) nb = ltt_type_element_number(t); /* CHECK syscalls should be an emun but currently are not! - tcs->syscall_names = g_new(GQuark, nb); + name_tables->syscall_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { - tcs->syscall_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + name_tables->syscall_names[i] = g_quark_from_string( + ltt_enum_string_get(t, i)); } */ - tcs->syscall_names = g_new(GQuark, 256); + name_tables->syscall_names = g_new(GQuark, 256); for(i = 0 ; i < 256 ; i++) { g_string_printf(fe_name, "syscall %d", i); - tcs->syscall_names[i] = g_quark_from_string(fe_name->str); + name_tables->syscall_names[i] = g_quark_from_string(fe_name->str); } lttv_trace_find_hook(tcs->parent.t, "core", "trap_entry", @@ -526,16 +633,17 @@ fill_name_tables(LttvTraceState *tcs) nb = ltt_type_element_number(t); /* - tcs->trap_names = g_new(GQuark, nb); + name_tables->trap_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { - tcs->trap_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + name_tables->trap_names[i] = g_quark_from_string( + ltt_enum_string_get(t, i)); } */ - tcs->trap_names = g_new(GQuark, 256); + name_tables->trap_names = g_new(GQuark, 256); for(i = 0 ; i < 256 ; i++) { g_string_printf(fe_name, "trap %d", i); - tcs->trap_names[i] = g_quark_from_string(fe_name->str); + name_tables->trap_names[i] = g_quark_from_string(fe_name->str); } lttv_trace_find_hook(tcs->parent.t, "core", "irq_entry", @@ -544,29 +652,57 @@ fill_name_tables(LttvTraceState *tcs) nb = ltt_type_element_number(t); /* - tcs->irq_names = g_new(GQuark, nb); + name_tables->irq_names = g_new(GQuark, nb); for(i = 0 ; i < nb ; i++) { - tcs->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); + name_tables->irq_names[i] = g_quark_from_string(ltt_enum_string_get(t, i)); } */ - tcs->irq_names = g_new(GQuark, 256); + name_tables->irq_names = g_new(GQuark, 256); for(i = 0 ; i < 256 ; i++) { g_string_printf(fe_name, "irq %d", i); - tcs->irq_names[i] = g_quark_from_string(fe_name->str); + name_tables->irq_names[i] = g_quark_from_string(fe_name->str); } g_string_free(fe_name, TRUE); } +static void +get_name_tables(LttvTraceState *tcs) +{ + LttvNameTables *name_tables; + + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + LTTV_POINTER, &v); + g_assert(*(v.v_pointer) != NULL); + name_tables = (LttvNameTables *)*(v.v_pointer); + tcs->eventtype_names = name_tables->eventtype_names; + tcs->syscall_names = name_tables->syscall_names; + tcs->trap_names = name_tables->trap_names; + tcs->irq_names = name_tables->irq_names; +} + + static void free_name_tables(LttvTraceState *tcs) { - g_free(tcs->eventtype_names); - g_free(tcs->syscall_names); - g_free(tcs->trap_names); - g_free(tcs->irq_names); + LttvNameTables *name_tables; + + LttvAttributeValue v; + + lttv_attribute_find(tcs->parent.t_a, LTTV_STATE_NAME_TABLES, + LTTV_POINTER, &v); + name_tables = (LttvNameTables *)*(v.v_pointer); + *(v.v_pointer) = NULL; + + g_free(name_tables->eventtype_names); + g_free(name_tables->syscall_names); + g_free(name_tables->trap_names); + g_free(name_tables->irq_names); + g_free(name_tables); } @@ -593,7 +729,7 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) { LttvProcessState *process = tfs->process; - guint depth = process->execution_stack->len - 1; + guint depth = process->execution_stack->len; if(process->state->t != t){ g_info("Different execution mode type (%d.%09d): ignore it\n", @@ -609,16 +745,15 @@ static void pop_state(LttvTracefileState *tfs, LttvExecutionMode t) return; } - if(depth == 0){ + if(depth == 1){ g_info("Trying to pop last state on stack (%d.%09d): ignore it\n", tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); return; } - g_array_remove_index(process->execution_stack, depth); - depth--; + g_array_set_size(process->execution_stack, depth - 1); process->state = &g_array_index(process->execution_stack, LttvExecutionState, - depth); + depth - 2); process->state->change = tfs->parent.timestamp; } @@ -637,10 +772,11 @@ lttv_state_create_process(LttvTracefileState *tfs, LttvProcessState *parent, char buffer[128]; - tcs = (LttvTraceState *)tc = tfs->parent.t_context; + tcs = ((LttvTraceState *)tc = tfs->parent.t_context); process->pid = pid; process->last_cpu = tfs->cpu_name; + g_warning("Process %u, core %p", process->pid, process); g_hash_table_insert(tcs->processes, process, process); if(parent) { @@ -825,14 +961,21 @@ static gboolean schedchange(void *hook_data, void *call_data) if(s->process != NULL) { + /* We could not know but it was not the idle process executing. + This should only happen at the beginning, before the first schedule + event, and when the initial information (current process for each CPU) + is missing. It is not obvious how we could, after the fact, compensate + the wrongly attributed statistics. */ + + if(s->process->pid != pid_out) { + g_assert(s->process->pid == 0); + } + if(state_out == 0) s->process->state->s = LTTV_STATE_WAIT_CPU; else if(s->process->state->s == LTTV_STATE_EXIT) exit_process(s, s->process); else s->process->state->s = LTTV_STATE_WAIT; - if(s->process->pid == 0) - s->process->pid = pid_out; - s->process->state->change = s->parent.timestamp; } s->process = lttv_state_find_process_or_create(s, pid_in); @@ -1175,7 +1318,9 @@ void lttv_state_traceset_seek_time_closest(LttvTracesetState *self, LttTime t) } /* restore the closest earlier saved state */ - if(min_pos != -1) lttv_state_restore(tcs, closest_tree); + if(min_pos != -1) { + lttv_state_restore(tcs, closest_tree); + } /* There is no saved state, yet we want to have it. Restart at T0 */ else { @@ -1364,6 +1509,9 @@ static void module_init() LTTV_STATE_SAVED_STATES_TIME = g_quark_from_string("saved states time"); LTTV_STATE_TIME = g_quark_from_string("time"); LTTV_STATE_HOOKS = g_quark_from_string("saved state hooks"); + LTTV_STATE_NAME_TABLES = g_quark_from_string("name tables"); + LTTV_STATE_TRACE_STATE_USE_COUNT = + g_quark_from_string("trace_state_use_count"); } static void module_destroy() diff --git a/ltt/branches/poly/lttv/main/stats.c b/ltt/branches/poly/lttv/main/stats.c index c577ab77..d5cd80b4 100644 --- a/ltt/branches/poly/lttv/main/stats.c +++ b/ltt/branches/poly/lttv/main/stats.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,11 @@ GQuark LTTV_STATS_CPU_TIME, LTTV_STATS_ELAPSED_TIME, LTTV_STATS_EVENTS, - LTTV_STATS_EVENTS_COUNT; + LTTV_STATS_EVENTS_COUNT, + LTTV_STATS_USE_COUNT, + LTTV_STATS, + LTTV_STATS_TRACEFILES, + LTTV_STATS_SUMMED; static GQuark LTTV_STATS_BEFORE_HOOKS, @@ -66,22 +71,47 @@ init(LttvTracesetStats *self, LttvTraceset *ts) LttTime timestamp = {0,0}; + LttvAttributeValue v; + + LttvAttribute + *stats_tree, + *tracefiles_stats; + LTTV_TRACESET_CONTEXT_CLASS(g_type_class_peek(LTTV_TRACESET_STATE_TYPE))-> init((LttvTracesetContext *)self, ts); - self->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + self->stats =lttv_attribute_find_subdir(self->parent.parent.ts_a,LTTV_STATS); + lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT, + LTTV_UINT, &v); + + *(v.v_uint)++; + if(*(v.v_uint) == 1) { + g_assert(lttv_attribute_get_number(self->stats) == 0); + } + nb_trace = lttv_traceset_number(ts); for(i = 0 ; i < nb_trace ; i++) { tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); - tcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + + tcs->stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a,LTTV_STATS); + tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a, + LTTV_STATS_TRACEFILES); + lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT, + LTTV_UINT, &v); + + *(v.v_uint)++; + if(*(v.v_uint) == 1) { + g_assert(lttv_attribute_get_number(tcs->stats) == 0); + } nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + ltt_trace_per_cpu_tracefile_number(tc->t); for(j = 0 ; j < nb_tracefile ; j++) { tfcs = LTTV_TRACEFILE_STATS(tc->tracefiles[j]); - tfcs->stats = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL); + tfcs->stats = lttv_attribute_find_subdir(tracefiles_stats, + tfcs->parent.cpu_name); find_event_tree(tfcs, LTTV_STATS_PROCESS_UNKNOWN, tfcs->parent.cpu_name, LTTV_STATE_MODE_UNKNOWN, LTTV_STATE_SUBMODE_UNKNOWN, &tfcs->current_events_tree, @@ -108,20 +138,47 @@ fini(LttvTracesetStats *self) LttTime timestamp = {0,0}; - lttv_attribute_recursive_free(self->stats); + LttvAttributeValue v; + + LttvAttribute *tracefiles_stats; + + lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_USE_COUNT, + LTTV_UINT, &v); + *(v.v_uint)--; + + if(*(v.v_uint) == 0) { + lttv_attribute_remove_by_name(self->parent.parent.ts_a, LTTV_STATS); + lttv_attribute_recursive_free(self->stats); + } + self->stats = NULL; + ts = self->parent.parent.ts; nb_trace = lttv_traceset_number(ts); for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)tc = (LTTV_TRACESET_CONTEXT(self)->traces[i]); - lttv_attribute_recursive_free(tcs->stats); + tcs = (LttvTraceStats *)(tc = (LTTV_TRACESET_CONTEXT(self)->traces[i])); + + lttv_attribute_find(tcs->parent.parent.t_a, LTTV_STATS_USE_COUNT, + LTTV_UINT, &v); + *(v.v_uint)--; + + if(*(v.v_uint) == 0) { + lttv_attribute_remove_by_name(tcs->parent.parent.t_a,LTTV_STATS); + lttv_attribute_recursive_free(tcs->stats); + tracefiles_stats = lttv_attribute_find_subdir(tcs->parent.parent.t_a, + LTTV_STATS_TRACEFILES); + lttv_attribute_remove_by_name(tcs->parent.parent.t_a, + LTTV_STATS_TRACEFILES); + lttv_attribute_recursive_free(tracefiles_stats); + } + tcs->stats = NULL; nb_tracefile = ltt_trace_control_tracefile_number(tc->t) + ltt_trace_per_cpu_tracefile_number(tc->t); for(j = 0 ; j < nb_tracefile ; j++) { - tfcs = (LttvTracefileStats *)tfc = tc->tracefiles[j]; - lttv_attribute_recursive_free(tfcs->stats); + tfcs = ((LttvTracefileStats *)tfc = tc->tracefiles[j]); + tfcs->stats = NULL; tfcs->current_events_tree = NULL; tfcs->current_event_types_tree = NULL; } @@ -516,15 +573,11 @@ gboolean every_event(void *hook_data, void *call_data) } -static gboolean -sum_stats(void *hook_data, void *call_data) +void +lttv_stats_sum_trace(LttvTraceStats *self) { - LttvTracesetStats *tscs = (LttvTracesetStats *)call_data; - LttvTraceStats *tcs; - LttvTraceset *traceset = tscs->parent.parent.ts; - LttvAttributeType type; LttvAttributeValue value; @@ -533,86 +586,115 @@ sum_stats(void *hook_data, void *call_data) unsigned sum; - int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode, + int i, j, k, l, m, nb_process, nb_cpu, nb_mode_type, nb_submode, nb_event_type; LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, *submode_tree, *event_types_tree, *mode_events_tree, *cpu_events_tree, *process_modes_tree, *trace_cpu_tree, - *trace_modes_tree, *traceset_modes_tree; - - traceset_modes_tree = lttv_attribute_find_subdir(tscs->stats, - LTTV_STATS_MODES); - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - main_tree = tcs->stats; - processes_tree = lttv_attribute_find_subdir(main_tree, - LTTV_STATS_PROCESSES); - trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES); - nb_process = lttv_attribute_get_number(processes_tree); - - for(j = 0 ; j < nb_process ; j++) { - type = lttv_attribute_get(processes_tree, j, &name, &value); - process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + *trace_modes_tree; + + main_tree = self->stats; + + lttv_attribute_find(self->parent.parent.t_a, LTTV_STATS_SUMMED, + LTTV_UINT, &value); + if(*(value.v_uint) != 0) return; + *(value.v_uint) = 1; + + processes_tree = lttv_attribute_find_subdir(main_tree, + LTTV_STATS_PROCESSES); + trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES); + nb_process = lttv_attribute_get_number(processes_tree); + + for(i = 0 ; i < nb_process ; i++) { + type = lttv_attribute_get(processes_tree, i, &name, &value); + process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); + process_modes_tree = lttv_attribute_find_subdir(process_tree, + LTTV_STATS_MODES); + nb_cpu = lttv_attribute_get_number(cpus_tree); + + for(j = 0 ; j < nb_cpu ; j++) { + type = lttv_attribute_get(cpus_tree, j, &name, &value); + cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + mode_types_tree = lttv_attribute_find_subdir(cpu_tree, + LTTV_STATS_MODE_TYPES); + cpu_events_tree = lttv_attribute_find_subdir(cpu_tree, + LTTV_STATS_EVENTS); + trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU); + trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name); + nb_mode_type = lttv_attribute_get_number(mode_types_tree); + + for(k = 0 ; k < nb_mode_type ; k++) { + type = lttv_attribute_get(mode_types_tree, k, &name, &value); + mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + + submodes_tree = lttv_attribute_find_subdir(mode_tree, + LTTV_STATS_SUBMODES); + mode_events_tree = lttv_attribute_find_subdir(mode_tree, + LTTV_STATS_EVENTS); + nb_submode = lttv_attribute_get_number(submodes_tree); - cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); - process_modes_tree = lttv_attribute_find_subdir(process_tree, - LTTV_STATS_MODES); - nb_cpu = lttv_attribute_get_number(cpus_tree); + for(l = 0 ; l < nb_submode ; l++) { + type = lttv_attribute_get(submodes_tree, l, &name, &value); + submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - for(k = 0 ; k < nb_cpu ; k++) { - type = lttv_attribute_get(cpus_tree, k, &name, &value); - cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); + event_types_tree = lttv_attribute_find_subdir(submode_tree, + LTTV_STATS_EVENT_TYPES); + nb_event_type = lttv_attribute_get_number(event_types_tree); - mode_types_tree = lttv_attribute_find_subdir(cpu_tree, - LTTV_STATS_MODE_TYPES); - cpu_events_tree = lttv_attribute_find_subdir(cpu_tree, - LTTV_STATS_EVENTS); - trace_cpu_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_CPU); - trace_cpu_tree = lttv_attribute_find_subdir(trace_cpu_tree, name); - nb_mode_type = lttv_attribute_get_number(mode_types_tree); - - for(l = 0 ; l < nb_mode_type ; l++) { - type = lttv_attribute_get(mode_types_tree, l, &name, &value); - mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - submodes_tree = lttv_attribute_find_subdir(mode_tree, - LTTV_STATS_SUBMODES); - mode_events_tree = lttv_attribute_find_subdir(mode_tree, - LTTV_STATS_EVENTS); - nb_submode = lttv_attribute_get_number(submodes_tree); - - for(m = 0 ; m < nb_submode ; m++) { - type = lttv_attribute_get(submodes_tree, m, &name, &value); - submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - event_types_tree = lttv_attribute_find_subdir(submode_tree, - LTTV_STATS_EVENT_TYPES); - nb_event_type = lttv_attribute_get_number(event_types_tree); - - sum = 0; - for(n = 0 ; n < nb_event_type ; n++) { - type = lttv_attribute_get(event_types_tree, n, &name, &value); - sum += *(value.v_uint); - } - lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT, - LTTV_UINT, &value); - *(value.v_uint) = sum; - lttv_attribute_recursive_add(mode_events_tree, submode_tree); + sum = 0; + for(m = 0 ; m < nb_event_type ; m++) { + type = lttv_attribute_get(event_types_tree, m, &name, &value); + sum += *(value.v_uint); } - lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree); + lttv_attribute_find(submode_tree, LTTV_STATS_EVENTS_COUNT, + LTTV_UINT, &value); + *(value.v_uint) = sum; + lttv_attribute_recursive_add(mode_events_tree, submode_tree); } - lttv_attribute_recursive_add(process_modes_tree, cpu_tree); - lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree); + lttv_attribute_recursive_add(cpu_events_tree, mode_events_tree); } - lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree); + lttv_attribute_recursive_add(process_modes_tree, cpu_tree); + lttv_attribute_recursive_add(trace_cpu_tree, cpu_tree); } + lttv_attribute_recursive_add(trace_modes_tree, process_modes_tree); + } +} + + +void +lttv_stats_sum_traceset(LttvTracesetStats *self) +{ + LttvTraceset *traceset = self->parent.parent.ts; + + LttvTraceStats *tcs; + + int i, nb_trace; + + LttvAttribute *main_tree, *trace_modes_tree, *traceset_modes_tree; + + LttvAttributeValue value; + + lttv_attribute_find(self->parent.parent.ts_a, LTTV_STATS_SUMMED, + LTTV_UINT, &value); + if(*(value.v_uint) != 0) return; + *(value.v_uint) = 1; + + traceset_modes_tree = lttv_attribute_find_subdir(self->stats, + LTTV_STATS_MODES); + nb_trace = lttv_traceset_number(traceset); + + for(i = 0 ; i < nb_trace ; i++) { + tcs = (LttvTraceStats *)(self->parent.parent.traces[i]); + lttv_stats_sum_trace(tcs); + main_tree = tcs->stats; + trace_modes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_MODES); lttv_attribute_recursive_add(traceset_modes_tree, trace_modes_tree); } - return FALSE; } @@ -736,7 +818,6 @@ lttv_stats_add_event_hooks(LttvTracesetStats *self) LTTV_POINTER, &val); *(val.v_pointer) = after_hooks; } - lttv_hooks_add(self->parent.parent.after, sum_stats, NULL); } @@ -795,361 +876,6 @@ lttv_stats_remove_event_hooks(LttvTracesetStats *self) g_array_free(before_hooks, TRUE); g_array_free(after_hooks, TRUE); } - lttv_hooks_remove_data(self->parent.parent.after, sum_stats, NULL); -} - - -void lttv_stats_save_attribute(LttvAttribute *attr, char *indent, FILE * fp) -{ - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - char type_value[BUF_SIZE]; - int i, nb_attr, flag; - - nb_attr = lttv_attribute_get_number(attr); - for(i=0;itv_sec, - value.v_time->tv_nsec); - break; - case LTTV_POINTER: - sprintf(type_value, "POINTER\0"); - break; - case LTTV_STRING: - sprintf(type_value, "%s\0", *value.v_string); - break; - default: - flag = 0; - break; - } - if(flag == 0) continue; - fprintf(fp,"%s",indent,type,g_quark_to_string(name)); - fprintf(fp,"%s",type_value); - fprintf(fp," \n"); - } - -} - -void lttv_stats_save_statistics(LttvTracesetStats *self) -{ - LttvTracesetStats *tscs = self; - LttvTraceStats *tcs; - LttvTraceset *traceset = tscs->parent.parent.ts; - LttvAttributeType type; - LttvAttributeValue value; - LttvAttributeName name; - - char filename[BUF_SIZE]; - FILE * fp; - char indent[10][24]= {" ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " " - }; - - - int i, j, k, l, m, n, nb_trace, nb_process, nb_cpu, nb_mode_type, nb_submode; - - LttvAttribute *main_tree, *processes_tree, *process_tree, *cpus_tree, - *cpu_tree, *mode_tree, *mode_types_tree, *submodes_tree, - *submode_tree, *event_types_tree; - - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - - filename[0] = '\0'; - strcat(filename,ltt_trace_name(tcs->parent.parent.t)); - strcat(filename,"/statistics.xml"); - fp = fopen(filename,"w"); - if(!fp){ - g_warning("can not open the file %s for saving statistics\n", filename); - exit(1); - } - - main_tree = tcs->stats; - processes_tree = lttv_attribute_find_subdir(main_tree, LTTV_STATS_PROCESSES); - nb_process = lttv_attribute_get_number(processes_tree); - - fprintf(fp, " \n",g_quark_to_string(LTTV_STATS_PROCESSES)); //root NODE - - for(j = 0 ; j < nb_process ; j++) { - type = lttv_attribute_get(processes_tree, j, &name, &value); - process_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[0],g_quark_to_string(name)); //process NODE - lttv_stats_save_attribute(process_tree,indent[1], fp); - fprintf(fp,"%s \n", indent[1],g_quark_to_string(LTTV_STATS_CPU)); //cpus NODE - - cpus_tree = lttv_attribute_find_subdir(process_tree, LTTV_STATS_CPU); - nb_cpu = lttv_attribute_get_number(cpus_tree); - - for(k = 0 ; k < nb_cpu ; k++) { - type = lttv_attribute_get(cpus_tree, k, &name, &value); - cpu_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[2],g_quark_to_string(name)); //cpu NODE - lttv_stats_save_attribute(cpu_tree,indent[3], fp); - fprintf(fp,"%s \n",indent[3],g_quark_to_string(LTTV_STATS_MODE_TYPES)); //mode_types NODE - - mode_types_tree = lttv_attribute_find_subdir(cpu_tree,LTTV_STATS_MODE_TYPES); - nb_mode_type = lttv_attribute_get_number(mode_types_tree); - - for(l = 0 ; l < nb_mode_type ; l++) { - type = lttv_attribute_get(mode_types_tree, l, &name, &value); - mode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - - fprintf(fp,"%s \n",indent[4],g_quark_to_string(name)); //mode NODE - lttv_stats_save_attribute(mode_tree,indent[5], fp); - fprintf(fp,"%s \n",indent[5],g_quark_to_string(LTTV_STATS_SUBMODES)); //sub_modes NODE - - submodes_tree = lttv_attribute_find_subdir(mode_tree,LTTV_STATS_SUBMODES); - nb_submode = lttv_attribute_get_number(submodes_tree); - - for(m = 0 ; m < nb_submode ; m++) { - type = lttv_attribute_get(submodes_tree, m, &name, &value); - submode_tree = LTTV_ATTRIBUTE(*(value.v_gobject)); - fprintf(fp,"%s \n",indent[6],g_quark_to_string(name)); //sub_mode NODE - lttv_stats_save_attribute(submode_tree,indent[7], fp); - fprintf(fp,"%s \n",indent[7],g_quark_to_string(LTTV_STATS_EVENT_TYPES)); //event_types NODE - - event_types_tree = lttv_attribute_find_subdir(submode_tree, LTTV_STATS_EVENT_TYPES); - lttv_stats_save_attribute(event_types_tree,indent[8], fp); - - fprintf(fp,"%s \n",indent[7]); //event_types NODE - fprintf(fp,"%s \n",indent[6]); //sub_mode NODE - } - fprintf(fp,"%s \n",indent[5]); //sub_modes NODE - fprintf(fp,"%s \n",indent[4]); //mode NODE - } - fprintf(fp,"%s \n",indent[3]); //mode_type NODE - fprintf(fp,"%s \n",indent[2]); //cpu NODE - } - fprintf(fp,"%s \n",indent[1]); //cpus NODE - fprintf(fp,"%s \n", indent[0]); //process NODE - } - fprintf(fp, "\n"); //root NODE - fclose(fp); - } -} - - -/* Functions to parse statistic.xml file (using glib xml parser) */ - -typedef struct _ParserStruct{ - GPtrArray * attribute; - LttvAttributeType type; - LttvAttributeName name; -} ParserStruct; - -static void stats_parser_start_element (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - int len; - LttvAttributeType type; - LttvAttributeName name; - LttvAttribute * parent_att, *new_att; - - len = parser->attribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - - if(strcmp("NODE", element_name) == 0){ - type = LTTV_GOBJECT; - name = g_quark_from_string(attribute_values[0]); - new_att = lttv_attribute_find_subdir(parent_att,name); - g_ptr_array_add(parser->attribute, (gpointer)new_att); - }else if(strcmp("VALUE", element_name) == 0){ - parser->type = (LttvAttributeType) atoi(attribute_values[0]); - parser->name = g_quark_from_string(attribute_values[1]); - }else{ - g_warning("This is not statistics.xml file\n"); - exit(1); - } -} - -static void stats_parser_end_element (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - int len; - LttvAttribute * parent_att; - - len = parser->attribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - - if(strcmp("NODE", element_name) == 0){ - g_ptr_array_remove_index(parser->attribute, len-1); - }else if(strcmp("VALUE", element_name) == 0){ - }else{ - g_warning("This is not statistics.xml file\n"); - exit(1); - } - -} - -static void stats_parser_characters (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - ParserStruct * parser = (ParserStruct *)user_data; - LttvAttributeValue value; - int len; - LttvAttribute * parent_att; - char *pos; - - pos = (char*)text; - for(len=0;lenattribute->len; - parent_att = (LttvAttribute *)g_ptr_array_index (parser->attribute, len-1); - if(!lttv_attribute_find(parent_att,parser->name, parser->type, &value)){ - g_warning("can not find value\n"); - exit(1); - } - - switch(parser->type) { - case LTTV_INT: - *value.v_int = atoi(text); - break; - case LTTV_UINT: - *value.v_uint = (unsigned)atoi(text); - break; - case LTTV_LONG: - *value.v_long = atol(text); - break; - case LTTV_ULONG: - *value.v_ulong = (unsigned long)atol(text); - break; - case LTTV_FLOAT: - *value.v_float = atof(text); - break; - case LTTV_DOUBLE: - *value.v_float = atof(text); - break; - case LTTV_TIME: - pos = strrchr(text,'.'); - if(pos){ - *pos = '\0'; - pos++; - value.v_time->tv_sec = atol(text); - value.v_time->tv_nsec = atol(pos); - }else{ - g_warning("The time value format is wrong\n"); - exit(1); - } - break; - case LTTV_POINTER: - break; - case LTTV_STRING: - *value.v_string = g_strdup(text); - break; - default: - break; - } - -} - -gboolean lttv_stats_load_statistics(LttvTracesetStats *self) -{ - FILE * fp; - char buf[BUF_SIZE]; - LttvTracesetStats *tscs = self; - LttvTraceStats *tcs; - LttvTraceset *traceset = tscs->parent.parent.ts; - char filename[BUF_SIZE]; - - GMarkupParseContext * context; - GError * error = NULL; - GMarkupParser markup_parser = - { - stats_parser_start_element, - stats_parser_end_element, - stats_parser_characters, - NULL, /* passthrough */ - NULL /* error */ - }; - - int i, nb_trace; - LttvAttribute *main_tree; - ParserStruct a_parser_struct; - a_parser_struct.attribute = g_ptr_array_new(); - - nb_trace = lttv_traceset_number(traceset); - - for(i = 0 ; i < nb_trace ; i++) { - tcs = (LttvTraceStats *)(tscs->parent.parent.traces[i]); - - filename[0] = '\0'; - strcat(filename,ltt_trace_name(tcs->parent.parent.t)); - strcat(filename,"/statistics.xml"); - fp = fopen(filename,"r"); - if(!fp){ - g_warning("can not open the file %s for reading statistics\n", filename); - return FALSE; - } - - main_tree = tcs->stats; - g_ptr_array_add(a_parser_struct.attribute,(gpointer)main_tree); - - context = g_markup_parse_context_new(&markup_parser, 0, (gpointer)&a_parser_struct, NULL); - - while(fgets(buf,BUF_SIZE, fp) != NULL){ - if(!g_markup_parse_context_parse(context, buf, BUF_SIZE, &error)){ - g_warning("Can not parse xml file: \n%s\n", error->message); - exit(1); - } - } - fclose(fp); - } - - sum_stats(NULL, (void *)self); - - return TRUE; } @@ -1168,6 +894,10 @@ static void module_init() LTTV_STATS_EVENTS_COUNT = g_quark_from_string("events count"); LTTV_STATS_BEFORE_HOOKS = g_quark_from_string("saved stats before hooks"); LTTV_STATS_AFTER_HOOKS = g_quark_from_string("saved stats after hooks"); + LTTV_STATS_USE_COUNT = g_quark_from_string("stats_use_count"); + LTTV_STATS = g_quark_from_string("statistics"); + LTTV_STATS_TRACEFILES = g_quark_from_string("tracefiles statistics"); + LTTV_STATS_SUMMED = g_quark_from_string("statistics summed"); } static void module_destroy() @@ -1178,3 +908,9 @@ static void module_destroy() LTTV_MODULE("stats", "Compute processes statistics", \ "Accumulate statistics for event types, processes and CPUs", \ module_init, module_destroy, "state"); + +/* Change the places where stats are called (create/read/write stats) + + Check for options in batchtest.c to reduce writing and see what tests are + best candidates for performance analysis. Once OK, commit, move to main + and run tests. Update the gui for statistics. */ diff --git a/ltt/branches/poly/lttv/modules/gui/statistics/statistics.c b/ltt/branches/poly/lttv/modules/gui/statistics/statistics.c index 101f83e9..9dbd162c 100644 --- a/ltt/branches/poly/lttv/modules/gui/statistics/statistics.c +++ b/ltt/branches/poly/lttv/modules/gui/statistics/statistics.c @@ -277,8 +277,8 @@ gui_statistic(MainWindow *parent_window, LttvTracesetSelector * s, char* key) &statistic_viewer_data->time_span); if(statistic_viewer_data->calculate_stats){ - if(lttv_stats_load_statistics(statistic_viewer_data->stats)) - statistic_viewer_data->calculate_stats = FALSE; + //if(lttv_stats_load_statistics(statistic_viewer_data->stats)) + // statistic_viewer_data->calculate_stats = FALSE; } if(statistic_viewer_data->calculate_stats == FALSE){ @@ -528,7 +528,7 @@ gboolean statistic_show_viewer(void * hook_data, void * call_data) show_traceset_stats(statistic_viewer_data); if(statistic_viewer_data->calculate_stats){ statistic_remove_context_hooks(statistic_viewer_data,tsc); - lttv_stats_save_statistics((LttvTracesetStats*)tsc); + //lttv_stats_save_statistics((LttvTracesetStats*)tsc); } } diff --git a/ltt/branches/poly/lttv/modules/text/batchtest.c b/ltt/branches/poly/lttv/modules/text/batchtest.c index 35ece3f9..e57c4414 100644 --- a/ltt/branches/poly/lttv/modules/text/batchtest.c +++ b/ltt/branches/poly/lttv/modules/text/batchtest.c @@ -58,6 +58,8 @@ static int a_save_interval; static gboolean + a_trace_event, + a_save_state_copy, a_test1, a_test2, a_test3, @@ -67,6 +69,8 @@ static gboolean a_test7, a_test_all; +LttEventPosition *a_event_position; + typedef struct _save_state { guint count; FILE *fp; @@ -99,10 +103,16 @@ static double run_one_test(LttvTracesetState *ts, LttTime start, LttTime end) { double t0, t1; + int i; + lttv_traceset_context_add_hooks(&ts->parent, before_traceset, after_traceset, NULL, before_trace, after_trace, NULL, before_tracefile, after_tracefile, NULL, before_event, after_event); + for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) { + ((LttvTraceState *)(ts->parent.traces[i]))->save_interval =a_save_interval; + } + t0 = get_time(); lttv_state_traceset_seek_time_closest(ts, start); lttv_process_traceset(&ts->parent, end, G_MAXULONG); @@ -116,6 +126,24 @@ static double run_one_test(LttvTracesetState *ts, LttTime start, LttTime end) } +gboolean trace_event(void *hook_data, void *call_data) +{ + LttvTracefileState *tfs = (LttvTracefileState *)call_data; + + guint nb_block, nb_event; + + LttTracefile *tf; + + ltt_event_position(tfs->parent.e, a_event_position); + ltt_event_position_get(a_event_position, &nb_block, &nb_event, &tf); + fprintf(stderr,"Event %s %lu.%09lu [%lu %lu]\n", + ltt_eventtype_name(ltt_event_eventtype(tfs->parent.e)), + tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec, + nb_block, nb_event); + return FALSE; +} + + gboolean count_event(void *hook_data, void *call_data) { guint *pcount = (guint *)hook_data; @@ -125,6 +153,35 @@ gboolean count_event(void *hook_data, void *call_data) } +gboolean save_state_copy_event(void *hook_data, void *call_data) +{ + SaveState *save_state = (SaveState *)hook_data; + + LttvTracefileState *tfs = (LttvTracefileState *)call_data; + + LttvTraceState *ts = (LttvTraceState *)tfs->parent.t_context; + + GString *filename; + + FILE *fp; + + if(ts->nb_event == 0 && strcmp(ltt_eventtype_name( + ltt_event_eventtype(tfs->parent.e)), "block_start") == 0) { + if(a_save_sample != NULL) { + filename = g_string_new(""); + g_string_printf(filename, "%s.copy.%lu.%09lu.xml", a_save_sample, + tfs->parent.timestamp.tv_sec, tfs->parent.timestamp.tv_nsec); + fp = fopen(filename->str, "w"); + if(fp == NULL) g_error("Cannot open %s", filename->str); + g_string_free(filename, TRUE); + lttv_state_write(ts, tfs->parent.timestamp, fp); + fclose(fp); + } //else lttv_state_write(ts, tfs->parent.timestamp, save_state->fp); + } + return FALSE; +} + + gboolean save_state_event(void *hook_data, void *call_data) { SaveState *save_state = (SaveState *)hook_data; @@ -149,7 +206,7 @@ gboolean save_state_event(void *hook_data, void *call_data) g_string_free(filename, TRUE); lttv_state_write(ts, tfs->parent.timestamp, fp); fclose(fp); - } else lttv_state_write(ts, tfs->parent.timestamp, save_state->fp); + } //else lttv_state_write(ts, tfs->parent.timestamp, save_state->fp); save_state->write_time[save_state->position] = tfs->parent.timestamp; save_state->position++; @@ -198,14 +255,13 @@ static gboolean process_traceset(void *hook_data, void *call_data) LttTime start_time; - LttEventPosition *event_position; - LttTime zero_time = ltt_time_zero; LttTime max_time = { G_MAXULONG, G_MAXULONG }; + a_event_position = ltt_event_position_new(); + if(a_dump_tracefiles != NULL) { - event_position = ltt_event_position_new(); for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) { trace = lttv_trace(lttv_traceset_get(traceset, i)); nb_control = ltt_trace_control_tracefile_number(trace); @@ -231,8 +287,8 @@ static gboolean process_traceset(void *hook_data, void *call_data) event_type = ltt_event_eventtype(event); time = ltt_event_time(event); cycle_count = ltt_event_cycle_count(event); - ltt_event_position(event, event_position); - ltt_event_position_get(event_position, &nb_block, &nb_event, &tf); + ltt_event_position(event, a_event_position); + ltt_event_position_get(a_event_position, &nb_block, &nb_event, &tf); fprintf(fp,"%s.%s: %llu %lu.%09lu position %u/%u\n", ltt_facility_name(facility), ltt_eventtype_name(event_type), cycle_count, (unsigned long)time.tv_sec, @@ -277,7 +333,6 @@ static gboolean process_traceset(void *hook_data, void *call_data) fclose(fp); } } - g_free(event_position); } tscs = g_object_new(LTTV_TRACESET_STATS_TYPE, NULL); @@ -285,9 +340,6 @@ static gboolean process_traceset(void *hook_data, void *call_data) tc = &tscs->parent.parent; lttv_context_init(tc, traceset); - for(i = 0 ; i < lttv_traceset_number(traceset) ; i++) { - ((LttvTraceState *)(tc->traces[i]))->save_interval = a_save_interval; - } /* For each case compute and print the elapsed time. The first case is simply to run through all events with a @@ -354,6 +406,21 @@ static gboolean process_traceset(void *hook_data, void *call_data) g_message("Memory summary after computing stats"); g_mem_profile(); } + + lttv_stats_sum_traceset(tscs); + + if(lttv_profile_memory) { + g_message("Memory summary after summing stats"); + g_mem_profile(); + } + + lttv_context_fini(tc); + lttv_context_init(tc, traceset); + + if(lttv_profile_memory) { + g_message("Memory summary after cleaning up the stats"); + g_mem_profile(); + } } /* Run through all events computing the state and stats. */ @@ -376,10 +443,20 @@ static gboolean process_traceset(void *hook_data, void *call_data) g_message("Memory summary after computing and state and stats"); g_mem_profile(); } + + lttv_context_fini(tc); + lttv_context_init(tc, traceset); + + if(lttv_profile_memory) { + g_message("Memory summary after cleaning up the stats"); + g_mem_profile(); + } } /* Run through all events computing and saving the state. */ + if(a_trace_event) lttv_hooks_add(after_event, trace_event, NULL); + if(a_test6 || a_test_all) { if(lttv_profile_memory) { g_message("Memory summary before computing and saving state"); @@ -388,9 +465,14 @@ static gboolean process_traceset(void *hook_data, void *call_data) lttv_state_add_event_hooks(ts); lttv_state_save_add_event_hooks(ts); + if(a_save_state_copy) + lttv_hooks_add(after_event, save_state_copy_event, &save_state); t = run_one_test(ts, zero_time, max_time); lttv_state_remove_event_hooks(ts); lttv_state_save_remove_event_hooks(ts); + if(a_save_state_copy) + lttv_hooks_remove_data(after_event,save_state_copy_event, &save_state); + g_warning("Processing trace while updating/saving state (%g seconds)", t); if(lttv_profile_memory) { @@ -424,16 +506,24 @@ static gboolean process_traceset(void *hook_data, void *call_data) save_state.write_time[j], fp); fclose(fp); } - else lttv_state_write((LttvTraceState *)tc->traces[0], - save_state.write_time[j], save_state.fp); + //else lttv_state_write((LttvTraceState *)tc->traces[0], + // save_state.write_time[j], save_state.fp); } } } + if(a_trace_event) lttv_hooks_remove_data(after_event, trace_event, NULL); + g_free(save_state.write_time); + g_free(a_event_position); lttv_context_fini(tc); g_object_unref(tscs); + if(lttv_profile_memory) { + g_message("Memory summary at the end of batchtest"); + g_mem_profile(); + } + g_info("BatchTest end process traceset"); } @@ -451,6 +541,8 @@ static void init() "pathname of the directory containing the trace", LTTV_OPT_STRING, &a_trace, lttv_trace_option, NULL); + a_trace_event = FALSE; + a_dump_tracefiles = NULL; lttv_option_add("dump-tracefiles", 'D', "Write event by event the content of tracefiles", @@ -463,6 +555,10 @@ static void init() "basename for the files containing the state samples", LTTV_OPT_STRING, &a_save_sample, NULL, NULL); + a_save_state_copy = FALSE; + lttv_option_add("save-state-copy", 'S', "Write the state saved for seeking", + "", LTTV_OPT_NONE, &a_save_state_copy, NULL, NULL); + a_save_interval = 100000; lttv_option_add("save-interval", 'i', "Interval between saving state", @@ -567,6 +663,7 @@ static void destroy() lttv_option_remove("trace"); lttv_option_remove("dump-tracefiles"); lttv_option_remove("save-sample"); + lttv_option_remove("save-state-copy"); lttv_option_remove("sample-interval"); lttv_option_remove("sample-number"); lttv_option_remove("save-interval"); diff --git a/ltt/branches/poly/lttv/modules/text/textDump.c b/ltt/branches/poly/lttv/modules/text/textDump.c index c105a07c..cc400d92 100644 --- a/ltt/branches/poly/lttv/modules/text/textDump.c +++ b/ltt/branches/poly/lttv/modules/text/textDump.c @@ -283,6 +283,7 @@ static gboolean write_traceset_footer(void *hook_data, void *call_data) fprintf(a_file,"End trace set\n\n"); if(LTTV_IS_TRACESET_STATS(tc)) { + lttv_stats_sum_traceset((LttvTracesetStats *)tc); print_stats(a_file, (LttvTracesetStats *)tc); } -- 2.34.1