OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <sstream> | 5 #include <sstream> |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/path_service.h" | 9 #include "base/path_service.h" |
10 #include "base/profiler/stack_sampling_profiler.h" | 10 #include "base/profiler/stack_sampling_profiler.h" |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 void TargetThread::SignalAndWaitUntilSignaled( | 77 void TargetThread::SignalAndWaitUntilSignaled( |
78 WaitableEvent* thread_started_event, | 78 WaitableEvent* thread_started_event, |
79 WaitableEvent* finish_event) { | 79 WaitableEvent* finish_event) { |
80 thread_started_event->Signal(); | 80 thread_started_event->Signal(); |
81 finish_event->Wait(); | 81 finish_event->Wait(); |
82 } | 82 } |
83 #if defined(_WIN64) | 83 #if defined(_WIN64) |
84 #pragma optimize("", on) | 84 #pragma optimize("", on) |
85 #endif | 85 #endif |
86 | 86 |
| 87 // Called on the profiler thread when complete, to collect profiles. |
| 88 void SaveProfiles(std::vector<Profile>* profiles, |
| 89 const std::vector<Profile>& pending_profiles) { |
| 90 *profiles = pending_profiles; |
| 91 } |
| 92 |
87 // Called on the profiler thread when complete. Collects profiles produced by | 93 // Called on the profiler thread when complete. Collects profiles produced by |
88 // the profiler, and signals an event to allow the main thread to know that that | 94 // the profiler, and signals an event to allow the main thread to know that that |
89 // the profiler is done. | 95 // the profiler is done. |
90 void SaveProfilesAndSignalEvent(std::vector<Profile>* profiles, | 96 void SaveProfilesAndSignalEvent(std::vector<Profile>* profiles, |
91 WaitableEvent* event, | 97 WaitableEvent* event, |
92 const std::vector<Profile>& pending_profiles) { | 98 const std::vector<Profile>& pending_profiles) { |
93 *profiles = pending_profiles; | 99 *profiles = pending_profiles; |
94 event->Signal(); | 100 event->Signal(); |
95 } | 101 } |
96 | 102 |
97 // Captures profiles as specified by |params| on the TargetThread, and returns | 103 // Starts the target thread and ensures it's in SignalAndWaitUntilSignaled(), |
98 // them in |profiles|. Waits up to |profiler_wait_time| for the profiler to | 104 // runs the provided function passing the thread ID, then stops and joins the |
99 // complete. | 105 // target thread. |
100 void CaptureProfiles(const StackSamplingProfiler::SamplingParams& params, | 106 template <class Function> |
101 std::vector<Profile>* profiles, | 107 void WithTargetThread(Function function) { |
102 TimeDelta profiler_wait_time) { | |
103 TargetThread target_thread; | 108 TargetThread target_thread; |
104 PlatformThreadHandle target_thread_handle; | 109 PlatformThreadHandle target_thread_handle; |
105 EXPECT_TRUE(PlatformThread::Create(0, &target_thread, &target_thread_handle)); | 110 EXPECT_TRUE(PlatformThread::Create(0, &target_thread, &target_thread_handle)); |
106 | 111 |
107 target_thread.WaitForThreadStart(); | 112 target_thread.WaitForThreadStart(); |
108 | 113 |
109 WaitableEvent sampling_thread_completed(true, false); | 114 function(target_thread.id()); |
110 profiles->clear(); | |
111 StackSamplingProfiler profiler(target_thread.id(), params); | |
112 profiler.SetCustomCompletedCallback( | |
113 Bind(&SaveProfilesAndSignalEvent, Unretained(profiles), | |
114 Unretained(&sampling_thread_completed))); | |
115 profiler.Start(); | |
116 sampling_thread_completed.TimedWait(profiler_wait_time); | |
117 profiler.Stop(); | |
118 sampling_thread_completed.Wait(); | |
119 | 115 |
120 target_thread.SignalThreadToFinish(); | 116 target_thread.SignalThreadToFinish(); |
121 | 117 |
122 PlatformThread::Join(target_thread_handle); | 118 PlatformThread::Join(target_thread_handle); |
123 } | 119 } |
124 | 120 |
| 121 // Captures profiles as specified by |params| on the TargetThread, and returns |
| 122 // them in |profiles|. Waits up to |profiler_wait_time| for the profiler to |
| 123 // complete. |
| 124 void CaptureProfilesWithObjectCallback( |
| 125 const StackSamplingProfiler::SamplingParams& params, |
| 126 std::vector<Profile>* profiles, |
| 127 TimeDelta profiler_wait_time) { |
| 128 profiles->clear(); |
| 129 |
| 130 WithTargetThread([¶ms, profiles, profiler_wait_time]( |
| 131 PlatformThreadId target_thread_id) { |
| 132 WaitableEvent sampling_thread_completed(true, false); |
| 133 const StackSamplingProfiler::CompletedCallback callback = |
| 134 Bind(&SaveProfilesAndSignalEvent, Unretained(profiles), |
| 135 Unretained(&sampling_thread_completed)); |
| 136 StackSamplingProfiler profiler(target_thread_id, params, callback); |
| 137 profiler.Start(); |
| 138 sampling_thread_completed.TimedWait(profiler_wait_time); |
| 139 profiler.Stop(); |
| 140 sampling_thread_completed.Wait(); |
| 141 }); |
| 142 } |
| 143 |
| 144 // Captures profiles as specified by |params| on the TargetThread, and returns |
| 145 // them in |profiles|. Uses the default callback rather than a per-object |
| 146 // callback. |
| 147 void CaptureProfilesWithDefaultCallback( |
| 148 const StackSamplingProfiler::SamplingParams& params, |
| 149 std::vector<Profile>* profiles) { |
| 150 profiles->clear(); |
| 151 |
| 152 WithTargetThread([¶ms, profiles](PlatformThreadId target_thread_id) { |
| 153 WaitableEvent sampling_thread_completed(false, false); |
| 154 StackSamplingProfiler::SetDefaultCompletedCallback( |
| 155 Bind(&SaveProfilesAndSignalEvent, Unretained(profiles), |
| 156 Unretained(&sampling_thread_completed))); |
| 157 |
| 158 StackSamplingProfiler profiler(target_thread_id, params); |
| 159 profiler.Start(); |
| 160 sampling_thread_completed.Wait(); |
| 161 |
| 162 StackSamplingProfiler::SetDefaultCompletedCallback( |
| 163 StackSamplingProfiler::CompletedCallback()); |
| 164 }); |
| 165 } |
| 166 |
| 167 // Runs the profiler with |params| on the TargetThread, with no default or |
| 168 // per-object callback. |
| 169 void RunProfilerWithNoCallback( |
| 170 const StackSamplingProfiler::SamplingParams& params, |
| 171 TimeDelta profiler_wait_time) { |
| 172 WithTargetThread([¶ms, profiler_wait_time]( |
| 173 PlatformThreadId target_thread_id) { |
| 174 StackSamplingProfiler profiler(target_thread_id, params); |
| 175 profiler.Start(); |
| 176 // Since we don't specify a callback, we don't have a synchronization |
| 177 // mechanism with the sampling thread. Just sleep instead. |
| 178 PlatformThread::Sleep(profiler_wait_time); |
| 179 profiler.Stop(); |
| 180 }); |
| 181 } |
| 182 |
125 // If this executable was linked with /INCREMENTAL (the default for non-official | 183 // If this executable was linked with /INCREMENTAL (the default for non-official |
126 // debug and release builds on Windows), function addresses do not correspond to | 184 // debug and release builds on Windows), function addresses do not correspond to |
127 // function code itself, but instead to instructions in the Incremental Link | 185 // function code itself, but instead to instructions in the Incremental Link |
128 // Table that jump to the functions. Check for a jump instruction and if present | 186 // Table that jump to the functions. Check for a jump instruction and if present |
129 // do a little decompilation to find the function's actual starting address. | 187 // do a little decompilation to find the function's actual starting address. |
130 const void* MaybeFixupFunctionAddressForILT(const void* function_address) { | 188 const void* MaybeFixupFunctionAddressForILT(const void* function_address) { |
131 #if defined(_WIN64) | 189 #if defined(_WIN64) |
132 const unsigned char* opcode = | 190 const unsigned char* opcode = |
133 reinterpret_cast<const unsigned char*>(function_address); | 191 reinterpret_cast<const unsigned char*>(function_address); |
134 if (*opcode == 0xe9) { | 192 if (*opcode == 0xe9) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 #define MAYBE_Basic DISABLED_Basic | 249 #define MAYBE_Basic DISABLED_Basic |
192 #endif | 250 #endif |
193 TEST(StackSamplingProfilerTest, MAYBE_Basic) { | 251 TEST(StackSamplingProfilerTest, MAYBE_Basic) { |
194 StackSamplingProfiler::SamplingParams params; | 252 StackSamplingProfiler::SamplingParams params; |
195 params.initial_delay = params.burst_interval = params.sampling_interval = | 253 params.initial_delay = params.burst_interval = params.sampling_interval = |
196 TimeDelta::FromMilliseconds(0); | 254 TimeDelta::FromMilliseconds(0); |
197 params.bursts = 1; | 255 params.bursts = 1; |
198 params.samples_per_burst = 1; | 256 params.samples_per_burst = 1; |
199 | 257 |
200 std::vector<Profile> profiles; | 258 std::vector<Profile> profiles; |
201 CaptureProfiles(params, &profiles, AVeryLongTimeDelta()); | 259 CaptureProfilesWithObjectCallback(params, &profiles, AVeryLongTimeDelta()); |
202 | 260 |
203 // Check that the profile and samples sizes are correct, and the module | 261 // Check that the profile and samples sizes are correct, and the module |
204 // indices are in range. | 262 // indices are in range. |
205 | 263 |
206 ASSERT_EQ(1u, profiles.size()); | 264 ASSERT_EQ(1u, profiles.size()); |
207 const Profile& profile = profiles[0]; | 265 const Profile& profile = profiles[0]; |
208 ASSERT_EQ(1u, profile.samples.size()); | 266 ASSERT_EQ(1u, profile.samples.size()); |
209 EXPECT_EQ(params.sampling_interval, profile.sampling_period); | 267 EXPECT_EQ(params.sampling_interval, profile.sampling_period); |
210 const Sample& sample = profile.samples[0]; | 268 const Sample& sample = profile.samples[0]; |
211 for (const auto& frame : sample) { | 269 for (const auto& frame : sample) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 #define MAYBE_MultipleProfilesAndSamples DISABLED_MultipleProfilesAndSamples | 303 #define MAYBE_MultipleProfilesAndSamples DISABLED_MultipleProfilesAndSamples |
246 #endif | 304 #endif |
247 TEST(StackSamplingProfilerTest, MAYBE_MultipleProfilesAndSamples) { | 305 TEST(StackSamplingProfilerTest, MAYBE_MultipleProfilesAndSamples) { |
248 StackSamplingProfiler::SamplingParams params; | 306 StackSamplingProfiler::SamplingParams params; |
249 params.initial_delay = params.burst_interval = params.sampling_interval = | 307 params.initial_delay = params.burst_interval = params.sampling_interval = |
250 TimeDelta::FromMilliseconds(0); | 308 TimeDelta::FromMilliseconds(0); |
251 params.bursts = 2; | 309 params.bursts = 2; |
252 params.samples_per_burst = 3; | 310 params.samples_per_burst = 3; |
253 | 311 |
254 std::vector<Profile> profiles; | 312 std::vector<Profile> profiles; |
255 CaptureProfiles(params, &profiles, AVeryLongTimeDelta()); | 313 CaptureProfilesWithObjectCallback(params, &profiles, AVeryLongTimeDelta()); |
256 | 314 |
257 ASSERT_EQ(2u, profiles.size()); | 315 ASSERT_EQ(2u, profiles.size()); |
258 EXPECT_EQ(3u, profiles[0].samples.size()); | 316 EXPECT_EQ(3u, profiles[0].samples.size()); |
259 EXPECT_EQ(3u, profiles[1].samples.size()); | 317 EXPECT_EQ(3u, profiles[1].samples.size()); |
260 } | 318 } |
261 | 319 |
262 // Checks that no profiles are captured if the profiling is stopped during the | 320 // Checks that no profiles are captured if the profiling is stopped during the |
263 // initial delay. | 321 // initial delay. |
264 #if defined(_WIN64) | 322 #if defined(_WIN64) |
265 #define MAYBE_StopDuringInitialDelay StopDuringInitialDelay | 323 #define MAYBE_StopDuringInitialDelay StopDuringInitialDelay |
266 #else | 324 #else |
267 #define MAYBE_StopDuringInitialDelay DISABLED_StopDuringInitialDelay | 325 #define MAYBE_StopDuringInitialDelay DISABLED_StopDuringInitialDelay |
268 #endif | 326 #endif |
269 TEST(StackSamplingProfilerTest, MAYBE_StopDuringInitialDelay) { | 327 TEST(StackSamplingProfilerTest, MAYBE_StopDuringInitialDelay) { |
270 StackSamplingProfiler::SamplingParams params; | 328 StackSamplingProfiler::SamplingParams params; |
271 params.burst_interval = params.sampling_interval = | 329 params.burst_interval = params.sampling_interval = |
272 TimeDelta::FromMilliseconds(0); | 330 TimeDelta::FromMilliseconds(0); |
273 params.initial_delay = TimeDelta::FromSeconds(60); | 331 params.initial_delay = TimeDelta::FromSeconds(60); |
274 params.bursts = params.samples_per_burst = 1; | 332 params.bursts = params.samples_per_burst = 1; |
275 | 333 |
276 std::vector<Profile> profiles; | 334 std::vector<Profile> profiles; |
277 CaptureProfiles(params, &profiles, TimeDelta::FromMilliseconds(0)); | 335 CaptureProfilesWithObjectCallback(params, &profiles, |
| 336 TimeDelta::FromMilliseconds(0)); |
278 | 337 |
279 EXPECT_TRUE(profiles.empty()); | 338 EXPECT_TRUE(profiles.empty()); |
280 } | 339 } |
281 | 340 |
282 // Checks that the single completed profile is captured if the profiling is | 341 // Checks that the single completed profile is captured if the profiling is |
283 // stopped between bursts. | 342 // stopped between bursts. |
284 #if defined(_WIN64) | 343 #if defined(_WIN64) |
285 #define MAYBE_StopDuringInterBurstInterval StopDuringInterBurstInterval | 344 #define MAYBE_StopDuringInterBurstInterval StopDuringInterBurstInterval |
286 #else | 345 #else |
287 #define MAYBE_StopDuringInterBurstInterval DISABLED_StopDuringInterBurstInterval | 346 #define MAYBE_StopDuringInterBurstInterval DISABLED_StopDuringInterBurstInterval |
288 #endif | 347 #endif |
289 TEST(StackSamplingProfilerTest, MAYBE_StopDuringInterBurstInterval) { | 348 TEST(StackSamplingProfilerTest, MAYBE_StopDuringInterBurstInterval) { |
290 StackSamplingProfiler::SamplingParams params; | 349 StackSamplingProfiler::SamplingParams params; |
291 params.initial_delay = params.sampling_interval = | 350 params.initial_delay = params.sampling_interval = |
292 TimeDelta::FromMilliseconds(0); | 351 TimeDelta::FromMilliseconds(0); |
293 params.burst_interval = TimeDelta::FromSeconds(60); | 352 params.burst_interval = TimeDelta::FromSeconds(60); |
294 params.bursts = 2; | 353 params.bursts = 2; |
295 params.samples_per_burst = 1; | 354 params.samples_per_burst = 1; |
296 | 355 |
297 std::vector<Profile> profiles; | 356 std::vector<Profile> profiles; |
298 CaptureProfiles(params, &profiles, TimeDelta::FromMilliseconds(50)); | 357 CaptureProfilesWithObjectCallback(params, &profiles, |
| 358 TimeDelta::FromMilliseconds(50)); |
299 | 359 |
300 ASSERT_EQ(1u, profiles.size()); | 360 ASSERT_EQ(1u, profiles.size()); |
301 EXPECT_EQ(1u, profiles[0].samples.size()); | 361 EXPECT_EQ(1u, profiles[0].samples.size()); |
302 } | 362 } |
303 | 363 |
304 // Checks that only completed profiles are captured. | 364 // Checks that only completed profiles are captured. |
305 #if defined(_WIN64) | 365 #if defined(_WIN64) |
306 #define MAYBE_StopDuringInterSampleInterval StopDuringInterSampleInterval | 366 #define MAYBE_StopDuringInterSampleInterval StopDuringInterSampleInterval |
307 #else | 367 #else |
308 #define MAYBE_StopDuringInterSampleInterval \ | 368 #define MAYBE_StopDuringInterSampleInterval \ |
309 DISABLED_StopDuringInterSampleInterval | 369 DISABLED_StopDuringInterSampleInterval |
310 #endif | 370 #endif |
311 TEST(StackSamplingProfilerTest, MAYBE_StopDuringInterSampleInterval) { | 371 TEST(StackSamplingProfilerTest, MAYBE_StopDuringInterSampleInterval) { |
312 StackSamplingProfiler::SamplingParams params; | 372 StackSamplingProfiler::SamplingParams params; |
313 params.initial_delay = params.burst_interval = TimeDelta::FromMilliseconds(0); | 373 params.initial_delay = params.burst_interval = TimeDelta::FromMilliseconds(0); |
314 params.sampling_interval = TimeDelta::FromSeconds(60); | 374 params.sampling_interval = TimeDelta::FromSeconds(60); |
315 params.bursts = 1; | 375 params.bursts = 1; |
316 params.samples_per_burst = 2; | 376 params.samples_per_burst = 2; |
317 | 377 |
318 std::vector<Profile> profiles; | 378 std::vector<Profile> profiles; |
319 CaptureProfiles(params, &profiles, TimeDelta::FromMilliseconds(50)); | 379 CaptureProfilesWithObjectCallback(params, &profiles, |
| 380 TimeDelta::FromMilliseconds(50)); |
320 | 381 |
321 EXPECT_TRUE(profiles.empty()); | 382 EXPECT_TRUE(profiles.empty()); |
322 } | 383 } |
323 | 384 |
324 } // namespace tracked_objects | 385 // Checks that profiles are captured via the default completed callback. |
| 386 #if defined(_WIN64) |
| 387 #define MAYBE_DefaultCallback DefaultCallback |
| 388 #else |
| 389 #define MAYBE_DefaultCallback DISABLED_DefaultCallback |
| 390 #endif |
| 391 TEST(StackSamplingProfilerTest, MAYBE_DefaultCallback) { |
| 392 StackSamplingProfiler::SamplingParams params; |
| 393 params.initial_delay = params.burst_interval = params.sampling_interval = |
| 394 TimeDelta::FromMilliseconds(0); |
| 395 params.bursts = 1; |
| 396 params.samples_per_burst = 1; |
| 397 |
| 398 std::vector<Profile> profiles; |
| 399 CaptureProfilesWithDefaultCallback(params, &profiles); |
| 400 |
| 401 EXPECT_EQ(1u, profiles.size()); |
| 402 EXPECT_EQ(1u, profiles[0].samples.size()); |
| 403 } |
| 404 |
| 405 // Checks that profiles are queued until a default callback is set, then |
| 406 // delivered. |
| 407 #if defined(_WIN64) |
| 408 #define MAYBE_ProfilesQueuedWithNoCallback ProfilesQueuedWithNoCallback |
| 409 #else |
| 410 #define MAYBE_ProfilesQueuedWithNoCallback DISABLED_ProfilesQueuedWithNoCallback |
| 411 #endif |
| 412 TEST(StackSamplingProfilerTest, MAYBE_ProfilesQueuedWithNoCallback) { |
| 413 StackSamplingProfiler::SamplingParams params; |
| 414 params.initial_delay = params.burst_interval = params.sampling_interval = |
| 415 TimeDelta::FromMilliseconds(0); |
| 416 params.bursts = 1; |
| 417 params.samples_per_burst = 1; |
| 418 |
| 419 RunProfilerWithNoCallback(params, TimeDelta::FromMilliseconds(50)); |
| 420 |
| 421 std::vector<Profile> profiles; |
| 422 // This should immediately call SaveProfiles on this thread. |
| 423 StackSamplingProfiler::SetDefaultCompletedCallback( |
| 424 Bind(&SaveProfiles, Unretained(&profiles))); |
| 425 EXPECT_EQ(1u, profiles.size()); |
| 426 EXPECT_EQ(1u, profiles[0].samples.size()); |
| 427 StackSamplingProfiler::SetDefaultCompletedCallback( |
| 428 StackSamplingProfiler::CompletedCallback()); |
| 429 } |
| 430 |
| 431 // Checks that we can destroy the profiler while profiling. |
| 432 #if defined(_WIN64) |
| 433 #define MAYBE_DestroyProfilerWhileProfiling DestroyProfilerWhileProfiling |
| 434 #else |
| 435 #define MAYBE_DestroyProfilerWhileProfiling \ |
| 436 DISABLED_DestroyProfilerWhileProfiling |
| 437 #endif |
| 438 TEST(StackSamplingProfilerTest, MAYBE_DestroyProfilerWhileProfiling) { |
| 439 StackSamplingProfiler::SamplingParams params; |
| 440 params.initial_delay = params.burst_interval = TimeDelta::FromMilliseconds(0); |
| 441 params.sampling_interval = TimeDelta::FromMilliseconds(10); |
| 442 params.bursts = 1; |
| 443 params.samples_per_burst = 300; |
| 444 |
| 445 std::vector<Profile> profiles; |
| 446 WithTargetThread([¶ms, &profiles](PlatformThreadId target_thread_id) { |
| 447 scoped_ptr<StackSamplingProfiler> profiler; |
| 448 profiler.reset(new StackSamplingProfiler(target_thread_id, params, |
| 449 Bind(&SaveProfiles, |
| 450 Unretained(&profiles)))); |
| 451 profiler->Start(); |
| 452 profiler.reset(); |
| 453 |
| 454 // Wait longer than a sample interval to catch any use-after-free actions by |
| 455 // the profiler thread. |
| 456 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50)); |
| 457 }); |
| 458 |
| 459 EXPECT_TRUE(profiles.empty()); |
| 460 } |
| 461 |
| 462 } // namespace base |
OLD | NEW |