5 * DEBUG: section 81 CPU Profiling Routines
6 * AUTHOR: Andres Kroonmaa
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * the Regents of the University of California. Please see the
16 * COPYRIGHT file for full details. Squid incorporates software
17 * developed and/or copyrighted by other sources. Please see the
18 * CREDITS file for full details.
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
38 #include "CacheManager.h"
40 #ifdef USE_XPROF_STATS
45 #define MAX_SORTLIST 200
47 static hrtime_t xprof_delta
= 0;
48 static hrtime_t xprof_start_t
= 0;
49 static hrtime_t xprof_verystart
= 0;
50 static hrtime_t xprof_average_delta
= 0;
51 static int xprof_events
= 0;
52 static int xprof_inited
= 0;
53 static xprof_stats_data Totals
;
55 static TimersArray
*xprof_stats_avg1sec
= NULL
;
56 static TimersArray
*xprof_stats_avg5sec
= NULL
;
57 static TimersArray
*xprof_stats_avg30sec
= NULL
;
58 static TimersArray
*xprof_stats_avg1min
= NULL
;
59 static TimersArray
*xprof_stats_avg5min
= NULL
;
60 static TimersArray
*xprof_stats_avg30min
= NULL
;
61 static TimersArray
*xprof_stats_avg1hour
= NULL
;
62 static TimersArray
*xprof_stats_avg5hour
= NULL
;
63 static TimersArray
*xprof_stats_avg24hour
= NULL
;
65 static xprof_stats_node
*sortlist
[XPROF_LAST
+ 2];
66 static void xprof_summary(StoreEntry
* sentry
);
69 xprof_reset(xprof_stats_data
* head
)
74 head
->best
= XP_NOBEST
;
81 xprof_move(xprof_stats_data
* head
, xprof_stats_data
* hist
)
83 memcpy(hist
, head
, sizeof(xprof_stats_data
));
87 xprof_comp(xprof_stats_node
** ii
, xprof_stats_node
** jj
)
89 if ((*ii
)->hist
.summ
< (*jj
)->hist
.summ
)
92 if ((*ii
)->hist
.summ
> (*jj
)->hist
.summ
)
99 xprof_sorthist(TimersArray
* xprof_list
)
103 for (i
= 0; i
< XPROF_LAST
; i
++) {
104 sortlist
[i
] = xprof_list
[i
];
107 qsort(&sortlist
[XPROF_hash_lookup
], XPROF_LAST
- XPROF_hash_lookup
, sizeof(xprof_stats_node
*), (QS
*) xprof_comp
);
110 static double time_frame
;
113 xprof_show_item(StoreEntry
* sentry
, const char *name
, xprof_stats_data
* hist
)
115 storeAppendPrintf(sentry
,
116 "%s\t %" PRIu64
"\t %" PRIu64
"\t %" PRIu64
"\t %" PRIu64
"\t %" PRIu64
"\t %.2f\t %6.3f\t\n",
120 (hist
->best
!= XP_NOBEST
? hist
->best
: 0),
121 hist
->count
? hist
->summ
/ hist
->count
: 0,
123 hist
->count
/ time_frame
,
124 dpercent((double) hist
->summ
, (double) hist
->delta
));
128 xprof_summary_item(StoreEntry
* sentry
, char const *descr
, TimersArray
* list
)
131 xprof_stats_node
**hist
;
132 xprof_stats_data
*show
;
133 xprof_reset(&Totals
);
134 xprof_sorthist(list
);
137 show
= &hist
[0]->hist
;
139 if (!hist
[0]->hist
.delta
)
140 show
= &hist
[0]->accu
;
142 time_frame
= (double) show
->delta
/ (double) xprof_average_delta
;
144 storeAppendPrintf(sentry
, "\n%s:", descr
);
146 storeAppendPrintf(sentry
, " (Cumulated time: %" PRIu64
", %.2f sec)\n",
151 storeAppendPrintf(sentry
,
152 "Probe Name\t Events\t cumulated time \t best case \t average \t worst case\t Rate / sec \t %% in int\n");
154 for (i
= 0; i
< XPROF_LAST
; i
++) {
158 show
= &hist
[i
]->hist
;
163 xprof_show_item(sentry
, hist
[i
]->name
, show
);
165 Totals
.count
+= show
->count
;
167 Totals
.summ
+= show
->summ
;
169 Totals
.best
+= (show
->best
!= XP_NOBEST
? show
->best
: 0);
171 Totals
.worst
+= show
->worst
;
173 Totals
.delta
= (show
->delta
> Totals
.delta
? show
->delta
: Totals
.delta
);
176 xprof_show_item(sentry
, "TOTALS", &Totals
);
180 xprof_average(TimersArray
** list
, int secs
)
183 TimersArray
*head
= xprof_Timers
;
187 int doavg
= (xprof_events
% secs
);
190 *list
= (TimersArray
*)xcalloc(XPROF_LAST
, sizeof(xprof_stats_node
));
196 for (i
= 0; i
< XPROF_LAST
; i
++) {
197 hist
[i
]->name
= head
[i
]->name
;
198 hist
[i
]->accu
.summ
+= head
[i
]->accu
.summ
;
199 hist
[i
]->accu
.count
+= head
[i
]->accu
.count
; /* accumulate multisec */
201 if (!hist
[i
]->accu
.best
)
202 hist
[i
]->accu
.best
= head
[i
]->accu
.best
;
204 if (hist
[i
]->accu
.best
> head
[i
]->accu
.best
)
205 hist
[i
]->accu
.best
= head
[i
]->accu
.best
;
207 if (hist
[i
]->accu
.worst
< head
[i
]->accu
.worst
)
208 hist
[i
]->accu
.worst
= head
[i
]->accu
.worst
;
210 hist
[i
]->accu
.delta
+= xprof_delta
;
213 /* we have X seconds accumulated */
214 xprof_move(&hist
[i
]->accu
, &hist
[i
]->hist
);
215 xprof_reset(&hist
[i
]->accu
);
217 hist
[i
]->accu
.start
= now
;
220 /* reset 0sec counters */
222 keep
= head
[i
]->accu
.start
;
223 xprof_move(&head
[i
]->accu
, &head
[i
]->hist
);
224 xprof_reset(&head
[i
]->accu
);
225 hist
[i
]->accu
.delta
= 0;
226 head
[i
]->accu
.start
= keep
;
232 xprof_summary(StoreEntry
* sentry
)
234 hrtime_t now
= get_tick();
236 storeAppendPrintf(sentry
, "CPU Profiling Statistics:\n");
237 storeAppendPrintf(sentry
,
238 " (CPU times are in arbitrary units, most probably in CPU clock ticks)\n");
239 storeAppendPrintf(sentry
,
240 "Probe Name\t Event Count\t last Interval \t Avg Interval \t since squid start \t (since system boot) \n");
241 storeAppendPrintf(sentry
, "Total\t %lu\t %" PRIu64
" \t %" PRIu64
" \t %" PRIu64
" \t %" PRIu64
"\n",
242 (long unsigned) xprof_events
,
245 now
- xprof_verystart
,
248 xprof_summary_item(sentry
, "Last 1 sec averages", xprof_stats_avg1sec
);
249 xprof_summary_item(sentry
, "Last 5 sec averages", xprof_stats_avg5sec
);
250 xprof_summary_item(sentry
, "Last 30 sec averages", xprof_stats_avg30sec
);
251 xprof_summary_item(sentry
, "Last 1 min averages", xprof_stats_avg1min
);
252 xprof_summary_item(sentry
, "Last 5 min averages", xprof_stats_avg5min
);
253 xprof_summary_item(sentry
, "Last 30 min averages", xprof_stats_avg30min
);
254 xprof_summary_item(sentry
, "Last 1 hour averages", xprof_stats_avg1hour
);
255 xprof_summary_item(sentry
, "Last 5 hour averages", xprof_stats_avg5hour
);
256 xprof_summary_item(sentry
, "Last 24 hour averages", xprof_stats_avg24hour
);
260 xprof_chk_overhead(int samples
)
263 PROF_start(PROF_OVERHEAD
);
264 PROF_stop(PROF_OVERHEAD
);
269 xprofRegisterWithCacheManager(void)
271 CacheManager::GetInstance()->
272 registerAction("cpu_profile", "CPU Profiling Stats", xprof_summary
, 0, 1);
276 // this gets colled once per event. This doesn't seem to make much sense,
285 xprof_delta
= xprof_verystart
= xprof_start_t
= now
;
289 xprofRegisterWithCacheManager(); //moved here so it's not double-init'ed
293 xprof_event(void *data
)
297 xprof_delta
= now
- xprof_start_t
;
301 if (!xprof_average_delta
)
302 xprof_average_delta
= xprof_delta
;
304 if (xprof_average_delta
> (xprof_delta
>> 1))
305 xprof_average_delta
= xprof_average_delta
- (xprof_average_delta
>> 8) + (xprof_delta
>> 8);
307 xprof_chk_overhead(2);
309 xprof_average(&xprof_stats_avg24hour
, 24 * 3600);
311 xprof_average(&xprof_stats_avg5hour
, 5 * 3600);
313 xprof_average(&xprof_stats_avg1hour
, 3600);
315 xprof_average(&xprof_stats_avg30min
, 1800);
317 xprof_average(&xprof_stats_avg5min
, 300);
319 xprof_average(&xprof_stats_avg1min
, 60);
321 xprof_average(&xprof_stats_avg30sec
, 30);
323 xprof_average(&xprof_stats_avg5sec
, 5);
325 xprof_average(&xprof_stats_avg1sec
, 1);
327 xprof_chk_overhead(30);
329 eventAdd("cpuProfiling", xprof_event
, NULL
, 1.0, 1);
332 #endif /* USE_XPROF_STATS */