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/strings/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 : base::CommandLine::Init(argc, argv);
68 :
69 m : logging::LoggingSettings settings;
70 m : settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
71 m : settings.lock_log = logging::DONT_LOCK_LOG_FILE;
72 m : settings.delete_old = logging::APPEND_TO_OLD_LOG_FILE;
73 m : if (!logging::InitLogging(settings))
74 m : return 1;
75 :
76 m : base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
77 m : DCHECK(cmd_line != NULL);
78 :
79 : // Parse the command line.
80 m : typedef base::CommandLine::StringType StringType;
81 m : base::FilePath instrumented_dll_path =
82 m : cmd_line->GetSwitchValuePath("instrumented-dll");
83 m : base::FilePath input_dll_path = cmd_line->GetSwitchValuePath("input-dll");
84 m : base::FilePath output_file_path = cmd_line->GetSwitchValuePath("output-file");
85 m : bool pretty_print = cmd_line->HasSwitch("pretty-print");
86 m : std::string simulate_method =
87 m : cmd_line->GetSwitchValueASCII("simulate-method");
88 :
89 m : std::vector<base::FilePath> trace_paths;
90 m : for (size_t i = 0; i < cmd_line->GetArgs().size(); ++i)
91 m : trace_paths.push_back(base::FilePath(cmd_line->GetArgs()[i]));
92 :
93 m : if (instrumented_dll_path.empty())
94 m : return Usage("You must specify instrumented-dll.");
95 m : if (trace_paths.empty())
96 m : return Usage("You must specify at least one trace file.");
97 :
98 m : scoped_ptr<SimulationEventHandler> simulation;
99 :
100 m : if (simulate_method == "pagefault") {
101 m : PageFaultSimulation* page_fault_simulation = new PageFaultSimulation();
102 m : DCHECK(page_fault_simulation != NULL);
103 m : simulation.reset(page_fault_simulation);
104 :
105 m : int page_size = 0;
106 m : int pages_per_code_fault = 0;
107 m : StringType page_size_str = cmd_line->GetSwitchValueNative("page-size");
108 m : StringType pages_per_code_fault_str =
109 m : cmd_line->GetSwitchValueNative("pages-per-code-fault");
110 :
111 m : if (!page_size_str.empty()) {
112 m : if (!base::StringToInt(page_size_str, &page_size))
113 m : return Usage("Invalid page-size value.");
114 m : else
115 m : page_fault_simulation->set_page_size(page_size);
116 m : }
117 :
118 m : if (!pages_per_code_fault_str.empty()) {
119 m : if (!base::StringToInt(pages_per_code_fault_str, &pages_per_code_fault))
120 m : return Usage("Invalid pages-per-code-fault value.");
121 m : else
122 m : page_fault_simulation->set_pages_per_code_fault(pages_per_code_fault);
123 m : }
124 m : } else if (simulate_method == "heatmap") {
125 m : HeatMapSimulation* heat_map_simulation = new HeatMapSimulation();
126 m : DCHECK(heat_map_simulation != NULL);
127 m : simulation.reset(heat_map_simulation);
128 :
129 m : int time_slice_usecs = 0;
130 m : int memory_slice_bytes = 0;
131 m : StringType time_slice_usecs_str =
132 m : cmd_line->GetSwitchValueNative("time-slice-usecs");
133 m : StringType memory_slice_bytes_str =
134 m : cmd_line->GetSwitchValueNative("memory-slice-bytes");
135 :
136 m : if (!time_slice_usecs_str.empty()) {
137 m : if (!base::StringToInt(time_slice_usecs_str, &time_slice_usecs))
138 m : return Usage("Invalid time-slice-usecs value.");
139 m : else
140 m : heat_map_simulation->set_time_slice_usecs(time_slice_usecs);
141 m : }
142 :
143 m : if (!memory_slice_bytes_str.empty()) {
144 m : if (!base::StringToInt(memory_slice_bytes_str, &memory_slice_bytes))
145 m : return Usage("Invalid memory-slice-bytes value.");
146 m : else
147 m : heat_map_simulation->set_memory_slice_bytes(memory_slice_bytes);
148 m : }
149 :
150 m : heat_map_simulation->set_output_individual_functions(
151 m : cmd_line->HasSwitch("output-individual-functions"));
152 m : } else {
153 m : return Usage("Invalid simulate-method value.");
154 m : }
155 :
156 :
157 m : Simulator simulator(input_dll_path,
158 m : instrumented_dll_path,
159 m : trace_paths,
160 m : simulation.get());
161 :
162 m : LOG(INFO) << "Parsing trace files.";
163 m : if (!simulator.ParseTraceFiles()) {
164 m : LOG(ERROR) << "Could not parse trace files.";
165 m : return 1;
166 m : }
167 :
168 m : base::ScopedFILE output_file;
169 m : FILE* output = NULL;
170 m : if (output_file_path.empty()) {
171 m : output = stdout;
172 m : } else {
173 m : output_file.reset(base::OpenFile(output_file_path, "w"));
174 m : output = output_file.get();
175 :
176 m : if (output == NULL) {
177 m : LOG(ERROR) << "Failed to open " << output_file_path.value()
178 m : << " for writing.";
179 m : return 1;
180 m : }
181 m : }
182 :
183 m : LOG(INFO) << "Writing JSON file.";
184 m : if (!simulation->SerializeToJSON(output, pretty_print)) {
185 m : LOG(ERROR) << "Unable to write JSON file.";
186 m : return 1;
187 m : }
188 :
189 m : return 0;
190 m : }
|