Logo AND Algorithmique Numérique Distribuée

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