aboutsummaryrefslogtreecommitdiff
path: root/miscutils
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-06-17 19:09:05 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-06-17 19:09:05 +0000
commit459be35234cc24b69309eb0ee22600024c73713e (patch)
tree15ac4122d9c42ec75ba68d342827e37fcb1306ed /miscutils
parente79dd06782175d50f639180cde5b2c56933aa2ee (diff)
downloadbusybox-w32-459be35234cc24b69309eb0ee22600024c73713e.tar.gz
busybox-w32-459be35234cc24b69309eb0ee22600024c73713e.tar.bz2
busybox-w32-459be35234cc24b69309eb0ee22600024c73713e.zip
hwclock: size optimizations
libbb/time.c: new file, introducing monotonic_us() pscan, traceroute, arping: use it instead of gettimeofday ping, zcip: TODO function old new delta monotonic_us - 89 +89 find_pair 164 180 +16 .rodata 129747 129763 +16 refresh 1144 1152 +8 ............ timeout 8 4 -4 static.start 8 4 -4 last 8 4 -4 parse_conf 1303 1284 -19 time_main 1149 1124 -25 gettimeofday_us 39 - -39 arping_main 2042 1969 -73 hwclock_main 594 501 -93 catcher 485 380 -105 traceroute_main 4300 4117 -183 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 8/11 up/down: 157/-562) Total: -405 bytes
Diffstat (limited to 'miscutils')
-rw-r--r--miscutils/time.c180
1 files changed, 76 insertions, 104 deletions
diff --git a/miscutils/time.c b/miscutils/time.c
index 705123c9e..578cb35ff 100644
--- a/miscutils/time.c
+++ b/miscutils/time.c
@@ -11,28 +11,16 @@
11 11
12#include "libbb.h" 12#include "libbb.h"
13 13
14#define TV_MSEC tv_usec / 1000
15
16/* Information on the resources used by a child process. */ 14/* Information on the resources used by a child process. */
17typedef struct { 15typedef struct {
18 int waitstatus; 16 int waitstatus;
19 struct rusage ru; 17 struct rusage ru;
20 struct timeval start, elapsed; /* Wallclock time of process. */ 18 unsigned elapsed_ms; /* Wallclock time of process. */
21} resource_t; 19} resource_t;
22 20
23/* msec = milliseconds = 1/1,000 (1*10e-3) second. 21/* msec = milliseconds = 1/1,000 (1*10e-3) second.
24 usec = microseconds = 1/1,000,000 (1*10e-6) second. */ 22 usec = microseconds = 1/1,000,000 (1*10e-6) second. */
25 23
26#ifndef TICKS_PER_SEC
27#define TICKS_PER_SEC 100
28#endif
29
30/* The number of milliseconds in one `tick' used by the `rusage' structure. */
31#define MSEC_PER_TICK (1000 / TICKS_PER_SEC)
32
33/* Return the number of clock ticks that occur in M milliseconds. */
34#define MSEC_TO_TICKS(m) ((m) / MSEC_PER_TICK)
35
36#define UL unsigned long 24#define UL unsigned long
37 25
38static const char default_format[] = "real\t%E\nuser\t%u\nsys\t%T"; 26static const char default_format[] = "real\t%E\nuser\t%u\nsys\t%T";
@@ -76,7 +64,6 @@ static const char long_format[] =
76static int resuse_end(pid_t pid, resource_t * resp) 64static int resuse_end(pid_t pid, resource_t * resp)
77{ 65{
78 int status; 66 int status;
79
80 pid_t caught; 67 pid_t caught;
81 68
82 /* Ignore signals, but don't ignore the children. When wait3 69 /* Ignore signals, but don't ignore the children. When wait3
@@ -85,18 +72,8 @@ static int resuse_end(pid_t pid, resource_t * resp)
85 if (caught == -1) 72 if (caught == -1)
86 return 0; 73 return 0;
87 } 74 }
88 75 resp->elapsed_ms = (monotonic_us() / 1000) - resp->elapsed_ms;
89 gettimeofday(&resp->elapsed, (struct timezone *) 0);
90 resp->elapsed.tv_sec -= resp->start.tv_sec;
91 if (resp->elapsed.tv_usec < resp->start.tv_usec) {
92 /* Manually carry a one from the seconds field. */
93 resp->elapsed.tv_usec += 1000000;
94 --resp->elapsed.tv_sec;
95 }
96 resp->elapsed.tv_usec -= resp->start.tv_usec;
97
98 resp->waitstatus = status; 76 resp->waitstatus = status;
99
100 return 1; 77 return 1;
101} 78}
102 79
@@ -181,30 +158,30 @@ static unsigned long ptok(unsigned long pages)
181 COMMAND is the command and args that are being summarized. 158 COMMAND is the command and args that are being summarized.
182 RESP is resource information on the command. */ 159 RESP is resource information on the command. */
183 160
161#ifndef TICKS_PER_SEC
162#define TICKS_PER_SEC 100
163#endif
164
184static void summarize(const char *fmt, char **command, resource_t * resp) 165static void summarize(const char *fmt, char **command, resource_t * resp)
185{ 166{
186 unsigned long r; /* Elapsed real milliseconds. */ 167 unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */
187 unsigned long v; /* Elapsed virtual (CPU) milliseconds. */ 168 unsigned cpu_ticks; /* Same, in "CPU ticks" */
188 169
189 if (WIFSTOPPED(resp->waitstatus)) 170 if (WIFSTOPPED(resp->waitstatus))
190 printf("Command stopped by signal %d\n", 171 printf("Command stopped by signal %u\n",
191 WSTOPSIG(resp->waitstatus)); 172 WSTOPSIG(resp->waitstatus));
192 else if (WIFSIGNALED(resp->waitstatus)) 173 else if (WIFSIGNALED(resp->waitstatus))
193 printf("Command terminated by signal %d\n", 174 printf("Command terminated by signal %u\n",
194 WTERMSIG(resp->waitstatus)); 175 WTERMSIG(resp->waitstatus));
195 else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus)) 176 else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus))
196 printf("Command exited with non-zero status %d\n", 177 printf("Command exited with non-zero status %u\n",
197 WEXITSTATUS(resp->waitstatus)); 178 WEXITSTATUS(resp->waitstatus));
198 179
199 /* Convert all times to milliseconds. Occasionally, one of these values 180 vv_ms = (resp->ru.ru_utime.tv_sec + resp->ru.ru_stime.tv_sec) * 1000
200 comes out as zero. Dividing by zero causes problems, so we first 181 + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000;
201 check the time value. If it is zero, then we take `evasive action'
202 instead of calculating a value. */
203 182
204 r = resp->elapsed.tv_sec * 1000 + resp->elapsed.tv_usec / 1000; 183 cpu_ticks = vv_ms * TICKS_PER_SEC / 1000;
205 184 if (!cpu_ticks) cpu_ticks = 1; /* we divide by it, must be nonzero */
206 v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC +
207 resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC;
208 185
209 /* putchar() != putc(stdout) in glibc! */ 186 /* putchar() != putc(stdout) in glibc! */
210 187
@@ -245,127 +222,122 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
245 break; 222 break;
246 case 'D': /* Average unshared data size. */ 223 case 'D': /* Average unshared data size. */
247 printf("%lu", 224 printf("%lu",
248 MSEC_TO_TICKS(v) == 0 ? 0 : 225 ptok((UL) resp->ru.ru_idrss) / cpu_ticks +
249 ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) + 226 ptok((UL) resp->ru.ru_isrss) / cpu_ticks);
250 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v)); 227 break;
251 break; 228 case 'E': { /* Elapsed real (wall clock) time. */
252 case 'E': /* Elapsed real (wall clock) time. */ 229 unsigned seconds = resp->elapsed_ms / 1000;
253 if (resp->elapsed.tv_sec >= 3600) /* One hour -> h:m:s. */ 230 if (seconds >= 3600) /* One hour -> h:m:s. */
254 printf("%ldh %ldm %02lds", 231 printf("%uh %um %02us",
255 resp->elapsed.tv_sec / 3600, 232 seconds / 3600,
256 (resp->elapsed.tv_sec % 3600) / 60, 233 (seconds % 3600) / 60,
257 resp->elapsed.tv_sec % 60); 234 seconds % 60);
258 else 235 else
259 printf("%ldm %ld.%02lds", /* -> m:s. */ 236 printf("%um %u.%02us", /* -> m:s. */
260 resp->elapsed.tv_sec / 60, 237 seconds / 60,
261 resp->elapsed.tv_sec % 60, 238 seconds % 60,
262 resp->elapsed.tv_usec / 10000); 239 (unsigned)(resp->elapsed_ms / 10) % 100);
263 break; 240 break;
241 }
264 case 'F': /* Major page faults. */ 242 case 'F': /* Major page faults. */
265 printf("%ld", resp->ru.ru_majflt); 243 printf("%lu", resp->ru.ru_majflt);
266 break; 244 break;
267 case 'I': /* Inputs. */ 245 case 'I': /* Inputs. */
268 printf("%ld", resp->ru.ru_inblock); 246 printf("%lu", resp->ru.ru_inblock);
269 break; 247 break;
270 case 'K': /* Average mem usage == data+stack+text. */ 248 case 'K': /* Average mem usage == data+stack+text. */
271 printf("%lu", 249 printf("%lu",
272 MSEC_TO_TICKS(v) == 0 ? 0 : 250 ptok((UL) resp->ru.ru_idrss) / cpu_ticks +
273 ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) + 251 ptok((UL) resp->ru.ru_isrss) / cpu_ticks +
274 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v) + 252 ptok((UL) resp->ru.ru_ixrss) / cpu_ticks);
275 ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
276 break; 253 break;
277 case 'M': /* Maximum resident set size. */ 254 case 'M': /* Maximum resident set size. */
278 printf("%lu", ptok((UL) resp->ru.ru_maxrss)); 255 printf("%lu", ptok((UL) resp->ru.ru_maxrss));
279 break; 256 break;
280 case 'O': /* Outputs. */ 257 case 'O': /* Outputs. */
281 printf("%ld", resp->ru.ru_oublock); 258 printf("%lu", resp->ru.ru_oublock);
282 break; 259 break;
283 case 'P': /* Percent of CPU this job got. */ 260 case 'P': /* Percent of CPU this job got. */
284 /* % cpu is (total cpu time)/(elapsed time). */ 261 /* % cpu is (total cpu time)/(elapsed time). */
285 if (r > 0) 262 if (resp->elapsed_ms > 0)
286 printf("%lu%%", (v * 100 / r)); 263 printf("%u%%", (unsigned)(vv_ms * 100 / resp->elapsed_ms));
287 else 264 else
288 printf("?%%"); 265 printf("?%%");
289 break; 266 break;
290 case 'R': /* Minor page faults (reclaims). */ 267 case 'R': /* Minor page faults (reclaims). */
291 printf("%ld", resp->ru.ru_minflt); 268 printf("%lu", resp->ru.ru_minflt);
292 break; 269 break;
293 case 'S': /* System time. */ 270 case 'S': /* System time. */
294 printf("%ld.%02ld", 271 printf("%u.%02u",
295 resp->ru.ru_stime.tv_sec, 272 (unsigned)resp->ru.ru_stime.tv_sec,
296 resp->ru.ru_stime.TV_MSEC / 10); 273 (unsigned)(resp->ru.ru_stime.tv_usec / 10000));
297 break; 274 break;
298 case 'T': /* System time. */ 275 case 'T': /* System time. */
299 if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */ 276 if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */
300 printf("%ldh %ldm %02lds", 277 printf("%uh %um %02us",
301 resp->ru.ru_stime.tv_sec / 3600, 278 (unsigned)(resp->ru.ru_stime.tv_sec / 3600),
302 (resp->ru.ru_stime.tv_sec % 3600) / 60, 279 (unsigned)(resp->ru.ru_stime.tv_sec % 3600) / 60,
303 resp->ru.ru_stime.tv_sec % 60); 280 (unsigned)(resp->ru.ru_stime.tv_sec % 60));
304 else 281 else
305 printf("%ldm %ld.%02lds", /* -> m:s. */ 282 printf("%um %u.%02us", /* -> m:s. */
306 resp->ru.ru_stime.tv_sec / 60, 283 (unsigned)(resp->ru.ru_stime.tv_sec / 60),
307 resp->ru.ru_stime.tv_sec % 60, 284 (unsigned)(resp->ru.ru_stime.tv_sec % 60),
308 resp->ru.ru_stime.tv_usec / 10000); 285 (unsigned)(resp->ru.ru_stime.tv_usec / 10000));
309 break; 286 break;
310 case 'U': /* User time. */ 287 case 'U': /* User time. */
311 printf("%ld.%02ld", 288 printf("%u.%02u",
312 resp->ru.ru_utime.tv_sec, 289 (unsigned)resp->ru.ru_utime.tv_sec,
313 resp->ru.ru_utime.TV_MSEC / 10); 290 (unsigned)(resp->ru.ru_utime.tv_usec / 10000));
314 break; 291 break;
315 case 'u': /* User time. */ 292 case 'u': /* User time. */
316 if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */ 293 if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */
317 printf("%ldh %ldm %02lds", 294 printf("%uh %um %02us",
318 resp->ru.ru_utime.tv_sec / 3600, 295 (unsigned)(resp->ru.ru_utime.tv_sec / 3600),
319 (resp->ru.ru_utime.tv_sec % 3600) / 60, 296 (unsigned)(resp->ru.ru_utime.tv_sec % 3600) / 60,
320 resp->ru.ru_utime.tv_sec % 60); 297 (unsigned)(resp->ru.ru_utime.tv_sec % 60));
321 else 298 else
322 printf("%ldm %ld.%02lds", /* -> m:s. */ 299 printf("%um %u.%02us", /* -> m:s. */
323 resp->ru.ru_utime.tv_sec / 60, 300 (unsigned)(resp->ru.ru_utime.tv_sec / 60),
324 resp->ru.ru_utime.tv_sec % 60, 301 (unsigned)(resp->ru.ru_utime.tv_sec % 60),
325 resp->ru.ru_utime.tv_usec / 10000); 302 (unsigned)(resp->ru.ru_utime.tv_usec / 10000));
326 break; 303 break;
327 case 'W': /* Times swapped out. */ 304 case 'W': /* Times swapped out. */
328 printf("%ld", resp->ru.ru_nswap); 305 printf("%lu", resp->ru.ru_nswap);
329 break; 306 break;
330 case 'X': /* Average shared text size. */ 307 case 'X': /* Average shared text size. */
331 printf("%lu", 308 printf("%lu", ptok((UL) resp->ru.ru_ixrss) / cpu_ticks);
332 MSEC_TO_TICKS(v) == 0 ? 0 :
333 ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
334 break; 309 break;
335 case 'Z': /* Page size. */ 310 case 'Z': /* Page size. */
336 printf("%d", getpagesize()); 311 printf("%u", getpagesize());
337 break; 312 break;
338 case 'c': /* Involuntary context switches. */ 313 case 'c': /* Involuntary context switches. */
339 printf("%ld", resp->ru.ru_nivcsw); 314 printf("%lu", resp->ru.ru_nivcsw);
340 break; 315 break;
341 case 'e': /* Elapsed real time in seconds. */ 316 case 'e': /* Elapsed real time in seconds. */
342 printf("%ld.%02ld", 317 printf("%u.%02u",
343 resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000); 318 (unsigned)resp->elapsed_ms / 1000,
319 (unsigned)(resp->elapsed_ms / 10) % 100);
344 break; 320 break;
345 case 'k': /* Signals delivered. */ 321 case 'k': /* Signals delivered. */
346 printf("%ld", resp->ru.ru_nsignals); 322 printf("%lu", resp->ru.ru_nsignals);
347 break; 323 break;
348 case 'p': /* Average stack segment. */ 324 case 'p': /* Average stack segment. */
349 printf("%lu", 325 printf("%lu", ptok((UL) resp->ru.ru_isrss) / cpu_ticks);
350 MSEC_TO_TICKS(v) == 0 ? 0 :
351 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
352 break; 326 break;
353 case 'r': /* Incoming socket messages received. */ 327 case 'r': /* Incoming socket messages received. */
354 printf("%ld", resp->ru.ru_msgrcv); 328 printf("%lu", resp->ru.ru_msgrcv);
355 break; 329 break;
356 case 's': /* Outgoing socket messages sent. */ 330 case 's': /* Outgoing socket messages sent. */
357 printf("%ld", resp->ru.ru_msgsnd); 331 printf("%lu", resp->ru.ru_msgsnd);
358 break; 332 break;
359 case 't': /* Average resident set size. */ 333 case 't': /* Average resident set size. */
360 printf("%lu", 334 printf("%lu", ptok((UL) resp->ru.ru_idrss) / cpu_ticks);
361 MSEC_TO_TICKS(v) == 0 ? 0 :
362 ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v));
363 break; 335 break;
364 case 'w': /* Voluntary context switches. */ 336 case 'w': /* Voluntary context switches. */
365 printf("%ld", resp->ru.ru_nvcsw); 337 printf("%lu", resp->ru.ru_nvcsw);
366 break; 338 break;
367 case 'x': /* Exit status. */ 339 case 'x': /* Exit status. */
368 printf("%d", WEXITSTATUS(resp->waitstatus)); 340 printf("%u", WEXITSTATUS(resp->waitstatus));
369 break; 341 break;
370 } 342 }
371 break; 343 break;
@@ -403,7 +375,7 @@ static void run_command(char *const *cmd, resource_t * resp)
403 pid_t pid; /* Pid of child. */ 375 pid_t pid; /* Pid of child. */
404 __sighandler_t interrupt_signal, quit_signal; 376 __sighandler_t interrupt_signal, quit_signal;
405 377
406 gettimeofday(&resp->start, (struct timezone *) 0); 378 resp->elapsed_ms = monotonic_us() / 1000;
407 pid = vfork(); /* Run CMD as child process. */ 379 pid = vfork(); /* Run CMD as child process. */
408 if (pid < 0) 380 if (pid < 0)
409 bb_error_msg_and_die("cannot fork"); 381 bb_error_msg_and_die("cannot fork");