1 : // Copyright 2012 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Parses trace files from an RPC instrumented dll file, and reports the number
16 : // of page-faults on them.
17 :
18 : #include <objbase.h>
19 : #include <iostream>
20 : #include <set>
21 :
22 : #include "base/at_exit.h"
23 : #include "base/command_line.h"
24 : #include "base/string_number_conversions.h"
25 : #include "syzygy/simulate/heat_map_simulation.h"
26 : #include "syzygy/simulate/page_fault_simulation.h"
27 : #include "syzygy/simulate/simulator.h"
28 :
29 m : namespace {
30 :
31 m : using simulate::HeatMapSimulation;
32 m : using simulate::PageFaultSimulation;
33 m : using simulate::SimulationEventHandler;
34 m : using simulate::Simulator;
35 :
36 m : const char kUsage[] =
37 m : "Usage: simulate [options] [RPC log files ...]\n"
38 m : " Required Options:\n"
39 m : " --instrumented-dll=<path> the path to the instrumented DLL.\n"
40 m : " --simulate-method=pagefault|heatmap what method used to simulate\n"
41 m : " the trace files.\n"
42 m : " Optional Options:\n"
43 m : " --pretty-print enables pretty printing of the JSON output file.\n"
44 m : " --input-dll=<path> the input DLL from where the trace files belong.\n"
45 m : " --output-file=<path> the output file.\n"
46 m : " For page fault method:\n"
47 m : " --pages-per-code-fault=INT The number of pages loaded by each\n"
48 m : " page-fault (default 8)\n"
49 m : " --page-size=INT the size of each page, in bytes (default 4KB).\n"
50 m : " For heat map method:\n"
51 m : " --time-slice-usecs=INT the size of each time slice in the heatmap,\n"
52 m : " in microseconds (default 1).\n"
53 m : " --memory-slice-bytes=INT the size of each memory slice,\n"
54 m : " in bytes (default 32KB).\n"
55 m : " --output-individual-functions Output information about each\n"
56 m : " function in each time/memory block\n";
57 :
58 m : int Usage(const char* message) {
59 m : std::cerr << message << std::endl << kUsage;
60 m : return 1;
61 m : }
62 :
63 m : } // namespace
64 :
65 m : int main(int argc, char** argv) {
66 m : base::AtExitManager at_exit_manager;
67 m : CommandLine::Init(argc, argv);
68 :
69 m : if (!logging::InitLogging(L"", logging::LOG_ONLY_TO_SYSTEM_DEBUG_LOG,
70 m : logging::DONT_LOCK_LOG_FILE, logging::APPEND_TO_OLD_LOG_FILE,
71 m : logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS)) {
72 m : return 1;
73 m : }
74 :
75 m : CommandLine* cmd_line = CommandLine::ForCurrentProcess();
76 m : DCHECK(cmd_line != NULL);
77 :
78 : // Parse the command line.
79 m : typedef CommandLine::StringType StringType;
80 m : base::FilePath instrumented_dll_path =
81 m : cmd_line->GetSwitchValuePath("instrumented-dll");
82 m : base::FilePath input_dll_path = cmd_line->GetSwitchValuePath("input-dll");
83 m : base::FilePath output_file_path = cmd_line->GetSwitchValuePath("output-file");
84 m : bool pretty_print = cmd_line->HasSwitch("pretty-print");
85 m : std::string simulate_method =
86 m : cmd_line->GetSwitchValueASCII("simulate-method");
87 :
88 m : std::vector<base::FilePath> trace_paths;
89 m : for (size_t i = 0; i < cmd_line->GetArgs().size(); ++i)
90 m : trace_paths.push_back(base::FilePath(cmd_line->GetArgs()[i]));
91 :
92 m : if (instrumented_dll_path.empty())
93 m : return Usage("You must specify instrumented-dll.");
94 m : if (trace_paths.empty())
95 m : return Usage("You must specify at least one trace file.");
96 :
97 m : scoped_ptr<SimulationEventHandler> simulation;
98 :
99 m : if (simulate_method == "pagefault") {
100 m : PageFaultSimulation* page_fault_simulation = new PageFaultSimulation();
101 m : DCHECK(page_fault_simulation != NULL);
102 m : simulation.reset(page_fault_simulation);
103 :
104 m : int page_size = 0;
105 m : int pages_per_code_fault = 0;
106 m : StringType page_size_str = cmd_line->GetSwitchValueNative("page-size");
107 m : StringType pages_per_code_fault_str =
108 m : cmd_line->GetSwitchValueNative("pages-per-code-fault");
109 :
110 m : if (!page_size_str.empty()) {
111 m : if (!base::StringToInt(page_size_str, &page_size))
112 m : return Usage("Invalid page-size value.");
113 m : else
114 m : page_fault_simulation->set_page_size(page_size);
115 m : }
116 :
117 m : if (!pages_per_code_fault_str.empty()) {
118 m : if (!base::StringToInt(pages_per_code_fault_str, &pages_per_code_fault))
119 m : return Usage("Invalid pages-per-code-fault value.");
120 m : else
121 m : page_fault_simulation->set_pages_per_code_fault(pages_per_code_fault);
122 m : }
123 m : } else if (simulate_method == "heatmap") {
124 m : HeatMapSimulation* heat_map_simulation = new HeatMapSimulation();
125 m : DCHECK(heat_map_simulation != NULL);
126 m : simulation.reset(heat_map_simulation);
127 :
128 m : int time_slice_usecs = 0;
129 m : int memory_slice_bytes = 0;
130 m : StringType time_slice_usecs_str =
131 m : cmd_line->GetSwitchValueNative("time-slice-usecs");
132 m : StringType memory_slice_bytes_str =
133 m : cmd_line->GetSwitchValueNative("memory-slice-bytes");
134 :
135 m : if (!time_slice_usecs_str.empty()) {
136 m : if (!base::StringToInt(time_slice_usecs_str, &time_slice_usecs))
137 m : return Usage("Invalid time-slice-usecs value.");
138 m : else
139 m : heat_map_simulation->set_time_slice_usecs(time_slice_usecs);
140 m : }
141 :
142 m : if (!memory_slice_bytes_str.empty()) {
143 m : if (!base::StringToInt(memory_slice_bytes_str, &memory_slice_bytes))
144 m : return Usage("Invalid memory-slice-bytes value.");
145 m : else
146 m : heat_map_simulation->set_memory_slice_bytes(memory_slice_bytes);
147 m : }
148 :
149 m : heat_map_simulation->set_output_individual_functions(
150 m : cmd_line->HasSwitch("output-individual-functions"));
151 m : } else {
152 m : return Usage("Invalid simulate-method value.");
153 m : }
154 :
155 :
156 m : Simulator simulator(input_dll_path,
157 m : instrumented_dll_path,
158 m : trace_paths,
159 m : simulation.get());
160 :
161 m : LOG(INFO) << "Parsing trace files.";
162 m : if (!simulator.ParseTraceFiles()) {
163 m : LOG(ERROR) << "Could not parse trace files.";
164 m : return 1;
165 m : }
166 :
167 m : file_util::ScopedFILE output_file;
168 m : FILE* output = NULL;
169 m : if (output_file_path.empty()) {
170 m : output = stdout;
171 m : } else {
172 m : output_file.reset(file_util::OpenFile(output_file_path, "w"));
173 m : output = output_file.get();
174 :
175 m : if (output == NULL) {
176 m : LOG(ERROR) << "Failed to open " << output_file_path.value()
177 m : << " for writing.";
178 m : return 1;
179 m : }
180 m : }
181 :
182 m : LOG(INFO) << "Writing JSON file.";
183 m : if (!simulation->SerializeToJSON(output, pretty_print)) {
184 m : LOG(ERROR) << "Unable to write JSON file.";
185 m : return 1;
186 m : }
187 :
188 m : return 0;
189 m : }
|