Contiki 2.5
profile-aggregates.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * $Id: profile-aggregates.c,v 1.4 2007/11/18 12:27:45 ksb Exp $
32  */
33 
34 /**
35  * \file
36  * Compuation of aggregates for the Contiki profiling system
37  * \author
38  * Adam Dunkels <adam@sics.se>
39  */
40 
41 #include "sys/profile.h"
42 
43 #include <stdlib.h>
44 #include <stdio.h>
45 
46 struct aggregate {
47  const char *ptr;
48  unsigned short episodes;
49  unsigned long cycles;
50 };
51 
52 #define DETAILED_AGGREGATES 0
53 
54 #define MAX_CATEGORIES 32
55 #define LIST_LEN 100
56 
57 static struct aggregate aggregates[LIST_LEN];
58 
59 static int aggregates_list_ptr = 0;
60 
61 /*---------------------------------------------------------------------------*/
62 static struct aggregate *
63 find_aggregate_category(const uint16_t cat)
64 {
65  int i;
66  uint16_t acat;
67 
68 /* printf("find_aggregate_category 0x%04x %c%c\n", */
69 /* cat, cat >> 8, cat & 0xff); */
70 
71  for(i = 0; i < aggregates_list_ptr; ++i) {
72  acat = (aggregates[i].ptr[0] << 8) + aggregates[i].ptr[1];
73 
74 /* printf("acat 0x%04x %c%c\n", */
75 /* acat, acat >> 8, acat & 0xff); */
76 
77  if(acat == cat) {
78  return &aggregates[i];
79  }
80  }
81 
82  if(i == LIST_LEN) {
83  return NULL;
84  }
85 
86  aggregates[aggregates_list_ptr].ptr = NULL;
87  return &aggregates[aggregates_list_ptr++];
88 }
89 /*---------------------------------------------------------------------------*/
90 #if DETAILED_AGGREGATES
91 static struct aggregate *
92 find_aggregate(const unsigned char *ptr)
93 {
94  int i;
95  for(i = 0; i < aggregates_list_ptr; ++i) {
96  if(aggregates[i].ptr == ptr) {
97  return &aggregates[i];
98  }
99  }
100  if(i == LIST_LEN) {
101  return NULL;
102  }
103 
104  return &aggregates[aggregates_list_ptr++];
105 }
106 #endif /* DETAILED_AGGREGATES */
107 /*---------------------------------------------------------------------------*/
108 void
109 profile_aggregates_print(void)
110 {
111  int i;
112 
113 #if DETAILED_AGGREGATES
114  for(i = 0; i < aggregates_list_ptr; ++i) {
115  printf("-- %s: %lu / %u = %lu\n", aggregates[i].ptr,
116  aggregates[i].cycles,
117  aggregates[i].episodes,
118  aggregates[i].cycles / aggregates[i].episodes);
119  }
120 #else
121  for(i = 0; i < aggregates_list_ptr; ++i) {
122  printf("-- %c%c: %lu / %u = %lu\n",
123  aggregates[i].ptr[0], aggregates[i].ptr[1],
124  aggregates[i].cycles,
125  aggregates[i].episodes,
126  aggregates[i].cycles / aggregates[i].episodes);
127  }
128 #endif
129 
130  printf("Memory for aggregates: %d * %d = %d\n",
131  (int)sizeof(struct aggregate), aggregates_list_ptr,
132  (int)sizeof(struct aggregate) * aggregates_list_ptr);
133 }
134 /*---------------------------------------------------------------------------*/
135 #if DETAILED_AGGREGATES
136 static void
137 detailed_profile_aggregates_compute(void)
138 {
139  int i;
140  rtimer_clock_t t;
141  /* const char *str = "profile_aggregates_compute";
142 
143  PROFILE_TIMESTAMP(str);*/
144 
145  t = profile_timestamps[0].time;
146 
147  for(i = 1; i < PROFILE_TIMESTAMP_PTR; ++i) {
148  struct aggregate *a;
149  a = find_aggregate(profile_timestamps[i - 1].ptr);
150  if(a == NULL) {
151  /* The list is full, skip this entry */
152  printf("profile_aggregates_compute: list full\n");
153  } else if(a->ptr == NULL) {
154  a->ptr = profile_timestamps[i - 1].ptr;
155  a->cycles = (unsigned long)(profile_timestamps[i].time - t);
156  a->episodes = 1;
157  } else {
158  a->cycles += (unsigned long)(profile_timestamps[i].time - t);
159  a->episodes++;
160  }
161  t = profile_timestamps[i].time;
162  }
163 
164  /* PROFILE_TIMESTAMP(str);*/
165 
166  /*printf("Aggregating time %u, len %d, list len %d, overhead %d\n",
167  profile_timediff(str, str), PROFILE_TIMESTAMP_PTR,
168  aggregates_list_ptr, profile_timestamp_time);*/
169 
170 
171  /* print_aggregates();*/
172 }
173 #endif /* DETAILED_AGGREGATES */
174 /*---------------------------------------------------------------------------*/
175 static void
176 category_profile_aggregates_compute(void)
177 {
178  int i,j;
179  rtimer_clock_t t;
180  uint16_t categories[MAX_CATEGORIES];
181  int categories_ptr = 0;
182  /* const char *str = "profile_aggregates_compute";
183 
184  PROFILE_TIMESTAMP(str);*/
185 
186  t = profile_timestamps[0].time;
187 
188  for(i = 1; i < PROFILE_TIMESTAMP_PTR; ++i) {
189  struct aggregate *a;
190  uint16_t cat;
191 
192 /* printf("category_profile_aggregates_compute %s\n", */
193 /* profile_timestamps[i - 1].ptr); */
194  cat = (profile_timestamps[i - 1].ptr[0] << 8) +
195  (profile_timestamps[i - 1].ptr[1] & 0xff);
196  a = find_aggregate_category(cat);
197  if(a == NULL) {
198  /* The list is full, skip this entry */
199  printf("profile_aggregates_compute: list full\n");
200  } else if(a->ptr == NULL) {
201  a->ptr = profile_timestamps[i - 1].ptr;
202  a->cycles = (unsigned long)(profile_timestamps[i].time - t - profile_timestamp_time);
203  a->episodes = 1;
204  } else {
205 
206  a->cycles += (unsigned long)(profile_timestamps[i].time - t - profile_timestamp_time);
207 
208  /* Make sure that we only update the episodes of each category
209  once per run. We keep track of all updated categories in the
210  "categories" array. If the category is already present in the
211  array, we do not update it. Otherwise, we insert the category
212  in the array and update the episodes counter of the
213  category. */
214 
215  for(j = 0; j < categories_ptr; ++j) {
216  if(categories[j] == cat) {
217  break;
218  }
219  }
220  if(j == categories_ptr) {
221  categories[j] = cat;
222  categories_ptr++;
223  a->episodes++;
224  }
225  }
226  t = profile_timestamps[i].time;
227  }
228 
229  /* PROFILE_TIMESTAMP(str);*/
230 
231  /*printf("Aggregating time %u, len %d, list len %d, overhead %d\n",
232  profile_timediff(str, str), PROFILE_TIMESTAMP_PTR,
233  aggregates_list_ptr, profile_timestamp_time);*/
234 
235 
236  /* print_aggregates();*/
237 }
238 /*---------------------------------------------------------------------------*/
239 void
240 profile_aggregates_compute(void)
241 {
242 #if DETAILED_AGGREGATES
243  detailed_profile_aggregates_compute();
244 #else
245  category_profile_aggregates_compute();
246 #endif
247 }
248 /*---------------------------------------------------------------------------*/