| 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 |