Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
isolating uncategorized resource utilization tracing to get a cleaner trace
[simgrid.git] / src / instr / resource_utilization.c
1 /* Copyright (c) 2010. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5   * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include "instr/private.h"
8
9 #ifdef HAVE_TRACING
10
11 #define VARIABLE_SEPARATOR '#'
12
13 //to check if variables were previously set to 0, otherwise paje won't simulate them
14 static xbt_dict_t platform_variables;   /* host or link name -> array of categories */
15
16 //B
17 static xbt_dict_t method_b_dict;
18
19 //C
20 static xbt_dict_t method_c_dict;
21
22 /* auxiliary function for resource utilization tracing */
23 static char *strsplit(char *input, int field, char del) //caller should free the returned string
24 {
25   char *ret = NULL;
26   int length = strlen(input), i;
27   int s = 0, e = length + 1;
28   int current_field = 0;
29   for (i = 0; i < length; i++) {
30     if (input[i] == del) {
31       if (current_field == field) {
32         e = i - 1;
33         break;
34       } else {
35         s = i + 1;
36         current_field++;
37       }
38     }
39   }
40   //copy string from s to e (with length equal to e-s) and return
41   ret = malloc((e - s + 2) * sizeof(char));
42   strncpy(ret, input + s, e - s + 1);
43   ret[e - s + 1] = '\0';
44   return ret;
45 }
46
47 //resource utilization tracing method
48 static void (*TRACE_method_alloc) (void) = NULL;
49 static void (*TRACE_method_release) (void) = NULL;
50 static void (*TRACE_method_start) (smx_action_t action) = NULL;
51 static void (*TRACE_method_event) (smx_action_t action, double now,
52                                    double delta, const char *variable,
53                                    const char *resource, double value) =
54     NULL;
55 static void (*TRACE_method_end) (smx_action_t action) = NULL;
56
57 //used by all methods
58 static void __TRACE_surf_check_variable_set_to_zero(double now,
59                                                     const char *variable,
60                                                     const char *resource)
61 {
62   /* check if we have to set it to 0 */
63   if (!xbt_dict_get_or_null(platform_variables, resource)) {
64     xbt_dynar_t array = xbt_dynar_new(sizeof(char *), xbt_free);
65     char *var_cpy = xbt_strdup(variable);
66     xbt_dynar_push(array, &var_cpy);
67     if (IS_TRACING_PLATFORM)
68       pajeSetVariable(now, variable, resource, "0");
69     xbt_dict_set(platform_variables, resource, array,
70                  xbt_dynar_free_voidp);
71   } else {
72     xbt_dynar_t array = xbt_dict_get(platform_variables, resource);
73     unsigned int i;
74     char *cat;
75     int flag = 0;
76     xbt_dynar_foreach(array, i, cat) {
77       if (strcmp(variable, cat) == 0) {
78         flag = 1;
79       }
80     }
81     if (flag == 0) {
82       char *var_cpy = xbt_strdup(variable);
83       xbt_dynar_push(array, &var_cpy);
84       if (IS_TRACING_PLATFORM)
85         pajeSetVariable(now, variable, resource, "0");
86     }
87   }
88   /* end of check */
89 }
90
91 #define A_METHOD
92 //A
93 static void __TRACE_A_alloc(void)
94 {
95 }
96
97 static void __TRACE_A_release(void)
98 {
99 }
100
101 static void __TRACE_A_start(smx_action_t action)
102 {
103 }
104
105 static void __TRACE_A_event(smx_action_t action, double now, double delta,
106                             const char *variable, const char *resource,
107                             double value)
108 {
109   if (!IS_TRACING_PLATFORM)
110     return;
111
112   char valuestr[100];
113   snprintf(valuestr, 100, "%f", value);
114
115   __TRACE_surf_check_variable_set_to_zero(now, variable, resource);
116   pajeAddVariable(now, variable, resource, valuestr);
117   pajeSubVariable(now + delta, variable, resource, valuestr);
118 }
119
120 static void __TRACE_A_end(smx_action_t action)
121 {
122 }
123
124 #define B_METHOD
125 //B
126
127 static void __TRACE_B_alloc(void)
128 {
129   method_b_dict = xbt_dict_new();
130 }
131
132 static void __TRACE_B_release(void)
133 {
134   xbt_dict_cursor_t cursor = NULL;
135   unsigned int cursor_ar = 0;
136   char *key, *value, *res;
137   char *resource;
138   char *aux = NULL;
139   char *var_cpy = NULL;
140   xbt_dynar_t resources = NULL;
141   if (!IS_TRACING_PLATFORM)
142     return;
143   if (!xbt_dict_length(method_b_dict)) {
144     return;
145   } else {
146     /* get all resources from method_b_dict */
147     resources = xbt_dynar_new(sizeof(char *), xbt_free);
148     xbt_dict_foreach(method_b_dict, cursor, key, value) {
149       res = strsplit(key, 0, VARIABLE_SEPARATOR);
150       aux = strsplit(key, 1, VARIABLE_SEPARATOR);
151       if (strcmp(aux, "Time") == 0) {   //only need to add one of three
152         var_cpy = xbt_strdup(res);
153         xbt_dynar_push(resources, &var_cpy);
154       }
155       free(aux);
156       free(res);
157     }
158
159     /* iterate through resources array */
160     xbt_dynar_foreach(resources, cursor_ar, resource) {
161       char timekey[100], valuekey[100], variablekey[100];
162       char *time = NULL;
163       char *value = NULL;
164       char *variable = NULL;
165       snprintf(timekey, 100, "%s%cTime", resource, VARIABLE_SEPARATOR);
166       snprintf(valuekey, 100, "%s%cValue", resource, VARIABLE_SEPARATOR);
167       snprintf(variablekey, 100, "%s%cVariable", resource,
168                VARIABLE_SEPARATOR);
169
170       time = xbt_dict_get_or_null(method_b_dict, timekey);
171       if (!time)
172         continue;
173       value = xbt_dict_get(method_b_dict, valuekey);
174       variable = xbt_dict_get(method_b_dict, variablekey);
175       pajeSubVariable(atof(time), variable, resource, value);
176
177       xbt_dict_remove(method_b_dict, timekey);
178       xbt_dict_remove(method_b_dict, valuekey);
179       xbt_dict_remove(method_b_dict, variablekey);
180     }
181   }
182   xbt_dict_free(&method_b_dict);
183 }
184
185 static void __TRACE_B_start(smx_action_t action)
186 {
187 }
188
189 static void __TRACE_B_event(smx_action_t action, double now, double delta,
190                             const char *variable, const char *resource,
191                             double value)
192 {
193
194   if (!IS_TRACING_PLATFORM)
195     return;
196
197   char valuestr[100];
198   char nowstr[100], nowdeltastr[100];
199   char timekey[100], valuekey[100], variablekey[100];
200   char *lastvariable = NULL;
201   char *lasttime = NULL;
202   char *lastvalue = NULL;
203   char *nowdeltastr_cpy = NULL;
204   char *valuestr_cpy = NULL;
205   char *variable_cpy = NULL;
206
207   /*
208    * The following code replaces the code above with the objective
209    * to decrease the size of file because of unnecessary add/sub on
210    * variables. It should be re-checked before put in production.
211    */
212
213   snprintf(valuestr, 100, "%f", value);
214   snprintf(nowstr, 100, "%f", now);
215   snprintf(nowdeltastr, 100, "%f", now + delta);
216   snprintf(timekey, 100, "%s%cTime", resource, VARIABLE_SEPARATOR);
217   snprintf(valuekey, 100, "%s%cValue", resource, VARIABLE_SEPARATOR);
218   snprintf(variablekey, 100, "%s%cVariable", resource, VARIABLE_SEPARATOR);
219
220   lastvariable = xbt_dict_get_or_null(method_b_dict, variablekey);
221   if (lastvariable == NULL) {
222     __TRACE_surf_check_variable_set_to_zero(now, variable, resource);
223     pajeAddVariable(now, variable, resource, valuestr);
224     nowdeltastr_cpy = xbt_strdup(nowdeltastr);
225     valuestr_cpy = xbt_strdup(valuestr);
226     variable_cpy = xbt_strdup(variable);
227     xbt_dict_set(method_b_dict, timekey, nowdeltastr_cpy, xbt_free);
228     xbt_dict_set(method_b_dict, valuekey, valuestr_cpy, xbt_free);
229     xbt_dict_set(method_b_dict, variablekey, variable_cpy, xbt_free);
230   } else {
231     lasttime = xbt_dict_get_or_null(method_b_dict, timekey);
232     lastvalue = xbt_dict_get_or_null(method_b_dict, valuekey);
233
234     /* check if it is the same variable */
235     if (strcmp(lastvariable, variable) == 0) {  /* same variable */
236       /* check if lasttime equals now */
237       if (atof(lasttime) == now) {      /* lastime == now */
238         /* check if lastvalue equals valuestr */
239         if (atof(lastvalue) == value) { /* lastvalue == value (good, just advance time) */
240           char *nowdeltastr_cpy = xbt_strdup(nowdeltastr);
241           xbt_dict_set(method_b_dict, timekey, nowdeltastr_cpy, xbt_free);
242         } else {                /* value has changed */
243           /* value has changed, subtract previous value, add new one */
244           pajeSubVariable(atof(lasttime), variable, resource, lastvalue);
245           pajeAddVariable(atof(nowstr), variable, resource, valuestr);
246           nowdeltastr_cpy = xbt_strdup(nowdeltastr);
247           valuestr_cpy = xbt_strdup(valuestr);
248           xbt_dict_set(method_b_dict, timekey, nowdeltastr_cpy, xbt_free);
249           xbt_dict_set(method_b_dict, valuekey, valuestr_cpy, xbt_free);
250         }
251       } else {                  /* lasttime != now */
252         /* the last time is different from new starting time, subtract to lasttime and add from nowstr */
253         pajeSubVariable(atof(lasttime), variable, resource, lastvalue);
254         pajeAddVariable(atof(nowstr), variable, resource, valuestr);
255         nowdeltastr_cpy = xbt_strdup(nowdeltastr);
256         valuestr_cpy = xbt_strdup(valuestr);
257         xbt_dict_set(method_b_dict, timekey, nowdeltastr_cpy, xbt_free);
258         xbt_dict_set(method_b_dict, valuekey, valuestr_cpy, xbt_free);
259       }
260     } else {                    /* variable has changed */
261       pajeSubVariable(atof(lasttime), lastvariable, resource, lastvalue);
262       __TRACE_surf_check_variable_set_to_zero(now, variable, resource);
263       pajeAddVariable(now, variable, resource, valuestr);
264       nowdeltastr_cpy = xbt_strdup(nowdeltastr);
265       valuestr_cpy = xbt_strdup(valuestr);
266       variable_cpy = xbt_strdup(variable);
267       xbt_dict_set(method_b_dict, timekey, nowdeltastr_cpy, xbt_free);
268       xbt_dict_set(method_b_dict, valuekey, valuestr_cpy, xbt_free);
269       xbt_dict_set(method_b_dict, variablekey, variable_cpy, xbt_free);
270     }
271   }
272   return;
273 }
274
275 static void __TRACE_B_end(smx_action_t action)
276 {
277 }
278
279 #define C_METHOD
280 //C
281 static void __TRACE_C_alloc(void)
282 {
283   method_c_dict = xbt_dict_new();
284 }
285
286 static void __TRACE_C_release(void)
287 {
288   xbt_dict_free(&method_c_dict);
289 }
290
291 static void __TRACE_C_start(smx_action_t action)
292 {
293   char key[100];
294   snprintf(key, 100, "%p", action);
295
296   //check if exists
297   if (xbt_dict_get_or_null(method_c_dict, key)) {
298     xbt_dict_remove(method_c_dict, key);        //should never execute here, but it does
299   }
300   xbt_dict_set(method_c_dict, key, xbt_dict_new(), xbt_free);
301 }
302
303 static void __TRACE_C_event(smx_action_t action, double now, double delta,
304                             const char *variable, const char *resource,
305                             double value)
306 {
307   char key[100];
308   snprintf(key, 100, "%p", action);
309
310   xbt_dict_t action_dict = xbt_dict_get(method_c_dict, key);
311   //setting start time
312   if (!xbt_dict_get_or_null(action_dict, "start")) {
313     char start_time[100];
314     snprintf(start_time, 100, "%f", now);
315     xbt_dict_set(action_dict, "start", xbt_strdup(start_time), xbt_free);
316   }
317   //updating end time
318   char end_time[100];
319   snprintf(end_time, 100, "%f", now + delta);
320   xbt_dict_set(action_dict, "end", xbt_strdup(end_time), xbt_free);
321
322   //accumulate the value resource-variable
323   char res_var[300];
324   snprintf(res_var, 300, "%s %s", resource, variable);
325   double current_value_f;
326   char *current_value = xbt_dict_get_or_null(action_dict, res_var);
327   if (current_value) {
328     current_value_f = atof(current_value);
329     current_value_f += value * delta;
330   } else {
331     current_value_f = value * delta;
332   }
333   char new_current_value[100];
334   snprintf(new_current_value, 100, "%f", current_value_f);
335   xbt_dict_set(action_dict, res_var, xbt_strdup(new_current_value),
336                xbt_free);
337 }
338
339 static void __TRACE_C_end(smx_action_t action)
340 {
341   char key[100];
342   snprintf(key, 100, "%p", action);
343
344   xbt_dict_t action_dict = xbt_dict_get(method_c_dict, key);
345   double start_time = atof(xbt_dict_get(action_dict, "start"));
346   double end_time = atof(xbt_dict_get(action_dict, "end"));
347
348   xbt_dict_cursor_t cursor = NULL;
349   char *action_dict_key, *action_dict_value;
350   xbt_dict_foreach(action_dict, cursor, action_dict_key, action_dict_value) {
351     char resource[100], variable[100];
352     if (sscanf(action_dict_key, "%s %s", resource, variable) != 2)
353       continue;
354     __TRACE_surf_check_variable_set_to_zero(start_time, variable,
355                                             resource);
356     char value_str[100];
357     if (end_time - start_time != 0) {
358       snprintf(value_str, 100, "%f",
359                atof(action_dict_value) / (end_time - start_time));
360       pajeAddVariable(start_time, variable, resource, value_str);
361       pajeSubVariable(end_time, variable, resource, value_str);
362     }
363   }
364   xbt_dict_remove(method_c_dict, key);
365 }
366
367 #define RESOURCE_UTILIZATION_INTERFACE
368 /*
369  * TRACE_surf_link_set_utilization: entry point from SimGrid
370  */
371 void TRACE_surf_link_set_utilization(void *link, smx_action_t smx_action,
372                                      surf_action_t surf_action,
373                                      double value, double now,
374                                      double delta)
375 {
376   if (!IS_TRACING)
377     return;
378   if (!value)
379     return;
380   //only trace link utilization if link is known by tracing mechanism
381   if (!TRACE_surf_link_is_traced(link))
382     return;
383   if (!value)
384     return;
385
386   char resource[100];
387   snprintf(resource, 100, "%p", link);
388
389   //trace uncategorized link utilization
390   if (TRACE_uncategorized()){
391     TRACE_surf_resource_utilization_event(smx_action, now, delta,
392                                         "bandwidth_used", resource, value);
393   }
394
395   //trace categorized utilization
396   if (!IS_TRACED(surf_action))
397     return;
398   char type[100];
399   snprintf(type, 100, "b%s", surf_action->category);
400   TRACE_surf_resource_utilization_event(smx_action, now, delta, type,
401                                         resource, value);
402   return;
403 }
404
405 /*
406  * TRACE_surf_host_set_utilization: entry point from SimGrid
407  */
408 void TRACE_surf_host_set_utilization(const char *name,
409                                      smx_action_t smx_action,
410                                      surf_action_t surf_action,
411                                      double value, double now,
412                                      double delta)
413 {
414   if (!IS_TRACING)
415     return;
416   if (!value)
417     return;
418
419   //trace uncategorized host utilization
420   if (TRACE_uncategorized()){
421     TRACE_surf_resource_utilization_event(smx_action, now, delta,
422                                         "power_used", name, value);
423   }
424
425   //trace categorized utilization
426   if (!IS_TRACED(surf_action))
427     return;
428   char type[100];
429   snprintf(type, 100, "p%s", surf_action->category);
430   TRACE_surf_resource_utilization_event(smx_action, now, delta, type, name,
431                                         value);
432   return;
433 }
434
435 /*
436  * __TRACE_surf_resource_utilization_*: entry points from tracing functions
437  */
438 void TRACE_surf_resource_utilization_start(smx_action_t action)
439 {
440   if (!IS_TRACING)
441     return;
442   TRACE_method_start(action);
443 }
444
445 void TRACE_surf_resource_utilization_event(smx_action_t action, double now,
446                                            double delta,
447                                            const char *variable,
448                                            const char *resource,
449                                            double value)
450 {
451   if (!IS_TRACING)
452     return;
453   TRACE_method_event(action, now, delta, variable, resource, value);
454 }
455
456 void TRACE_surf_resource_utilization_end(smx_action_t action)
457 {
458   if (!IS_TRACING)
459     return;
460   TRACE_method_end(action);
461 }
462
463 void TRACE_surf_resource_utilization_release()
464 {
465   if (!IS_TRACING)
466     return;
467   TRACE_method_release();
468 }
469
470 static void __TRACE_define_method(char *method)
471 {
472   if (!strcmp(method, "a")) {
473     TRACE_method_alloc = __TRACE_A_alloc;
474     TRACE_method_release = __TRACE_A_release;
475     TRACE_method_start = __TRACE_A_start;
476     TRACE_method_event = __TRACE_A_event;
477     TRACE_method_end = __TRACE_A_end;
478   } else if (!strcmp(method, "c")) {
479     TRACE_method_alloc = __TRACE_C_alloc;
480     TRACE_method_release = __TRACE_C_release;
481     TRACE_method_start = __TRACE_C_start;
482     TRACE_method_event = __TRACE_C_event;
483     TRACE_method_end = __TRACE_C_end;
484   } else {                      //default is B
485     TRACE_method_alloc = __TRACE_B_alloc;
486     TRACE_method_release = __TRACE_B_release;
487     TRACE_method_start = __TRACE_B_start;
488     TRACE_method_event = __TRACE_B_event;
489     TRACE_method_end = __TRACE_B_end;
490   }
491 }
492
493 void TRACE_surf_resource_utilization_alloc()
494 {
495   platform_variables = xbt_dict_new();
496   __TRACE_define_method(TRACE_get_platform_method());
497   TRACE_method_alloc();
498 }
499 #endif