59121f0c |
1 | /* |
2 | |
3 | Analyse: loop over events, either one tracefile after another or |
4 | simultaneously by increasing time over all tracefiles. |
5 | |
6 | Process: create the process_state structure and register for all state |
7 | changing events to update the process_state. |
8 | |
9 | Stats: create an lttv_attributes to receive statistics. Offer functions |
10 | to specify statistics gathering (event types, specific field as int, |
11 | specific field as histogram...); this is used for syscalls and for |
12 | bytes read and written. Eventually factor out the type of |
13 | state and key positions (disk state, ethernet state...) |
14 | |
15 | Operations on stats: |
16 | select based on match, sort based on compare function/key order, |
17 | sum based on equality of truncated key |
18 | |
19 | Sort order: |
20 | key to base the sort on, by decreasing order of preference |
21 | |
22 | Match/combine: |
23 | for each key component, accept as is, only accept x, combine with previous. |
24 | |
25 | Print stats: |
26 | print hierarchically |
27 | |
28 | |
29 | */ |
30 | |
31 | |
32 | typedef struct _stats_hook_data { |
33 | lttv_attributes *a; |
34 | lttv_key *key; |
35 | GHashTable *processes; |
36 | lttv_string_id current_process; |
37 | GArray *state; |
38 | lttv_string_id current_state; |
39 | bool init_done; |
40 | } stats_hook_data; |
41 | |
42 | /* Process state is wait, user, system, trap, irq */ |
43 | |
44 | /* before, after, print, free */ |
45 | |
46 | /* The accumulated statistics are: |
47 | |
48 | for each trace: |
49 | |
50 | The hierarchical key contains: |
51 | |
52 | system/cpu/process/state/type/id |
53 | |
54 | where state is one of user, system, irq, trap or wait, and type is one |
55 | of eventtype, syscall, and id is specific to each category (event id, |
56 | syscall number...). |
57 | |
58 | print per system/state/substate/eventid (sum over process/cpu) |
59 | print per system/cpu/state/substate/eventid (sum over process) |
60 | print per system/process/state/substate/eventid (sum over cpu) |
61 | |
62 | number of events of each type |
63 | */ |
64 | |
65 | lttv_basicStats_before(lttv_trace_set *s) |
66 | { |
67 | int i, j, nb_trace, nb_tracefile; |
68 | lttv_trace *t; |
69 | lttv_tracefile *tf; |
70 | lttv_attributes *a; |
71 | stats_hook_data *hook_data, *old; |
72 | |
73 | nb_trace = lttv_trace_set_number(s); |
74 | |
75 | for(i = 0 ; i < nb_trace ; i++) { |
76 | t = lttv_trace_set_get(s,i); |
77 | nb_tracefile = lttv_trace_number(t); |
78 | |
79 | hook_data = lttv_basicStats_new(); |
80 | a = lttv_trace_attributes(t); |
81 | old = (stats_hook_data *)lttv_attributes_get_pointer_pathname(a, |
82 | "stats/basic"); |
83 | lttv_basicStats_destroy(old); |
84 | lttv_attributes_set_pointer_pathname(a,"stats/basic",hook_data); |
85 | |
86 | for(j = 0 ; j < nb_tracefile ; j++) { |
87 | tf = lttv_trace_get(t,j); |
88 | a = lttv_tracefile_attributes(tf); |
89 | h = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,"hooks/event"); |
90 | lttv_hooks_add(h, compute_stats, hook_data); |
91 | } |
92 | } |
93 | } |
94 | |
95 | lttv_basicStats_after(lttv_trace_set *s) |
96 | { |
97 | int i, j, nb_trace, nb_tracefile; |
98 | lttv_trace *t; |
99 | lttv_tracefile *tf; |
100 | lttv_attributes *a; |
101 | stats_hook_data *hook_data; |
102 | |
103 | nb_trace = lttv_trace_set_number(s); |
104 | |
105 | for(i = 0 ; i < nb_trace ; i++) { |
106 | t = lttv_trace_set_get(s,i); |
107 | nb_tracefile = lttv_trace_number(t); |
108 | |
109 | hook_data = (stats_hook_data *)lttv_attributes_get_pointer_pathname(a, |
110 | "stats/basic"); |
111 | |
112 | for(j = 0 ; j < nb_tracefile ; j++) { |
113 | tf = lttv_trace_get(t,j); |
114 | a = lttv_tracefile_attributes(tf); |
115 | h = (lttv_hooks *)lttv_attributes_get_pointer_pathname(a,"hooks/event"); |
116 | lttv_hooks_remove(h, compute_stats, hook_data); |
117 | } |
118 | |
119 | lttv_basicStats_destroy(hook_data); |
120 | } |
121 | } |
122 | |
123 | |
124 | update_state |
125 | |
126 | compute time in that state... |
127 | |
128 | For processes remember the command name... |
129 | |
130 | Compute bytes read/written... |
131 | |
132 | static void compute_eventtype_id_stats(void *hook_data, void *call_data) |
133 | { |
134 | stats_hook_data *d; |
135 | ltt_event *e; |
136 | |
137 | d = (stats_hook_data *)hook_data; |
138 | e = (ltt_event *)call_data; |
139 | |
140 | lttv_key_index(d->key,4) = string_id_EventType; |
141 | lttv_key_index(d->key,5) = string_id_unsigned(ltt_event_eventtype_id(e)); |
142 | (*lttv_attributes_get_integer(d->a,d->key))++; |
143 | } |
144 | |
145 | /* The field for which a sum is required is expressed as eventtype/field */ |
146 | |
147 | typedef struct _field_sum_data { |
148 | stats_hook_data *d; |
149 | ltt_field *f; |
150 | lttv_string_id type_name; |
151 | lttv_string_id id_name; |
152 | } field_sum_data; |
153 | |
154 | lttv_basicStats_sum_integer_field_before(lttv_trace_set *s, char *field_path, |
155 | char *type_name, char *id_name) |
156 | { |
157 | int i, j, nb_trace, nb_tracefile; |
158 | lttv_trace *t; |
159 | lttv_tracefile *tf; |
160 | lttv_attributes *a; |
161 | lttv_hooks_by_id h; |
162 | stats_hook_data *stats_data; |
163 | field_sum_data *hook_data; |
164 | unsigned id; |
165 | |
166 | nb_trace = lttv_trace_set_number(s); |
167 | |
168 | for(i = 0 ; i < nb_trace ; i++) { |
169 | t = lttv_trace_set_get(s,i); |
170 | nb_tracefile = lttv_trace_number(t); |
171 | |
172 | a = lttv_trace_attributes(t); |
173 | stats_data = (stats_hook_data *)lttv_attributes_get_pointer_pathname(a, |
174 | "stats/basic"); |
175 | |
176 | for(j = 0 ; j < nb_tracefile ; j++) { |
177 | tf = lttv_trace_get(t,j); |
178 | a = lttv_tracefile_attributes(tf); |
179 | hook_data = g_new(field_sum_data); |
180 | hook_data->d = stats_data; |
181 | hook_data->f = lttv_tracefile_eventtype_field_pathname( |
182 | lttv_tracefile_ltt_tracefile(tf), field_path, &id); |
183 | hook_data->type_name = type_name; |
184 | hook_data->id_name = id_name; |
185 | h = (lttv_hooks_by_id *)lttv_attributes_get_pointer_pathname(a, |
186 | "hooks/eventid"); |
187 | if(id_name != NULL) { |
188 | lttv_hooks_add(h, compute_integer_field_sum, hook_data); |
189 | } |
190 | else { |
191 | lttv_hooks_add(h, compute_integer_field_histogram, hook_data); |
192 | } |
193 | } |
194 | } |
195 | } |
196 | |
197 | static void compute_integer_field_sum(void *hook_data, void *call_data) |
198 | { |
199 | field_sum_data *d; |
200 | ltt_event *e; |
201 | |
202 | d = (field_sum_data *)hook_data; |
203 | e = (ltt_event *)call_data; |
204 | |
205 | lttv_key_index(d->key,4) = d->type_name; |
206 | lttv_key_index(d->key,5) = d->id_name; |
207 | (*lttv_attributes_get_integer(d->a,d->key)) += |
208 | ltt_event_get_unsigned(e,d->f); |
209 | } |
210 | |
211 | static void compute_integer_field_histogram(void *hook_data, void *call_data) |
212 | { |
213 | field_sum_data *d; |
214 | ltt_event *e; |
215 | |
216 | d = (field_sum_data *)hook_data; |
217 | e = (ltt_event *)call_data; |
218 | |
219 | lttv_key_index(d->key,4) = d->type_name; |
220 | lttv_key_index(d->key,5)= string_id_unsigned(ltt_event_get_unsigned(e,d->f)); |
221 | (*lttv_attributes_get_integer(d->a,d->key))++; |
222 | } |
223 | |
224 | |
225 | stats_hook_data *lttv_basicStats_new() |
226 | { |
227 | g_new(stats_hook_data,1); |
228 | hook_data->a = lttv_attributes_new(); |
229 | hook_data->key = lttv_key_new(); |
230 | id = lttv_string_id(""); |
231 | for j = 0 ; j < 6 ; j++) lttv_key_append(hook_data->key,id); |
232 | hook_data->processes = g_hash_table_new(g_int_hash,g_int_equal); |
233 | hook_data->init_done = FALSE; |
234 | } |
235 | |
236 | stats_hook_data *lttv_basicStats_destroy(stats_hook_data *hook_data) |
237 | { |
238 | lttv_attributes_destroy(hook_data->a); |
239 | lttv_key_destroy(hook_data->key); |
240 | lttv_process_state_destroy(hook_data->processes); |
241 | g_free(hook_data); |
242 | return NULL; |
243 | } |
244 | |
245 | |
246 | |