xref: /haiku/src/bin/debug/time_stats/time_stats.cpp (revision cbe0a0c436162d78cc3f92a305b64918c839d079)
1 /*
2  * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <getopt.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/stat.h>
13 #include <unistd.h>
14 
15 #include <OS.h>
16 
17 #include "time_stats.h"
18 
19 
20 #define SCHEDULING_ANALYSIS_BUFFER_SIZE	10 * 1024 * 1024
21 
22 
23 extern const char* __progname;
24 
25 static const char* kUsage =
26 	"Usage: %s [ <options> ] <command line>\n"
27 	"Executes the given command line <command line> and print an analysis of\n"
28 	"the user and kernel times of all threads that ran during that time.\n"
29 	"\n"
30 	"Options:\n"
31 	"  -b <size>    - When doing scheduling analysis: the size of the buffer\n"
32 	"                 used (in MB)\n"
33 	"  -h, --help   - Print this usage info.\n"
34 	"  -o <output>  - Print the results to file <output>.\n"
35 	"  -s           - Also perform a scheduling analysis over the time the\n"
36 	"                 child process ran. This requires that scheduler kernel\n"
37 	"                 tracing had been enabled at compile time.\n"
38 ;
39 
40 
41 static void
42 print_usage_and_exit(bool error)
43 {
44     fprintf(error ? stderr : stdout, kUsage, __progname);
45     exit(error ? 1 : 0);
46 }
47 
48 
49 int
50 main(int argc, const char* const* argv)
51 {
52 	const char* outputFile = NULL;
53 	bool schedulingAnalysis = false;
54 	size_t bufferSize = SCHEDULING_ANALYSIS_BUFFER_SIZE;
55 
56 	while (true) {
57 		static struct option sLongOptions[] = {
58 			{ "help", no_argument, 0, 'h' },
59 			{ "output", required_argument, 0, 'o' },
60 			{ 0, 0, 0, 0 }
61 		};
62 
63 		opterr = 0; // don't print errors
64 		int c = getopt_long(argc, (char**)argv, "+b:ho:s", sLongOptions, NULL);
65 		if (c == -1)
66 			break;
67 
68 		switch (c) {
69 			case 'b':
70 				bufferSize = atol(optarg);
71 				if (bufferSize < 1 || bufferSize > 1024) {
72 					fprintf(stderr, "Error: Invalid buffer size. Should be "
73 						"between 1 and 1024 MB\n");
74 					exit(1);
75 				}
76 				bufferSize *= 1024 * 1024;
77 				break;
78 			case 'h':
79 				print_usage_and_exit(false);
80 				break;
81 			case 'o':
82 				outputFile = optarg;
83 				break;
84 			case 's':
85 				schedulingAnalysis = true;
86 				break;
87 
88 			default:
89 				print_usage_and_exit(true);
90 				break;
91 		}
92 	}
93 
94 	if (optind >= argc)
95 		print_usage_and_exit(true);
96 
97 	// open output file, if specified
98 	int outFD = -1;
99 	if (outputFile != NULL) {
100 		outFD = open(outputFile, O_WRONLY | O_CREAT | O_TRUNC,
101 			S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP| S_IROTH | S_IWOTH);
102 		if (outFD < 0) {
103 			fprintf(stderr, "Error: Failed to open \"%s\": %s\n", outputFile,
104 				strerror(errno));
105 			exit(1);
106 		}
107 	}
108 
109 	do_timing_analysis(argc - optind, argv + optind, schedulingAnalysis, outFD,
110 		bufferSize);
111 
112 	return 0;
113 }
114