Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
be326bedca6d64750929b6ce1e06dd959e3e8b05
[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, double delta, const char *variable, const char *resource, double value) = NULL;
52 static void (*TRACE_method_end)(smx_action_t action) = NULL;
53
54 //used by all methods
55 static void __TRACE_surf_check_variable_set_to_zero (double now, const char *variable, const char *resource)
56 {
57   /* check if we have to set it to 0 */
58   if (!xbt_dict_get_or_null (platform_variables, resource)){
59     xbt_dynar_t array = xbt_dynar_new(sizeof(char*), xbt_free);
60     char *var_cpy = xbt_strdup(variable);
61     xbt_dynar_push (array, &var_cpy);
62     if (IS_TRACING_PLATFORM) pajeSetVariable (now, variable, resource, "0");
63     xbt_dict_set (platform_variables, resource, array, xbt_dynar_free_voidp);
64   }else{
65     xbt_dynar_t array = xbt_dict_get (platform_variables, resource);
66     unsigned int i;
67     char* cat;
68     int flag = 0;
69     xbt_dynar_foreach (array, i, cat) {
70       if (strcmp(variable, cat)==0){
71         flag = 1;
72       }
73     }
74     if (flag==0){
75       char *var_cpy = xbt_strdup(variable);
76       xbt_dynar_push (array, &var_cpy);
77       if (IS_TRACING_PLATFORM) pajeSetVariable (now, variable, resource, "0");
78     }
79   }
80   /* end of check */
81 }
82
83 #define A_METHOD
84 //A
85 static void __TRACE_A_alloc (void) {}
86 static void __TRACE_A_release (void) {}
87 static void __TRACE_A_start (smx_action_t action) {}
88 static void __TRACE_A_event (smx_action_t action, double now, double delta, const char *variable, const char *resource, double value)
89 {
90   if (!IS_TRACING_PLATFORM) return;
91
92   char valuestr[100];
93   snprintf (valuestr, 100, "%f", value);
94
95   __TRACE_surf_check_variable_set_to_zero (now, variable, resource);
96   pajeAddVariable (now, variable, resource, valuestr);
97   pajeSubVariable (now+delta, variable, resource, valuestr);
98 }
99 static void __TRACE_A_end (smx_action_t action) {}
100
101 #define B_METHOD
102 //B
103
104 static void __TRACE_B_alloc (void)
105 {
106   method_b_dict =  xbt_dict_new();
107 }
108
109 static void __TRACE_B_release (void)
110 {
111   xbt_dict_cursor_t cursor = NULL;
112   unsigned int cursor_ar = 0;
113     char *key, *value, *res;
114     char *resource;
115     char *aux = NULL;
116     char *var_cpy = NULL;
117     xbt_dynar_t resources = NULL;
118   if (!IS_TRACING_PLATFORM) return;
119   if (!xbt_dict_length(method_b_dict)){
120     return;
121   }else{
122     /* get all resources from method_b_dict */
123     resources = xbt_dynar_new(sizeof(char*), xbt_free);
124     xbt_dict_foreach(method_b_dict, cursor, key, value) {
125       res = strsplit (key, 0, VARIABLE_SEPARATOR);
126       aux = strsplit (key, 1, VARIABLE_SEPARATOR);
127       if (strcmp (aux, "Time") == 0){ //only need to add one of three
128         var_cpy = xbt_strdup (res);
129         xbt_dynar_push (resources, &var_cpy);
130       }
131       free (aux);
132       free (res);
133     }
134
135     /* iterate through resources array */
136     xbt_dynar_foreach (resources, cursor_ar, resource) {
137       char timekey[100], valuekey[100], variablekey[100];
138       char *time = NULL;
139       char *value = NULL;
140       char *variable = NULL;
141       snprintf (timekey, 100, "%s%cTime", resource, VARIABLE_SEPARATOR);
142       snprintf (valuekey, 100, "%s%cValue", resource, VARIABLE_SEPARATOR);
143       snprintf (variablekey, 100, "%s%cVariable", resource, VARIABLE_SEPARATOR);
144
145       time = xbt_dict_get_or_null (method_b_dict, timekey);
146       if (!time) continue;
147       value = xbt_dict_get (method_b_dict, valuekey);
148       variable = xbt_dict_get (method_b_dict, variablekey);
149       pajeSubVariable (atof(time), variable, resource, value);
150
151       xbt_dict_remove (method_b_dict, timekey);
152       xbt_dict_remove (method_b_dict, valuekey);
153       xbt_dict_remove (method_b_dict, variablekey);
154     }
155   }
156   xbt_dict_free (&method_b_dict);
157 }
158
159 static void __TRACE_B_start (smx_action_t action) {}
160 static void __TRACE_B_event (smx_action_t action, double now, double delta, const char *variable, const char *resource, double value)
161 {
162
163   if (!IS_TRACING_PLATFORM) return;
164
165   char valuestr[100];
166   char nowstr[100], nowdeltastr[100];
167   char timekey[100], valuekey[100], variablekey[100];
168   char *lastvariable = NULL;
169   char *lasttime = NULL;
170   char *lastvalue = NULL;
171   char *nowdeltastr_cpy = NULL;
172   char *valuestr_cpy = NULL;
173   char *variable_cpy = NULL;
174
175   /*
176    * The following code replaces the code above with the objective
177    * to decrease the size of file because of unnecessary add/sub on
178    * variables. It should be re-checked before put in production.
179    */
180
181   snprintf (valuestr, 100, "%f", value);
182   snprintf (nowstr, 100, "%f", now);
183   snprintf (nowdeltastr, 100, "%f", now+delta);
184   snprintf (timekey, 100, "%s%cTime", resource, VARIABLE_SEPARATOR);
185   snprintf (valuekey, 100, "%s%cValue", resource, VARIABLE_SEPARATOR);
186   snprintf (variablekey, 100, "%s%cVariable", resource, VARIABLE_SEPARATOR);
187
188   lastvariable = xbt_dict_get_or_null (method_b_dict, variablekey);
189   if (lastvariable == NULL){
190     __TRACE_surf_check_variable_set_to_zero (now, variable, resource);
191     pajeAddVariable (now, variable, resource, valuestr);
192     nowdeltastr_cpy = xbt_strdup (nowdeltastr);
193     valuestr_cpy = xbt_strdup (valuestr);
194     variable_cpy = xbt_strdup (variable);
195     xbt_dict_set (method_b_dict, timekey, nowdeltastr_cpy, xbt_free);
196     xbt_dict_set (method_b_dict, valuekey, valuestr_cpy, xbt_free);
197     xbt_dict_set (method_b_dict, variablekey, variable_cpy, xbt_free);
198   }else{
199     lasttime = xbt_dict_get_or_null (method_b_dict, timekey);
200     lastvalue = xbt_dict_get_or_null (method_b_dict, valuekey);
201
202     /* check if it is the same variable */
203     if (strcmp(lastvariable, variable) == 0){ /* same variable */
204       /* check if lasttime equals now */
205       if (atof(lasttime) == now){ /* lastime == now */
206         /* check if lastvalue equals valuestr */
207         if (atof(lastvalue) == value){ /* lastvalue == value (good, just advance time) */
208           char *nowdeltastr_cpy = xbt_strdup (nowdeltastr);
209           xbt_dict_set (method_b_dict, timekey, nowdeltastr_cpy, xbt_free);
210         }else{ /* value has changed */
211           /* value has changed, subtract previous value, add new one */
212           pajeSubVariable (atof(lasttime), variable, resource, lastvalue);
213           pajeAddVariable (atof(nowstr), variable, resource, valuestr);
214           nowdeltastr_cpy = xbt_strdup (nowdeltastr);
215           valuestr_cpy = xbt_strdup (valuestr);
216           xbt_dict_set (method_b_dict, timekey, nowdeltastr_cpy, xbt_free);
217           xbt_dict_set (method_b_dict, valuekey, valuestr_cpy, xbt_free);
218         }
219       }else{ /* lasttime != now */
220         /* the last time is different from new starting time, subtract to lasttime and add from nowstr */
221         pajeSubVariable (atof(lasttime), variable, resource, lastvalue);
222         pajeAddVariable (atof(nowstr), variable, resource, valuestr);
223         nowdeltastr_cpy = xbt_strdup (nowdeltastr);
224         valuestr_cpy = xbt_strdup (valuestr);
225         xbt_dict_set (method_b_dict, timekey, nowdeltastr_cpy, xbt_free);
226         xbt_dict_set (method_b_dict, valuekey, valuestr_cpy, xbt_free);
227       }
228     }else{ /* variable has changed */
229       pajeSubVariable (atof(lasttime), lastvariable, resource, lastvalue);
230       __TRACE_surf_check_variable_set_to_zero (now, variable, resource);
231       pajeAddVariable (now, variable, resource, valuestr);
232       nowdeltastr_cpy = xbt_strdup (nowdeltastr);
233       valuestr_cpy = xbt_strdup (valuestr);
234       variable_cpy = xbt_strdup (variable);
235       xbt_dict_set (method_b_dict, timekey, nowdeltastr_cpy, xbt_free);
236       xbt_dict_set (method_b_dict, valuekey, valuestr_cpy, xbt_free);
237       xbt_dict_set (method_b_dict, variablekey, variable_cpy, xbt_free);
238     }
239   }
240   return;
241 }
242 static void __TRACE_B_end (smx_action_t action) {}
243
244 #define C_METHOD
245 //C
246 static void __TRACE_C_alloc (void)
247 {
248   method_c_dict = xbt_dict_new();
249 }
250
251 static void __TRACE_C_release (void)
252 {
253   xbt_dict_free (&method_c_dict);
254 }
255
256 static void __TRACE_C_start (smx_action_t action)
257 {
258   char key[100];
259   snprintf (key, 100, "%p", action);
260
261   //check if exists
262   if (xbt_dict_get_or_null (method_c_dict, key)){
263     xbt_dict_remove (method_c_dict, key); //should never execute here, but it does
264   }
265   xbt_dict_set (method_c_dict, key, xbt_dict_new(), xbt_free);
266 }
267
268 static void __TRACE_C_event (smx_action_t action, double now, double delta, const char *variable, const char *resource, double value)
269 {
270   char key[100];
271   snprintf (key, 100, "%p", action);
272
273   xbt_dict_t action_dict = xbt_dict_get (method_c_dict, key);
274   //setting start time
275   if (!xbt_dict_get_or_null (action_dict, "start")){
276     char start_time[100];
277     snprintf (start_time, 100, "%f", now);
278     xbt_dict_set (action_dict, "start", xbt_strdup (start_time), xbt_free);
279   }
280   //updating end time
281   char end_time[100];
282   snprintf (end_time, 100, "%f", now+delta);
283   xbt_dict_set (action_dict, "end", xbt_strdup (end_time), xbt_free);
284
285   //accumulate the value resource-variable
286   char res_var[300];
287   snprintf (res_var, 300, "%s %s", resource, variable);
288   double current_value_f;
289   char *current_value = xbt_dict_get_or_null (action_dict, res_var);
290   if (current_value){
291     current_value_f = atof (current_value);
292     current_value_f += value*delta;
293   }else{
294     current_value_f = value*delta;
295   }
296   char new_current_value[100];
297   snprintf (new_current_value, 100, "%f", current_value_f);
298   xbt_dict_set (action_dict, res_var, xbt_strdup (new_current_value), xbt_free);
299 }
300
301 static void __TRACE_C_end (smx_action_t action)
302 {
303   char key[100];
304   snprintf (key, 100, "%p", action);
305
306   xbt_dict_t action_dict = xbt_dict_get (method_c_dict, key);
307   double start_time = atof(xbt_dict_get (action_dict, "start"));
308   double end_time = atof(xbt_dict_get (action_dict, "end"));
309
310   xbt_dict_cursor_t cursor=NULL;
311   char *action_dict_key, *action_dict_value;
312   xbt_dict_foreach(action_dict,cursor,action_dict_key,action_dict_value) {
313     char resource[100], variable[100];
314     if (sscanf (action_dict_key, "%s %s", resource, variable) != 2) continue;
315     __TRACE_surf_check_variable_set_to_zero (start_time, variable, resource);
316     char value_str[100];
317     if(end_time-start_time != 0){
318       snprintf (value_str, 100, "%f", atof(action_dict_value)/(end_time-start_time));
319       pajeAddVariable (start_time, variable, resource, value_str);
320       pajeSubVariable (end_time, variable, resource, value_str);
321     }
322   }
323   xbt_dict_remove (method_c_dict, key);
324 }
325
326 #define RESOURCE_UTILIZATION_INTERFACE
327 /*
328  * TRACE_surf_link_set_utilization: entry point from SimGrid
329  */
330 void TRACE_surf_link_set_utilization (void *link, smx_action_t smx_action, double value, double now, double delta)
331 {
332   if (!IS_TRACING) return;
333   if (!value) return;
334   //only trace link utilization if link is known by tracing mechanism
335   if (!TRACE_surf_link_is_traced (link)) return;
336   if (!value) return;
337
338   //trace uncategorized link utilization
339   char resource[100];
340   snprintf (resource, 100, "%p", link);
341   TRACE_surf_resource_utilization_event (smx_action, now, delta, "bandwidth_used", resource, value);
342
343   //trace categorized utilization
344   if (!IS_TRACED(smx_action)) return;
345   char type[100];
346   snprintf (type, 100, "b%s", smx_action->category);
347   TRACE_surf_resource_utilization_event (smx_action, now, delta, type, resource, value);
348   return;
349 }
350
351 /*
352  * TRACE_surf_host_set_utilization: entry point from SimGrid
353  */
354 void TRACE_surf_host_set_utilization (const char *name, smx_action_t smx_action, double value, double now, double delta)
355 {
356   if (!IS_TRACING) return;
357   if (!value) return;
358
359   //trace uncategorized host utilization
360   TRACE_surf_resource_utilization_event (smx_action, now, delta, "power_used", name, value);
361
362   //trace categorized utilization
363   if (!IS_TRACED(smx_action)) return;
364   char type[100];
365   snprintf (type, 100, "p%s", smx_action->category);
366   TRACE_surf_resource_utilization_event (smx_action, now, delta, type, name, value);
367   return;
368 }
369
370 /*
371  * __TRACE_surf_resource_utilization_*: entry points from tracing functions
372  */
373 void TRACE_surf_resource_utilization_start (smx_action_t action)
374 {
375   if (!IS_TRACING) return;
376   TRACE_method_start (action);
377 }
378
379 void TRACE_surf_resource_utilization_event (smx_action_t action, double now, double delta, const char *variable, const char *resource, double value)
380 {
381   if (!IS_TRACING) return;
382   TRACE_method_event (action, now, delta, variable, resource, value);
383 }
384
385 void TRACE_surf_resource_utilization_end (smx_action_t action)
386 {
387   if (!IS_TRACING) return;
388   TRACE_method_end (action);
389 }
390
391 void TRACE_surf_resource_utilization_release ()
392 {
393   if (!IS_TRACING) return;
394   TRACE_method_release ();
395 }
396
397 static void __TRACE_define_method (char *method)
398 {
399   if (!strcmp(method, "a")){
400     TRACE_method_alloc = __TRACE_A_alloc;
401     TRACE_method_release = __TRACE_A_release;
402     TRACE_method_start = __TRACE_A_start;
403     TRACE_method_event = __TRACE_A_event;
404     TRACE_method_end = __TRACE_A_end;
405   }else if (!strcmp(method, "c")){
406     TRACE_method_alloc = __TRACE_C_alloc;
407     TRACE_method_release = __TRACE_C_release;
408     TRACE_method_start = __TRACE_C_start;
409     TRACE_method_event = __TRACE_C_event;
410     TRACE_method_end = __TRACE_C_end;
411   }else{ //default is B
412     TRACE_method_alloc = __TRACE_B_alloc;
413     TRACE_method_release = __TRACE_B_release;
414     TRACE_method_start = __TRACE_B_start;
415     TRACE_method_event = __TRACE_B_event;
416     TRACE_method_end = __TRACE_B_end;
417   }
418 }
419
420 void TRACE_surf_resource_utilization_alloc ()
421 {
422   platform_variables = xbt_dict_new();
423   __TRACE_define_method (TRACE_get_platform_method());
424   TRACE_method_alloc ();
425 }
426 #endif