1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
14 #include "base/compiler_specific.h"
15 #include "base/files/file_util.h"
16 #include "base/functional/bind.h"
17 #include "base/functional/callback.h"
18 #include "base/location.h"
19 #include "base/memory/ptr_util.h"
20 #include "base/memory/raw_ptr.h"
21 #include "base/metrics/metrics_hashes.h"
22 #include "base/profiler/profiler_buildflags.h"
23 #include "base/profiler/sample_metadata.h"
24 #include "base/profiler/stack_sampler.h"
25 #include "base/profiler/stack_sampling_profiler.h"
26 #include "base/profiler/stack_sampling_profiler_test_util.h"
27 #include "base/profiler/unwinder.h"
28 #include "base/ranges/algorithm.h"
29 #include "base/run_loop.h"
30 #include "base/scoped_native_library.h"
31 #include "base/strings/utf_string_conversions.h"
32 #include "base/synchronization/lock.h"
33 #include "base/synchronization/waitable_event.h"
34 #include "base/test/bind.h"
35 #include "base/threading/simple_thread.h"
36 #include "base/time/time.h"
37 #include "build/build_config.h"
38 #include "testing/gtest/include/gtest/gtest.h"
48 // STACK_SAMPLING_PROFILER_SUPPORTED is used to conditionally enable the tests
49 // below for supported platforms (currently Win x64, Mac x64, iOS 64, some
50 // Android, and ChromeOS x64).
51 // ChromeOS: These don't run under MSan because parts of the stack aren't
53 #if (BUILDFLAG(IS_WIN) && defined(ARCH_CPU_X86_64)) || \
54 (BUILDFLAG(IS_MAC) && defined(ARCH_CPU_X86_64)) || \
55 (BUILDFLAG(IS_IOS) && defined(ARCH_CPU_64_BITS)) || \
56 (BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_ARM_CFI_TABLE)) || \
57 (BUILDFLAG(IS_CHROMEOS) && defined(ARCH_CPU_X86_64) && \
58 !defined(MEMORY_SANITIZER))
59 #define STACK_SAMPLING_PROFILER_SUPPORTED 1
64 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
65 #define PROFILER_TEST_F(TestClass, TestName) TEST_F(TestClass, TestName)
67 #define PROFILER_TEST_F(TestClass, TestName) \
68 TEST_F(TestClass, DISABLED_##TestName)
71 using SamplingParams = StackSamplingProfiler::SamplingParams;
75 // State provided to the ProfileBuilder's ApplyMetadataRetrospectively function.
76 struct RetrospectiveMetadata {
77 TimeTicks period_start;
79 MetadataRecorder::Item item;
82 // Profile consists of a set of samples and other sampling information.
84 // The collected samples.
85 std::vector<std::vector<Frame>> samples;
87 // The number of invocations of RecordMetadata().
88 int record_metadata_count;
90 // The retrospective metadata requests.
91 std::vector<RetrospectiveMetadata> retrospective_metadata;
93 // The profile metadata requests.
94 std::vector<MetadataRecorder::Item> profile_metadata;
96 // Duration of this profile.
97 TimeDelta profile_duration;
99 // Time between samples.
100 TimeDelta sampling_period;
103 // The callback type used to collect a profile. The passed Profile is move-only.
104 // Other threads, including the UI thread, may block on callback completion so
105 // this should run as quickly as possible.
106 using ProfileCompletedCallback = OnceCallback<void(Profile)>;
108 // TestProfileBuilder collects samples produced by the profiler.
109 class TestProfileBuilder : public ProfileBuilder {
111 TestProfileBuilder(ModuleCache* module_cache,
112 ProfileCompletedCallback callback);
114 TestProfileBuilder(const TestProfileBuilder&) = delete;
115 TestProfileBuilder& operator=(const TestProfileBuilder&) = delete;
117 ~TestProfileBuilder() override;
120 ModuleCache* GetModuleCache() override;
122 const MetadataRecorder::MetadataProvider& metadata_provider) override;
123 void ApplyMetadataRetrospectively(
124 TimeTicks period_start,
125 TimeTicks period_end,
126 const MetadataRecorder::Item& item) override;
127 void AddProfileMetadata(const MetadataRecorder::Item& item) override;
128 void OnSampleCompleted(std::vector<Frame> sample,
129 TimeTicks sample_timestamp) override;
130 void OnProfileCompleted(TimeDelta profile_duration,
131 TimeDelta sampling_period) override;
134 raw_ptr<ModuleCache> module_cache_;
136 // The set of recorded samples.
137 std::vector<std::vector<Frame>> samples_;
139 // The number of invocations of RecordMetadata().
140 int record_metadata_count_ = 0;
142 // The retrospective metadata requests.
143 std::vector<RetrospectiveMetadata> retrospective_metadata_;
145 // The profile metadata requests.
146 std::vector<MetadataRecorder::Item> profile_metadata_;
148 // Callback made when sampling a profile completes.
149 ProfileCompletedCallback callback_;
152 TestProfileBuilder::TestProfileBuilder(ModuleCache* module_cache,
153 ProfileCompletedCallback callback)
154 : module_cache_(module_cache), callback_(std::move(callback)) {}
156 TestProfileBuilder::~TestProfileBuilder() = default;
158 ModuleCache* TestProfileBuilder::GetModuleCache() {
159 return module_cache_;
162 void TestProfileBuilder::RecordMetadata(
163 const MetadataRecorder::MetadataProvider& metadata_provider) {
164 ++record_metadata_count_;
167 void TestProfileBuilder::ApplyMetadataRetrospectively(
168 TimeTicks period_start,
169 TimeTicks period_end,
170 const MetadataRecorder::Item& item) {
171 retrospective_metadata_.push_back(
172 RetrospectiveMetadata{period_start, period_end, item});
175 void TestProfileBuilder::AddProfileMetadata(
176 const MetadataRecorder::Item& item) {
177 profile_metadata_.push_back(item);
180 void TestProfileBuilder::OnSampleCompleted(std::vector<Frame> sample,
181 TimeTicks sample_timestamp) {
182 samples_.push_back(std::move(sample));
185 void TestProfileBuilder::OnProfileCompleted(TimeDelta profile_duration,
186 TimeDelta sampling_period) {
187 std::move(callback_).Run(Profile{samples_, record_metadata_count_,
188 retrospective_metadata_, profile_metadata_,
189 profile_duration, sampling_period});
192 // Unloads |library| and returns when it has completed unloading. Unloading a
193 // library is asynchronous on Windows, so simply calling UnloadNativeLibrary()
194 // is insufficient to ensure it's been unloaded.
195 void SynchronousUnloadNativeLibrary(NativeLibrary library) {
196 UnloadNativeLibrary(library);
197 #if BUILDFLAG(IS_WIN)
198 // NativeLibrary is a typedef for HMODULE, which is actually the base address
200 uintptr_t module_base_address = reinterpret_cast<uintptr_t>(library);
201 HMODULE module_handle;
202 // Keep trying to get the module handle until the call fails.
203 while (::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
204 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
205 reinterpret_cast<LPCTSTR>(module_base_address),
207 ::GetLastError() != ERROR_MOD_NOT_FOUND) {
208 PlatformThread::Sleep(Milliseconds(1));
210 #elif BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS)
211 // Unloading a library on Mac and Android is synchronous.
217 void WithTargetThread(ProfileCallback profile_callback) {
218 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
219 WithTargetThread(&scenario, std::move(profile_callback));
222 struct TestProfilerInfo {
223 TestProfilerInfo(SamplingProfilerThreadToken thread_token,
224 const SamplingParams& params,
225 ModuleCache* module_cache,
226 StackSamplerTestDelegate* delegate = nullptr)
227 : completed(WaitableEvent::ResetPolicy::MANUAL,
228 WaitableEvent::InitialState::NOT_SIGNALED),
229 profiler(thread_token,
231 std::make_unique<TestProfileBuilder>(
233 BindLambdaForTesting([this](Profile result_profile) {
234 profile = std::move(result_profile);
237 CreateCoreUnwindersFactoryForTesting(module_cache),
241 TestProfilerInfo(const TestProfilerInfo&) = delete;
242 TestProfilerInfo& operator=(const TestProfilerInfo&) = delete;
244 // The order here is important to ensure objects being referenced don't get
245 // destructed until after the objects referencing them.
247 WaitableEvent completed;
248 StackSamplingProfiler profiler;
251 // Captures samples as specified by |params| on the TargetThread, and returns
252 // them. Waits up to |profiler_wait_time| for the profiler to complete.
253 std::vector<std::vector<Frame>> CaptureSamples(const SamplingParams& params,
254 TimeDelta profiler_wait_time,
255 ModuleCache* module_cache) {
256 std::vector<std::vector<Frame>> samples;
257 WithTargetThread(BindLambdaForTesting(
258 [&](SamplingProfilerThreadToken target_thread_token) {
259 TestProfilerInfo info(target_thread_token, params, module_cache);
260 info.profiler.Start();
261 info.completed.TimedWait(profiler_wait_time);
262 info.profiler.Stop();
263 info.completed.Wait();
264 samples = std::move(info.profile.samples);
270 // Waits for one of multiple samplings to complete.
271 size_t WaitForSamplingComplete(
272 const std::vector<std::unique_ptr<TestProfilerInfo>>& infos) {
273 // Map unique_ptrs to something that WaitMany can accept.
274 std::vector<WaitableEvent*> sampling_completed_rawptrs(infos.size());
275 ranges::transform(infos, sampling_completed_rawptrs.begin(),
276 [](const std::unique_ptr<TestProfilerInfo>& info) {
277 return &info.get()->completed;
279 // Wait for one profiler to finish.
280 return WaitableEvent::WaitMany(sampling_completed_rawptrs.data(),
281 sampling_completed_rawptrs.size());
284 // Returns a duration that is longer than the test timeout. We would use
285 // TimeDelta::Max() but https://crbug.com/465948.
286 TimeDelta AVeryLongTimeDelta() {
290 // Tests the scenario where the library is unloaded after copying the stack, but
291 // before walking it. If |wait_until_unloaded| is true, ensures that the
292 // asynchronous library loading has completed before walking the stack. If
293 // false, the unloading may still be occurring during the stack walk.
294 void TestLibraryUnload(bool wait_until_unloaded, ModuleCache* module_cache) {
295 // Test delegate that supports intervening between the copying of the stack
296 // and the walking of the stack.
297 class StackCopiedSignaler : public StackSamplerTestDelegate {
299 StackCopiedSignaler(WaitableEvent* stack_copied,
300 WaitableEvent* start_stack_walk,
301 bool wait_to_walk_stack)
302 : stack_copied_(stack_copied),
303 start_stack_walk_(start_stack_walk),
304 wait_to_walk_stack_(wait_to_walk_stack) {}
306 void OnPreStackWalk() override {
307 stack_copied_->Signal();
308 if (wait_to_walk_stack_)
309 start_stack_walk_->Wait();
313 const raw_ptr<WaitableEvent> stack_copied_;
314 const raw_ptr<WaitableEvent> start_stack_walk_;
315 const bool wait_to_walk_stack_;
318 SamplingParams params;
319 params.sampling_interval = Milliseconds(0);
320 params.samples_per_profile = 1;
322 NativeLibrary other_library = LoadOtherLibrary();
324 UnwindScenario scenario(
325 BindRepeating(&CallThroughOtherLibrary, Unretained(other_library)));
327 UnwindScenario::SampleEvents events;
328 TargetThread target_thread(
329 BindLambdaForTesting([&]() { scenario.Execute(&events); }));
330 target_thread.Start();
331 events.ready_for_sample.Wait();
333 WaitableEvent sampling_thread_completed(
334 WaitableEvent::ResetPolicy::MANUAL,
335 WaitableEvent::InitialState::NOT_SIGNALED);
338 WaitableEvent stack_copied(WaitableEvent::ResetPolicy::MANUAL,
339 WaitableEvent::InitialState::NOT_SIGNALED);
340 WaitableEvent start_stack_walk(WaitableEvent::ResetPolicy::MANUAL,
341 WaitableEvent::InitialState::NOT_SIGNALED);
342 StackCopiedSignaler test_delegate(&stack_copied, &start_stack_walk,
343 wait_until_unloaded);
344 StackSamplingProfiler profiler(
345 target_thread.thread_token(), params,
346 std::make_unique<TestProfileBuilder>(
348 BindLambdaForTesting(
349 [&profile, &sampling_thread_completed](Profile result_profile) {
350 profile = std::move(result_profile);
351 sampling_thread_completed.Signal();
353 CreateCoreUnwindersFactoryForTesting(module_cache), RepeatingClosure(),
358 // Wait for the stack to be copied and the target thread to be resumed.
361 // Cause the target thread to finish, so that it's no longer executing code in
362 // the library we're about to unload.
363 events.sample_finished.Signal();
364 target_thread.Join();
366 // Unload the library now that it's not being used.
367 if (wait_until_unloaded)
368 SynchronousUnloadNativeLibrary(other_library);
370 UnloadNativeLibrary(other_library);
372 // Let the stack walk commence after unloading the library, if we're waiting
374 start_stack_walk.Signal();
376 // Wait for the sampling thread to complete and fill out |profile|.
377 sampling_thread_completed.Wait();
379 // Look up the sample.
380 ASSERT_EQ(1u, profile.samples.size());
381 const std::vector<Frame>& sample = profile.samples[0];
383 if (wait_until_unloaded) {
384 // We expect the stack to look something like this, with the frame in the
385 // now-unloaded library having a null module.
387 // ... WaitableEvent and system frames ...
389 // TargetThread::OtherLibraryCallback
390 // <frame in unloaded library>
391 EXPECT_EQ(nullptr, sample.back().module)
393 << FormatSampleForDiagnosticOutput(sample);
395 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange()});
396 ExpectStackDoesNotContain(sample,
397 {scenario.GetSetupFunctionAddressRange(),
398 scenario.GetOuterFunctionAddressRange()});
400 // We didn't wait for the asynchronous unloading to complete, so the results
401 // are non-deterministic: if the library finished unloading we should have
402 // the same stack as |wait_until_unloaded|, if not we should have the full
403 // stack. The important thing is that we should not crash.
405 if (!sample.back().module) {
406 // This is the same case as |wait_until_unloaded|.
407 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange()});
408 ExpectStackDoesNotContain(sample,
409 {scenario.GetSetupFunctionAddressRange(),
410 scenario.GetOuterFunctionAddressRange()});
414 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
415 scenario.GetSetupFunctionAddressRange(),
416 scenario.GetOuterFunctionAddressRange()});
420 // Provide a suitable (and clean) environment for the tests below. All tests
421 // must use this class to ensure that proper clean-up is done and thus be
422 // usable in a later test.
423 class StackSamplingProfilerTest : public testing::Test {
425 void SetUp() override {
426 // The idle-shutdown time is too long for convenient (and accurate) testing.
427 // That behavior is checked instead by artificially triggering it through
429 StackSamplingProfiler::TestPeer::DisableIdleShutdown();
432 void TearDown() override {
433 // Be a good citizen and clean up after ourselves. This also re-enables the
434 // idle-shutdown behavior.
435 StackSamplingProfiler::TestPeer::Reset();
439 ModuleCache* module_cache() { return &module_cache_; }
442 ModuleCache module_cache_;
447 // Checks that the basic expected information is present in sampled frames.
449 // macOS ASAN is not yet supported - crbug.com/718628.
451 // TODO(https://crbug.com/1100175): Enable this test again for Android with
452 // ASAN. This is now disabled because the android-asan bot fails.
454 // If we're running the ChromeOS unit tests on Linux, this test will never pass
455 // because Ubuntu's libc isn't compiled with frame pointers. Skip if not a real
457 #if (defined(ADDRESS_SANITIZER) && BUILDFLAG(IS_APPLE)) || \
458 (defined(ADDRESS_SANITIZER) && BUILDFLAG(IS_ANDROID)) || \
459 (BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_CHROMEOS_DEVICE))
460 #define MAYBE_Basic DISABLED_Basic
462 #define MAYBE_Basic Basic
464 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_Basic) {
465 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
466 const std::vector<Frame>& sample = SampleScenario(&scenario, module_cache());
468 // Check that all the modules are valid.
469 for (const auto& frame : sample)
470 EXPECT_NE(nullptr, frame.module);
472 // The stack should contain a full unwind.
473 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
474 scenario.GetSetupFunctionAddressRange(),
475 scenario.GetOuterFunctionAddressRange()});
478 // A simple unwinder that always generates one frame then aborts the stack walk.
479 class TestAuxUnwinder : public Unwinder {
481 TestAuxUnwinder(const Frame& frame_to_report,
482 base::RepeatingClosure add_initial_modules_callback)
483 : frame_to_report_(frame_to_report),
484 add_initial_modules_callback_(std::move(add_initial_modules_callback)) {
487 TestAuxUnwinder(const TestAuxUnwinder&) = delete;
488 TestAuxUnwinder& operator=(const TestAuxUnwinder&) = delete;
490 void InitializeModules() override {
491 if (add_initial_modules_callback_)
492 add_initial_modules_callback_.Run();
494 bool CanUnwindFrom(const Frame& current_frame) const override { return true; }
496 UnwindResult TryUnwind(RegisterContext* thread_context,
498 std::vector<Frame>* stack) override {
499 stack->push_back(frame_to_report_);
500 return UnwindResult::kAborted;
504 const Frame frame_to_report_;
505 base::RepeatingClosure add_initial_modules_callback_;
508 // Checks that the profiler handles stacks containing dynamically-allocated
510 // macOS ASAN is not yet supported - crbug.com/718628.
511 // Android is not supported since Chrome unwind tables don't support dynamic
513 // If we're running the ChromeOS unit tests on Linux, this test will never pass
514 // because Ubuntu's libc isn't compiled with frame pointers. Skip if not a real
516 #if (defined(ADDRESS_SANITIZER) && BUILDFLAG(IS_APPLE)) || \
517 BUILDFLAG(IS_ANDROID) || \
518 (BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_CHROMEOS_DEVICE))
519 #define MAYBE_Alloca DISABLED_Alloca
521 #define MAYBE_Alloca Alloca
523 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_Alloca) {
524 UnwindScenario scenario(BindRepeating(&CallWithAlloca));
525 const std::vector<Frame>& sample = SampleScenario(&scenario, module_cache());
527 // The stack should contain a full unwind.
528 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
529 scenario.GetSetupFunctionAddressRange(),
530 scenario.GetOuterFunctionAddressRange()});
533 // Checks that a stack that runs through another library produces a stack with
534 // the expected functions.
535 // macOS ASAN is not yet supported - crbug.com/718628.
536 // iOS chrome doesn't support loading native libraries.
537 // Android is not supported when EXCLUDE_UNWIND_TABLES |other_library| doesn't
538 // have unwind tables.
539 // TODO(https://crbug.com/1100175): Enable this test again for Android with
540 // ASAN. This is now disabled because the android-asan bot fails.
541 // If we're running the ChromeOS unit tests on Linux, this test will never pass
542 // because Ubuntu's libc isn't compiled with frame pointers. Skip if not a real
544 #if (defined(ADDRESS_SANITIZER) && BUILDFLAG(IS_APPLE)) || \
545 BUILDFLAG(IS_IOS) || \
546 (BUILDFLAG(IS_ANDROID) && BUILDFLAG(EXCLUDE_UNWIND_TABLES)) || \
547 (BUILDFLAG(IS_ANDROID) && defined(ADDRESS_SANITIZER)) || \
548 (BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_CHROMEOS_DEVICE))
549 #define MAYBE_OtherLibrary DISABLED_OtherLibrary
551 #define MAYBE_OtherLibrary OtherLibrary
553 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_OtherLibrary) {
554 ScopedNativeLibrary other_library(LoadOtherLibrary());
555 UnwindScenario scenario(
556 BindRepeating(&CallThroughOtherLibrary, Unretained(other_library.get())));
557 const std::vector<Frame>& sample = SampleScenario(&scenario, module_cache());
559 // The stack should contain a full unwind.
560 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
561 scenario.GetSetupFunctionAddressRange(),
562 scenario.GetOuterFunctionAddressRange()});
565 // Checks that a stack that runs through a library that is unloading produces a
566 // stack, and doesn't crash.
567 // Unloading is synchronous on the Mac, so this test is inapplicable.
568 // Android is not supported when EXCLUDE_UNWIND_TABLES |other_library| doesn't
569 // have unwind tables.
570 // TODO(https://crbug.com/1100175): Enable this test again for Android with
571 // ASAN. This is now disabled because the android-asan bot fails.
572 // If we're running the ChromeOS unit tests on Linux, this test will never pass
573 // because Ubuntu's libc isn't compiled with frame pointers. Skip if not a real
575 #if BUILDFLAG(IS_APPLE) || \
576 (BUILDFLAG(IS_ANDROID) && BUILDFLAG(EXCLUDE_UNWIND_TABLES)) || \
577 (BUILDFLAG(IS_ANDROID) && defined(ADDRESS_SANITIZER)) || \
578 (BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_CHROMEOS_DEVICE))
579 #define MAYBE_UnloadingLibrary DISABLED_UnloadingLibrary
581 #define MAYBE_UnloadingLibrary UnloadingLibrary
583 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_UnloadingLibrary) {
584 TestLibraryUnload(false, module_cache());
587 // Checks that a stack that runs through a library that has been unloaded
588 // produces a stack, and doesn't crash.
589 // macOS ASAN is not yet supported - crbug.com/718628.
590 // Android is not supported since modules are found before unwinding.
591 // If we're running the ChromeOS unit tests on Linux, this test will never pass
592 // because Ubuntu's libc isn't compiled with frame pointers. Skip if not a real
594 #if (defined(ADDRESS_SANITIZER) && BUILDFLAG(IS_APPLE)) || \
595 BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) || \
596 (BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_CHROMEOS_DEVICE))
597 #define MAYBE_UnloadedLibrary DISABLED_UnloadedLibrary
599 #define MAYBE_UnloadedLibrary UnloadedLibrary
601 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_UnloadedLibrary) {
602 TestLibraryUnload(true, module_cache());
605 // Checks that a profiler can stop/destruct without ever having started.
606 PROFILER_TEST_F(StackSamplingProfilerTest, StopWithoutStarting) {
607 WithTargetThread(BindLambdaForTesting(
608 [this](SamplingProfilerThreadToken target_thread_token) {
609 SamplingParams params;
610 params.sampling_interval = Milliseconds(0);
611 params.samples_per_profile = 1;
614 WaitableEvent sampling_completed(
615 WaitableEvent::ResetPolicy::MANUAL,
616 WaitableEvent::InitialState::NOT_SIGNALED);
618 StackSamplingProfiler profiler(
619 target_thread_token, params,
620 std::make_unique<TestProfileBuilder>(
622 BindLambdaForTesting(
623 [&profile, &sampling_completed](Profile result_profile) {
624 profile = std::move(result_profile);
625 sampling_completed.Signal();
627 CreateCoreUnwindersFactoryForTesting(module_cache()));
629 profiler.Stop(); // Constructed but never started.
630 EXPECT_FALSE(sampling_completed.IsSignaled());
634 // Checks that its okay to stop a profiler before it finishes even when the
635 // sampling thread continues to run.
636 PROFILER_TEST_F(StackSamplingProfilerTest, StopSafely) {
637 // Test delegate that counts samples.
638 class SampleRecordedCounter : public StackSamplerTestDelegate {
640 SampleRecordedCounter() = default;
642 void OnPreStackWalk() override {
643 AutoLock lock(lock_);
648 AutoLock lock(lock_);
658 BindLambdaForTesting([](SamplingProfilerThreadToken target_thread_token) {
659 SamplingParams params[2];
661 // Providing an initial delay makes it more likely that both will be
662 // scheduled before either starts to run. Once started, samples will
663 // run ordered by their scheduled, interleaved times regardless of
664 // whatever interval the thread wakes up.
665 params[0].initial_delay = Milliseconds(10);
666 params[0].sampling_interval = Milliseconds(1);
667 params[0].samples_per_profile = 100000;
669 params[1].initial_delay = Milliseconds(10);
670 params[1].sampling_interval = Milliseconds(1);
671 params[1].samples_per_profile = 100000;
673 SampleRecordedCounter samples_recorded[std::size(params)];
674 ModuleCache module_cache1, module_cache2;
675 TestProfilerInfo profiler_info0(target_thread_token, params[0],
676 &module_cache1, &samples_recorded[0]);
677 TestProfilerInfo profiler_info1(target_thread_token, params[1],
678 &module_cache2, &samples_recorded[1]);
680 profiler_info0.profiler.Start();
681 profiler_info1.profiler.Start();
683 // Wait for both to start accumulating samples. Using a WaitableEvent is
684 // possible but gets complicated later on because there's no way of
685 // knowing if 0 or 1 additional sample will be taken after Stop() and
686 // thus no way of knowing how many Wait() calls to make on it.
687 while (samples_recorded[0].Get() == 0 || samples_recorded[1].Get() == 0)
688 PlatformThread::Sleep(Milliseconds(1));
690 // Ensure that the first sampler can be safely stopped while the second
691 // continues to run. The stopped first profiler will still have a
692 // RecordSampleTask pending that will do nothing when executed because
693 // the collection will have been removed by Stop().
694 profiler_info0.profiler.Stop();
695 profiler_info0.completed.Wait();
696 size_t count0 = samples_recorded[0].Get();
697 size_t count1 = samples_recorded[1].Get();
699 // Waiting for the second sampler to collect a couple samples ensures
700 // that the pending RecordSampleTask for the first has executed because
701 // tasks are always ordered by their next scheduled time.
702 while (samples_recorded[1].Get() < count1 + 2)
703 PlatformThread::Sleep(Milliseconds(1));
705 // Ensure that the first profiler didn't do anything since it was
707 EXPECT_EQ(count0, samples_recorded[0].Get());
711 // Checks that no sample are captured if the profiling is stopped during the
713 PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInitialDelay) {
714 SamplingParams params;
715 params.initial_delay = Seconds(60);
717 std::vector<std::vector<Frame>> samples =
718 CaptureSamples(params, Milliseconds(0), module_cache());
720 EXPECT_TRUE(samples.empty());
723 // Checks that tasks can be stopped before completion and incomplete samples are
725 PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInterSampleInterval) {
726 // Test delegate that counts samples.
727 class SampleRecordedEvent : public StackSamplerTestDelegate {
729 SampleRecordedEvent()
730 : sample_recorded_(WaitableEvent::ResetPolicy::MANUAL,
731 WaitableEvent::InitialState::NOT_SIGNALED) {}
733 void OnPreStackWalk() override { sample_recorded_.Signal(); }
735 void WaitForSample() { sample_recorded_.Wait(); }
738 WaitableEvent sample_recorded_;
741 WithTargetThread(BindLambdaForTesting(
742 [this](SamplingProfilerThreadToken target_thread_token) {
743 SamplingParams params;
745 params.sampling_interval = AVeryLongTimeDelta();
746 params.samples_per_profile = 2;
748 SampleRecordedEvent samples_recorded;
749 TestProfilerInfo profiler_info(target_thread_token, params,
750 module_cache(), &samples_recorded);
752 profiler_info.profiler.Start();
754 // Wait for profiler to start accumulating samples.
755 samples_recorded.WaitForSample();
757 // Ensure that it can stop safely.
758 profiler_info.profiler.Stop();
759 profiler_info.completed.Wait();
761 EXPECT_EQ(1u, profiler_info.profile.samples.size());
765 PROFILER_TEST_F(StackSamplingProfilerTest, GetNextSampleTime_NormalExecution) {
766 const auto& GetNextSampleTime =
767 StackSamplingProfiler::TestPeer::GetNextSampleTime;
769 const TimeTicks scheduled_current_sample_time = TimeTicks::UnixEpoch();
770 const TimeDelta sampling_interval = Milliseconds(10);
772 // When executing the sample at exactly the scheduled time the next sample
773 // should be one interval later.
774 EXPECT_EQ(scheduled_current_sample_time + sampling_interval,
775 GetNextSampleTime(scheduled_current_sample_time, sampling_interval,
776 scheduled_current_sample_time));
778 // When executing the sample less than half an interval after the scheduled
779 // time the next sample also should be one interval later.
780 EXPECT_EQ(scheduled_current_sample_time + sampling_interval,
782 scheduled_current_sample_time, sampling_interval,
783 scheduled_current_sample_time + 0.4 * sampling_interval));
785 // When executing the sample less than half an interval before the scheduled
786 // time the next sample also should be one interval later. This is not
787 // expected to occur in practice since delayed tasks never run early.
788 EXPECT_EQ(scheduled_current_sample_time + sampling_interval,
790 scheduled_current_sample_time, sampling_interval,
791 scheduled_current_sample_time - 0.4 * sampling_interval));
794 PROFILER_TEST_F(StackSamplingProfilerTest, GetNextSampleTime_DelayedExecution) {
795 const auto& GetNextSampleTime =
796 StackSamplingProfiler::TestPeer::GetNextSampleTime;
798 const TimeTicks scheduled_current_sample_time = TimeTicks::UnixEpoch();
799 const TimeDelta sampling_interval = Milliseconds(10);
801 // When executing the sample between 0.5 and 1.5 intervals after the scheduled
802 // time the next sample should be two intervals later.
803 EXPECT_EQ(scheduled_current_sample_time + 2 * sampling_interval,
805 scheduled_current_sample_time, sampling_interval,
806 scheduled_current_sample_time + 0.6 * sampling_interval));
807 EXPECT_EQ(scheduled_current_sample_time + 2 * sampling_interval,
809 scheduled_current_sample_time, sampling_interval,
810 scheduled_current_sample_time + 1.0 * sampling_interval));
811 EXPECT_EQ(scheduled_current_sample_time + 2 * sampling_interval,
813 scheduled_current_sample_time, sampling_interval,
814 scheduled_current_sample_time + 1.4 * sampling_interval));
816 // Similarly when executing the sample between 9.5 and 10.5 intervals after
817 // the scheduled time the next sample should be 11 intervals later.
818 EXPECT_EQ(scheduled_current_sample_time + 11 * sampling_interval,
820 scheduled_current_sample_time, sampling_interval,
821 scheduled_current_sample_time + 9.6 * sampling_interval));
822 EXPECT_EQ(scheduled_current_sample_time + 11 * sampling_interval,
824 scheduled_current_sample_time, sampling_interval,
825 scheduled_current_sample_time + 10.0 * sampling_interval));
826 EXPECT_EQ(scheduled_current_sample_time + 11 * sampling_interval,
828 scheduled_current_sample_time, sampling_interval,
829 scheduled_current_sample_time + 10.4 * sampling_interval));
832 // Checks that we can destroy the profiler while profiling.
833 PROFILER_TEST_F(StackSamplingProfilerTest, DestroyProfilerWhileProfiling) {
834 SamplingParams params;
835 params.sampling_interval = Milliseconds(10);
838 WithTargetThread(BindLambdaForTesting([&, this](SamplingProfilerThreadToken
839 target_thread_token) {
840 std::unique_ptr<StackSamplingProfiler> profiler;
841 auto profile_builder = std::make_unique<TestProfileBuilder>(
843 BindLambdaForTesting([&profile](Profile result_profile) {
844 profile = std::move(result_profile);
846 profiler = std::make_unique<StackSamplingProfiler>(
847 target_thread_token, params, std::move(profile_builder),
848 CreateCoreUnwindersFactoryForTesting(module_cache()));
852 // Wait longer than a sample interval to catch any use-after-free actions by
853 // the profiler thread.
854 PlatformThread::Sleep(Milliseconds(50));
858 // Checks that the different profilers may be run.
859 PROFILER_TEST_F(StackSamplingProfilerTest, CanRunMultipleProfilers) {
860 SamplingParams params;
861 params.sampling_interval = Milliseconds(0);
862 params.samples_per_profile = 1;
864 std::vector<std::vector<Frame>> samples =
865 CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
866 ASSERT_EQ(1u, samples.size());
868 samples = CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
869 ASSERT_EQ(1u, samples.size());
872 // Checks that a sampler can be started while another is running.
873 PROFILER_TEST_F(StackSamplingProfilerTest, MultipleStart) {
875 BindLambdaForTesting([](SamplingProfilerThreadToken target_thread_token) {
876 SamplingParams params1;
877 params1.initial_delay = AVeryLongTimeDelta();
878 params1.samples_per_profile = 1;
879 ModuleCache module_cache1;
880 TestProfilerInfo profiler_info1(target_thread_token, params1,
883 SamplingParams params2;
884 params2.sampling_interval = Milliseconds(1);
885 params2.samples_per_profile = 1;
886 ModuleCache module_cache2;
887 TestProfilerInfo profiler_info2(target_thread_token, params2,
890 profiler_info1.profiler.Start();
891 profiler_info2.profiler.Start();
892 profiler_info2.completed.Wait();
893 EXPECT_EQ(1u, profiler_info2.profile.samples.size());
897 // Checks that the profile duration and the sampling interval are calculated
898 // correctly. Also checks that RecordMetadata() is invoked each time a sample
900 PROFILER_TEST_F(StackSamplingProfilerTest, ProfileGeneralInfo) {
901 WithTargetThread(BindLambdaForTesting(
902 [this](SamplingProfilerThreadToken target_thread_token) {
903 SamplingParams params;
904 params.sampling_interval = Milliseconds(1);
905 params.samples_per_profile = 3;
907 TestProfilerInfo profiler_info(target_thread_token, params,
910 profiler_info.profiler.Start();
911 profiler_info.completed.Wait();
912 EXPECT_EQ(3u, profiler_info.profile.samples.size());
914 // The profile duration should be greater than the total sampling
916 EXPECT_GT(profiler_info.profile.profile_duration,
917 profiler_info.profile.sampling_period * 3);
919 EXPECT_EQ(Milliseconds(1), profiler_info.profile.sampling_period);
921 // The number of invocations of RecordMetadata() should be equal to the
922 // number of samples recorded.
923 EXPECT_EQ(3, profiler_info.profile.record_metadata_count);
927 // Checks that the sampling thread can shut down.
928 PROFILER_TEST_F(StackSamplingProfilerTest, SamplerIdleShutdown) {
929 SamplingParams params;
930 params.sampling_interval = Milliseconds(0);
931 params.samples_per_profile = 1;
933 std::vector<std::vector<Frame>> samples =
934 CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
935 ASSERT_EQ(1u, samples.size());
937 // Capture thread should still be running at this point.
938 ASSERT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
940 // Initiate an "idle" shutdown and ensure it happens. Idle-shutdown was
941 // disabled by the test fixture so the test will fail due to a timeout if
943 StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(false);
945 // While the shutdown has been initiated, the actual exit of the thread still
946 // happens asynchronously. Watch until the thread actually exits. This test
947 // will time-out in the case of failure.
948 while (StackSamplingProfiler::TestPeer::IsSamplingThreadRunning())
949 PlatformThread::Sleep(Milliseconds(1));
952 // Checks that additional requests will restart a stopped profiler.
953 PROFILER_TEST_F(StackSamplingProfilerTest,
954 WillRestartSamplerAfterIdleShutdown) {
955 SamplingParams params;
956 params.sampling_interval = Milliseconds(0);
957 params.samples_per_profile = 1;
959 std::vector<std::vector<Frame>> samples =
960 CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
961 ASSERT_EQ(1u, samples.size());
963 // Capture thread should still be running at this point.
964 ASSERT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
966 // Post a ShutdownTask on the sampling thread which, when executed, will
967 // mark the thread as EXITING and begin shut down of the thread.
968 StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(false);
970 // Ensure another capture will start the sampling thread and run.
971 samples = CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
972 ASSERT_EQ(1u, samples.size());
973 EXPECT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
976 // Checks that it's safe to stop a task after it's completed and the sampling
977 // thread has shut-down for being idle.
978 PROFILER_TEST_F(StackSamplingProfilerTest, StopAfterIdleShutdown) {
979 WithTargetThread(BindLambdaForTesting(
980 [this](SamplingProfilerThreadToken target_thread_token) {
981 SamplingParams params;
983 params.sampling_interval = Milliseconds(1);
984 params.samples_per_profile = 1;
986 TestProfilerInfo profiler_info(target_thread_token, params,
989 profiler_info.profiler.Start();
990 profiler_info.completed.Wait();
992 // Capture thread should still be running at this point.
993 ASSERT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
995 // Perform an idle shutdown.
996 StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(
999 // Stop should be safe though its impossible to know at this moment if
1000 // the sampling thread has completely exited or will just "stop soon".
1001 profiler_info.profiler.Stop();
1005 // Checks that profilers can run both before and after the sampling thread has
1007 PROFILER_TEST_F(StackSamplingProfilerTest,
1008 ProfileBeforeAndAfterSamplingThreadRunning) {
1010 BindLambdaForTesting([](SamplingProfilerThreadToken target_thread_token) {
1011 ModuleCache module_cache1;
1012 ModuleCache module_cache2;
1014 std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos;
1015 profiler_infos.push_back(std::make_unique<TestProfilerInfo>(
1016 target_thread_token,
1017 SamplingParams{/*initial_delay=*/AVeryLongTimeDelta(),
1018 /*samples_per_profile=*/1,
1019 /*sampling_interval=*/Milliseconds(1)},
1021 profiler_infos.push_back(std::make_unique<TestProfilerInfo>(
1022 target_thread_token,
1023 SamplingParams{/*initial_delay=*/Milliseconds(0),
1024 /*samples_per_profile=*/1,
1025 /*sampling_interval=*/Milliseconds(1)},
1028 // First profiler is started when there has never been a sampling
1031 StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
1032 profiler_infos[0]->profiler.Start();
1033 // Second profiler is started when sampling thread is already running.
1034 EXPECT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
1035 profiler_infos[1]->profiler.Start();
1037 // Only the second profiler should finish before test times out.
1038 size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
1039 EXPECT_EQ(1U, completed_profiler);
1043 // Checks that an idle-shutdown task will abort if a new profiler starts
1044 // between when it was posted and when it runs.
1045 PROFILER_TEST_F(StackSamplingProfilerTest, IdleShutdownAbort) {
1046 WithTargetThread(BindLambdaForTesting(
1047 [this](SamplingProfilerThreadToken target_thread_token) {
1048 SamplingParams params;
1050 params.sampling_interval = Milliseconds(1);
1051 params.samples_per_profile = 1;
1053 TestProfilerInfo profiler_info(target_thread_token, params,
1056 profiler_info.profiler.Start();
1057 profiler_info.completed.Wait();
1058 EXPECT_EQ(1u, profiler_info.profile.samples.size());
1060 // Perform an idle shutdown but simulate that a new capture is started
1061 // before it can actually run.
1062 StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(
1065 // Though the shutdown-task has been executed, any actual exit of the
1066 // thread is asynchronous so there is no way to detect that *didn't*
1067 // exit except to wait a reasonable amount of time and then check. Since
1068 // the thread was just running ("perform" blocked until it was), it
1069 // should finish almost immediately and without any waiting for tasks or
1071 PlatformThread::Sleep(Milliseconds(200));
1072 EXPECT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
1074 // Ensure that it's still possible to run another sampler.
1075 TestProfilerInfo another_info(target_thread_token, params,
1077 another_info.profiler.Start();
1078 another_info.completed.Wait();
1079 EXPECT_EQ(1u, another_info.profile.samples.size());
1083 // Checks that synchronized multiple sampling requests execute in parallel.
1084 PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_InSync) {
1086 BindLambdaForTesting([](SamplingProfilerThreadToken target_thread_token) {
1087 std::vector<ModuleCache> module_caches(2);
1089 // Providing an initial delay makes it more likely that both will be
1090 // scheduled before either starts to run. Once started, samples will
1091 // run ordered by their scheduled, interleaved times regardless of
1092 // whatever interval the thread wakes up. Thus, total execution time
1093 // will be 10ms (delay) + 10x1ms (sampling) + 1/2 timer minimum
1095 std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos;
1096 profiler_infos.push_back(std::make_unique<TestProfilerInfo>(
1097 target_thread_token,
1098 SamplingParams{/*initial_delay=*/Milliseconds(10),
1099 /*samples_per_profile=*/9,
1100 /*sampling_interval=*/Milliseconds(1)},
1101 &module_caches[0]));
1102 profiler_infos.push_back(std::make_unique<TestProfilerInfo>(
1103 target_thread_token,
1104 SamplingParams{/*initial_delay=*/Milliseconds(11),
1105 /*samples_per_profile=*/8,
1106 /*sampling_interval=*/Milliseconds(1)},
1107 &module_caches[1]));
1109 profiler_infos[0]->profiler.Start();
1110 profiler_infos[1]->profiler.Start();
1112 // Wait for one profiler to finish.
1113 size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
1115 size_t other_profiler = 1 - completed_profiler;
1116 // Wait for the other profiler to finish.
1117 profiler_infos[other_profiler]->completed.Wait();
1119 // Ensure each got the correct number of samples.
1120 EXPECT_EQ(9u, profiler_infos[0]->profile.samples.size());
1121 EXPECT_EQ(8u, profiler_infos[1]->profile.samples.size());
1125 // Checks that several mixed sampling requests execute in parallel.
1126 PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_Mixed) {
1127 WithTargetThread(BindLambdaForTesting([](SamplingProfilerThreadToken
1128 target_thread_token) {
1129 std::vector<ModuleCache> module_caches(3);
1131 std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos;
1132 profiler_infos.push_back(std::make_unique<TestProfilerInfo>(
1133 target_thread_token,
1134 SamplingParams{/*initial_delay=*/Milliseconds(8),
1135 /*samples_per_profile=*/10,
1136 /*sampling_interval=*/Milliseconds(4)},
1137 &module_caches[0]));
1138 profiler_infos.push_back(std::make_unique<TestProfilerInfo>(
1139 target_thread_token,
1140 SamplingParams{/*initial_delay=*/Milliseconds(9),
1141 /*samples_per_profile=*/10,
1142 /*sampling_interval=*/Milliseconds(3)},
1143 &module_caches[1]));
1144 profiler_infos.push_back(std::make_unique<TestProfilerInfo>(
1145 target_thread_token,
1146 SamplingParams{/*initial_delay=*/Milliseconds(10),
1147 /*samples_per_profile=*/10,
1148 /*sampling_interval=*/Milliseconds(2)},
1149 &module_caches[2]));
1151 for (auto& i : profiler_infos)
1152 i->profiler.Start();
1154 // Wait for one profiler to finish.
1155 size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
1156 EXPECT_EQ(10u, profiler_infos[completed_profiler]->profile.samples.size());
1157 // Stop and destroy all profilers, always in the same order. Don't
1159 for (auto& i : profiler_infos)
1161 for (auto& i : profiler_infos)
1166 // Checks that different threads can be sampled in parallel.
1167 PROFILER_TEST_F(StackSamplingProfilerTest, MultipleSampledThreads) {
1168 UnwindScenario scenario1(BindRepeating(&CallWithPlainFunction));
1169 UnwindScenario::SampleEvents events1;
1170 TargetThread target_thread1(
1171 BindLambdaForTesting([&]() { scenario1.Execute(&events1); }));
1172 target_thread1.Start();
1173 events1.ready_for_sample.Wait();
1175 UnwindScenario scenario2(BindRepeating(&CallWithPlainFunction));
1176 UnwindScenario::SampleEvents events2;
1177 TargetThread target_thread2(
1178 BindLambdaForTesting([&]() { scenario2.Execute(&events2); }));
1179 target_thread2.Start();
1180 events2.ready_for_sample.Wait();
1182 // Providing an initial delay makes it more likely that both will be
1183 // scheduled before either starts to run. Once started, samples will
1184 // run ordered by their scheduled, interleaved times regardless of
1185 // whatever interval the thread wakes up.
1186 SamplingParams params1, params2;
1187 params1.initial_delay = Milliseconds(10);
1188 params1.sampling_interval = Milliseconds(1);
1189 params1.samples_per_profile = 9;
1190 params2.initial_delay = Milliseconds(10);
1191 params2.sampling_interval = Milliseconds(1);
1192 params2.samples_per_profile = 8;
1194 Profile profile1, profile2;
1195 ModuleCache module_cache1, module_cache2;
1197 WaitableEvent sampling_thread_completed1(
1198 WaitableEvent::ResetPolicy::MANUAL,
1199 WaitableEvent::InitialState::NOT_SIGNALED);
1200 StackSamplingProfiler profiler1(
1201 target_thread1.thread_token(), params1,
1202 std::make_unique<TestProfileBuilder>(
1204 BindLambdaForTesting(
1205 [&profile1, &sampling_thread_completed1](Profile result_profile) {
1206 profile1 = std::move(result_profile);
1207 sampling_thread_completed1.Signal();
1209 CreateCoreUnwindersFactoryForTesting(&module_cache1));
1211 WaitableEvent sampling_thread_completed2(
1212 WaitableEvent::ResetPolicy::MANUAL,
1213 WaitableEvent::InitialState::NOT_SIGNALED);
1214 StackSamplingProfiler profiler2(
1215 target_thread2.thread_token(), params2,
1216 std::make_unique<TestProfileBuilder>(
1218 BindLambdaForTesting(
1219 [&profile2, &sampling_thread_completed2](Profile result_profile) {
1220 profile2 = std::move(result_profile);
1221 sampling_thread_completed2.Signal();
1223 CreateCoreUnwindersFactoryForTesting(&module_cache2));
1225 // Finally the real work.
1228 sampling_thread_completed1.Wait();
1229 sampling_thread_completed2.Wait();
1230 EXPECT_EQ(9u, profile1.samples.size());
1231 EXPECT_EQ(8u, profile2.samples.size());
1233 events1.sample_finished.Signal();
1234 events2.sample_finished.Signal();
1235 target_thread1.Join();
1236 target_thread2.Join();
1239 // A simple thread that runs a profiler on another thread.
1240 class ProfilerThread : public SimpleThread {
1242 ProfilerThread(const std::string& name,
1243 SamplingProfilerThreadToken thread_token,
1244 const SamplingParams& params,
1245 ModuleCache* module_cache)
1246 : SimpleThread(name, Options()),
1247 run_(WaitableEvent::ResetPolicy::MANUAL,
1248 WaitableEvent::InitialState::NOT_SIGNALED),
1249 completed_(WaitableEvent::ResetPolicy::MANUAL,
1250 WaitableEvent::InitialState::NOT_SIGNALED),
1251 profiler_(thread_token,
1253 std::make_unique<TestProfileBuilder>(
1255 BindLambdaForTesting([this](Profile result_profile) {
1256 profile_ = std::move(result_profile);
1257 completed_.Signal();
1259 CreateCoreUnwindersFactoryForTesting(module_cache)) {}
1260 void Run() override {
1265 void Go() { run_.Signal(); }
1267 void Wait() { completed_.Wait(); }
1269 Profile& profile() { return profile_; }
1275 WaitableEvent completed_;
1276 StackSamplingProfiler profiler_;
1279 // Checks that different threads can run samplers in parallel.
1280 PROFILER_TEST_F(StackSamplingProfilerTest, MultipleProfilerThreads) {
1282 BindLambdaForTesting([](SamplingProfilerThreadToken target_thread_token) {
1283 // Providing an initial delay makes it more likely that both will be
1284 // scheduled before either starts to run. Once started, samples will
1285 // run ordered by their scheduled, interleaved times regardless of
1286 // whatever interval the thread wakes up.
1287 SamplingParams params1, params2;
1288 params1.initial_delay = Milliseconds(10);
1289 params1.sampling_interval = Milliseconds(1);
1290 params1.samples_per_profile = 9;
1291 params2.initial_delay = Milliseconds(10);
1292 params2.sampling_interval = Milliseconds(1);
1293 params2.samples_per_profile = 8;
1295 // Start the profiler threads and give them a moment to get going.
1296 ModuleCache module_cache1;
1297 ProfilerThread profiler_thread1("profiler1", target_thread_token,
1298 params1, &module_cache1);
1299 ModuleCache module_cache2;
1300 ProfilerThread profiler_thread2("profiler2", target_thread_token,
1301 params2, &module_cache2);
1302 profiler_thread1.Start();
1303 profiler_thread2.Start();
1304 PlatformThread::Sleep(Milliseconds(10));
1306 // This will (approximately) synchronize the two threads.
1307 profiler_thread1.Go();
1308 profiler_thread2.Go();
1310 // Wait for them both to finish and validate collection.
1311 profiler_thread1.Wait();
1312 profiler_thread2.Wait();
1313 EXPECT_EQ(9u, profiler_thread1.profile().samples.size());
1314 EXPECT_EQ(8u, profiler_thread2.profile().samples.size());
1316 profiler_thread1.Join();
1317 profiler_thread2.Join();
1321 PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_BeforeStart) {
1322 SamplingParams params;
1323 params.sampling_interval = Milliseconds(0);
1324 params.samples_per_profile = 1;
1326 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1328 int add_initial_modules_invocation_count = 0;
1329 const auto add_initial_modules_callback =
1330 [&add_initial_modules_invocation_count]() {
1331 ++add_initial_modules_invocation_count;
1337 BindLambdaForTesting(
1338 [&](SamplingProfilerThreadToken target_thread_token) {
1339 WaitableEvent sampling_thread_completed(
1340 WaitableEvent::ResetPolicy::MANUAL,
1341 WaitableEvent::InitialState::NOT_SIGNALED);
1342 StackSamplingProfiler profiler(
1343 target_thread_token, params,
1344 std::make_unique<TestProfileBuilder>(
1346 BindLambdaForTesting([&profile, &sampling_thread_completed](
1347 Profile result_profile) {
1348 profile = std::move(result_profile);
1349 sampling_thread_completed.Signal();
1351 CreateCoreUnwindersFactoryForTesting(module_cache()));
1352 profiler.AddAuxUnwinder(std::make_unique<TestAuxUnwinder>(
1354 BindLambdaForTesting(add_initial_modules_callback)));
1356 sampling_thread_completed.Wait();
1359 ASSERT_EQ(1, add_initial_modules_invocation_count);
1361 // The sample should have one frame from the context values and one from the
1363 ASSERT_EQ(1u, profile.samples.size());
1364 const std::vector<Frame>& frames = profile.samples[0];
1366 ASSERT_EQ(2u, frames.size());
1367 EXPECT_EQ(23u, frames[1].instruction_pointer);
1368 EXPECT_EQ(nullptr, frames[1].module);
1371 PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_AfterStart) {
1372 SamplingParams params;
1373 params.sampling_interval = Milliseconds(10);
1374 params.samples_per_profile = 2;
1376 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1378 int add_initial_modules_invocation_count = 0;
1379 const auto add_initial_modules_callback =
1380 [&add_initial_modules_invocation_count]() {
1381 ++add_initial_modules_invocation_count;
1387 BindLambdaForTesting(
1388 [&](SamplingProfilerThreadToken target_thread_token) {
1389 WaitableEvent sampling_thread_completed(
1390 WaitableEvent::ResetPolicy::MANUAL,
1391 WaitableEvent::InitialState::NOT_SIGNALED);
1392 StackSamplingProfiler profiler(
1393 target_thread_token, params,
1394 std::make_unique<TestProfileBuilder>(
1396 BindLambdaForTesting([&profile, &sampling_thread_completed](
1397 Profile result_profile) {
1398 profile = std::move(result_profile);
1399 sampling_thread_completed.Signal();
1401 CreateCoreUnwindersFactoryForTesting(module_cache()));
1403 profiler.AddAuxUnwinder(std::make_unique<TestAuxUnwinder>(
1405 BindLambdaForTesting(add_initial_modules_callback)));
1406 sampling_thread_completed.Wait();
1409 ASSERT_EQ(1, add_initial_modules_invocation_count);
1411 // The sample should have one frame from the context values and one from the
1413 ASSERT_EQ(2u, profile.samples.size());
1415 // Whether the aux unwinder is available for the first sample is racy, so rely
1416 // on the second sample.
1417 const std::vector<Frame>& frames = profile.samples[1];
1418 ASSERT_EQ(2u, frames.size());
1419 EXPECT_EQ(23u, frames[1].instruction_pointer);
1420 EXPECT_EQ(nullptr, frames[1].module);
1423 PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_AfterStop) {
1424 SamplingParams params;
1425 params.sampling_interval = Milliseconds(0);
1426 params.samples_per_profile = 1;
1428 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1433 BindLambdaForTesting(
1434 [&](SamplingProfilerThreadToken target_thread_token) {
1435 WaitableEvent sampling_thread_completed(
1436 WaitableEvent::ResetPolicy::MANUAL,
1437 WaitableEvent::InitialState::NOT_SIGNALED);
1438 StackSamplingProfiler profiler(
1439 target_thread_token, params,
1440 std::make_unique<TestProfileBuilder>(
1442 BindLambdaForTesting([&profile, &sampling_thread_completed](
1443 Profile result_profile) {
1444 profile = std::move(result_profile);
1445 sampling_thread_completed.Signal();
1447 CreateCoreUnwindersFactoryForTesting(module_cache()));
1450 profiler.AddAuxUnwinder(std::make_unique<TestAuxUnwinder>(
1451 Frame(23, nullptr), base::RepeatingClosure()));
1452 sampling_thread_completed.Wait();
1455 // The AuxUnwinder should be accepted without error. It will have no effect
1456 // since the collection has stopped.
1459 // Checks that requests to apply metadata to past samples are passed on to the
1461 PROFILER_TEST_F(StackSamplingProfilerTest,
1462 ApplyMetadataToPastSamples_PassedToProfileBuilder) {
1463 // Runs the passed closure on the profiler thread after a sample is taken.
1464 class PostSampleInvoker : public StackSamplerTestDelegate {
1466 explicit PostSampleInvoker(RepeatingClosure post_sample_closure)
1467 : post_sample_closure_(std::move(post_sample_closure)) {}
1469 void OnPreStackWalk() override { post_sample_closure_.Run(); }
1472 RepeatingClosure post_sample_closure_;
1475 // Thread-safe representation of the times that samples were taken.
1476 class SynchronizedSampleTimes {
1479 AutoLock lock(lock_);
1480 times_.push_back(TimeTicks::Now());
1483 std::vector<TimeTicks> GetTimes() {
1484 AutoLock lock(lock_);
1490 std::vector<TimeTicks> times_;
1493 SamplingParams params;
1494 params.sampling_interval = Milliseconds(10);
1495 // 10,000 samples ensures the profiler continues running until manually
1496 // stopped, after applying metadata.
1497 params.samples_per_profile = 10000;
1499 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1501 std::vector<TimeTicks> sample_times;
1505 BindLambdaForTesting(
1506 [&](SamplingProfilerThreadToken target_thread_token) {
1507 SynchronizedSampleTimes synchronized_sample_times;
1508 WaitableEvent sample_seen(WaitableEvent::ResetPolicy::AUTOMATIC);
1509 PostSampleInvoker post_sample_invoker(BindLambdaForTesting([&]() {
1510 synchronized_sample_times.AddNow();
1511 sample_seen.Signal();
1514 StackSamplingProfiler profiler(
1515 target_thread_token, params,
1516 std::make_unique<TestProfileBuilder>(
1518 BindLambdaForTesting([&profile](Profile result_profile) {
1519 profile = std::move(result_profile);
1521 CreateCoreUnwindersFactoryForTesting(module_cache()),
1522 RepeatingClosure(), &post_sample_invoker);
1524 // Wait for 5 samples to be collected.
1525 for (int i = 0; i < 5; ++i)
1527 sample_times = synchronized_sample_times.GetTimes();
1528 // Record metadata on past samples, with and without a key value.
1529 // The range [times[1], times[3]] is guaranteed to include only
1530 // samples 2 and 3, and likewise [times[2], times[4]] is guaranteed
1531 // to include only samples 3 and 4.
1532 ApplyMetadataToPastSamples(sample_times[1], sample_times[3],
1533 "TestMetadata1", 10,
1534 base::SampleMetadataScope::kProcess);
1535 ApplyMetadataToPastSamples(sample_times[2], sample_times[4],
1536 "TestMetadata2", 100, 11,
1537 base::SampleMetadataScope::kProcess);
1541 ASSERT_EQ(2u, profile.retrospective_metadata.size());
1543 const RetrospectiveMetadata& metadata1 = profile.retrospective_metadata[0];
1544 EXPECT_EQ(sample_times[1], metadata1.period_start);
1545 EXPECT_EQ(sample_times[3], metadata1.period_end);
1546 EXPECT_EQ(HashMetricName("TestMetadata1"), metadata1.item.name_hash);
1547 EXPECT_FALSE(metadata1.item.key.has_value());
1548 EXPECT_EQ(10, metadata1.item.value);
1550 const RetrospectiveMetadata& metadata2 = profile.retrospective_metadata[1];
1551 EXPECT_EQ(sample_times[2], metadata2.period_start);
1552 EXPECT_EQ(sample_times[4], metadata2.period_end);
1553 EXPECT_EQ(HashMetricName("TestMetadata2"), metadata2.item.name_hash);
1554 ASSERT_TRUE(metadata2.item.key.has_value());
1555 EXPECT_EQ(100, *metadata2.item.key);
1556 EXPECT_EQ(11, metadata2.item.value);
1560 StackSamplingProfilerTest,
1561 ApplyMetadataToPastSamples_PassedToProfileBuilder_MultipleCollections) {
1562 SamplingParams params;
1563 params.sampling_interval = Milliseconds(10);
1564 // 10,000 samples ensures the profiler continues running until manually
1565 // stopped, after applying metadata.
1566 params.samples_per_profile = 10000;
1567 ModuleCache module_cache1, module_cache2;
1569 WaitableEvent profiler1_started;
1570 WaitableEvent profiler2_started;
1571 WaitableEvent profiler1_metadata_applied;
1572 WaitableEvent profiler2_metadata_applied;
1575 WaitableEvent sampling_completed1;
1576 TargetThread target_thread1(BindLambdaForTesting([&]() {
1577 StackSamplingProfiler profiler1(
1578 target_thread1.thread_token(), params,
1579 std::make_unique<TestProfileBuilder>(
1580 &module_cache1, BindLambdaForTesting([&](Profile result_profile) {
1581 profile1 = std::move(result_profile);
1582 sampling_completed1.Signal();
1584 CreateCoreUnwindersFactoryForTesting(&module_cache1),
1585 RepeatingClosure());
1587 profiler1_started.Signal();
1588 profiler2_started.Wait();
1590 // Record metadata on past samples only for this thread. The time range
1591 // shouldn't affect the outcome, it should always be passed to the
1593 ApplyMetadataToPastSamples(TimeTicks(), TimeTicks::Now(), "TestMetadata1",
1594 10, 10, SampleMetadataScope::kThread);
1596 profiler1_metadata_applied.Signal();
1597 profiler2_metadata_applied.Wait();
1600 target_thread1.Start();
1603 WaitableEvent sampling_completed2;
1604 TargetThread target_thread2(BindLambdaForTesting([&]() {
1605 StackSamplingProfiler profiler2(
1606 target_thread2.thread_token(), params,
1607 std::make_unique<TestProfileBuilder>(
1608 &module_cache2, BindLambdaForTesting([&](Profile result_profile) {
1609 profile2 = std::move(result_profile);
1610 sampling_completed2.Signal();
1612 CreateCoreUnwindersFactoryForTesting(&module_cache2),
1613 RepeatingClosure());
1615 profiler2_started.Signal();
1616 profiler1_started.Wait();
1618 // Record metadata on past samples only for this thread.
1619 ApplyMetadataToPastSamples(TimeTicks(), TimeTicks::Now(), "TestMetadata2",
1620 20, 20, SampleMetadataScope::kThread);
1622 profiler2_metadata_applied.Signal();
1623 profiler1_metadata_applied.Wait();
1626 target_thread2.Start();
1628 target_thread1.Join();
1629 target_thread2.Join();
1631 // Wait for the profile to be captured before checking expectations.
1632 sampling_completed1.Wait();
1633 sampling_completed2.Wait();
1635 ASSERT_EQ(1u, profile1.retrospective_metadata.size());
1636 ASSERT_EQ(1u, profile2.retrospective_metadata.size());
1639 const RetrospectiveMetadata& metadata1 = profile1.retrospective_metadata[0];
1640 EXPECT_EQ(HashMetricName("TestMetadata1"), metadata1.item.name_hash);
1641 ASSERT_TRUE(metadata1.item.key.has_value());
1642 EXPECT_EQ(10, *metadata1.item.key);
1643 EXPECT_EQ(10, metadata1.item.value);
1646 const RetrospectiveMetadata& metadata2 = profile2.retrospective_metadata[0];
1647 EXPECT_EQ(HashMetricName("TestMetadata2"), metadata2.item.name_hash);
1648 ASSERT_TRUE(metadata2.item.key.has_value());
1649 EXPECT_EQ(20, *metadata2.item.key);
1650 EXPECT_EQ(20, metadata2.item.value);
1654 // Checks that requests to add profile metadata are passed on to the profile
1656 PROFILER_TEST_F(StackSamplingProfilerTest,
1657 AddProfileMetadata_PassedToProfileBuilder) {
1658 // Runs the passed closure on the profiler thread after a sample is taken.
1659 class PostSampleInvoker : public StackSamplerTestDelegate {
1661 explicit PostSampleInvoker(RepeatingClosure post_sample_closure)
1662 : post_sample_closure_(std::move(post_sample_closure)) {}
1664 void OnPreStackWalk() override { post_sample_closure_.Run(); }
1667 RepeatingClosure post_sample_closure_;
1670 SamplingParams params;
1671 params.sampling_interval = Milliseconds(10);
1672 // 10,000 samples ensures the profiler continues running until manually
1674 params.samples_per_profile = 10000;
1676 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1681 BindLambdaForTesting(
1682 [&](SamplingProfilerThreadToken target_thread_token) {
1683 WaitableEvent sample_seen(WaitableEvent::ResetPolicy::AUTOMATIC);
1684 PostSampleInvoker post_sample_invoker(
1685 BindLambdaForTesting([&]() { sample_seen.Signal(); }));
1687 StackSamplingProfiler profiler(
1688 target_thread_token, params,
1689 std::make_unique<TestProfileBuilder>(
1691 BindLambdaForTesting([&profile](Profile result_profile) {
1692 profile = std::move(result_profile);
1694 CreateCoreUnwindersFactoryForTesting(module_cache()),
1695 RepeatingClosure(), &post_sample_invoker);
1698 AddProfileMetadata("TestMetadata", 1, 2,
1699 SampleMetadataScope::kProcess);
1703 ASSERT_EQ(1u, profile.profile_metadata.size());
1704 const MetadataRecorder::Item& item = profile.profile_metadata[0];
1705 EXPECT_EQ(HashMetricName("TestMetadata"), item.name_hash);
1706 EXPECT_EQ(1, *item.key);
1707 EXPECT_EQ(2, item.value);
1710 PROFILER_TEST_F(StackSamplingProfilerTest,
1711 AddProfileMetadata_PassedToProfileBuilder_MultipleCollections) {
1712 SamplingParams params;
1713 params.sampling_interval = Milliseconds(10);
1714 // 10,000 samples ensures the profiler continues running until manually
1716 params.samples_per_profile = 10000;
1717 ModuleCache module_cache1, module_cache2;
1719 WaitableEvent profiler1_started;
1720 WaitableEvent profiler2_started;
1721 WaitableEvent profiler1_metadata_applied;
1722 WaitableEvent profiler2_metadata_applied;
1725 WaitableEvent sampling_completed1;
1726 TargetThread target_thread1(BindLambdaForTesting([&]() {
1727 StackSamplingProfiler profiler1(
1728 target_thread1.thread_token(), params,
1729 std::make_unique<TestProfileBuilder>(
1730 &module_cache1, BindLambdaForTesting([&](Profile result_profile) {
1731 profile1 = std::move(result_profile);
1732 sampling_completed1.Signal();
1734 CreateCoreUnwindersFactoryForTesting(&module_cache1),
1735 RepeatingClosure());
1737 profiler1_started.Signal();
1738 profiler2_started.Wait();
1740 AddProfileMetadata("TestMetadata1", 1, 2, SampleMetadataScope::kThread);
1742 profiler1_metadata_applied.Signal();
1743 profiler2_metadata_applied.Wait();
1746 target_thread1.Start();
1749 WaitableEvent sampling_completed2;
1750 TargetThread target_thread2(BindLambdaForTesting([&]() {
1751 StackSamplingProfiler profiler2(
1752 target_thread2.thread_token(), params,
1753 std::make_unique<TestProfileBuilder>(
1754 &module_cache2, BindLambdaForTesting([&](Profile result_profile) {
1755 profile2 = std::move(result_profile);
1756 sampling_completed2.Signal();
1758 CreateCoreUnwindersFactoryForTesting(&module_cache2),
1759 RepeatingClosure());
1761 profiler2_started.Signal();
1762 profiler1_started.Wait();
1764 AddProfileMetadata("TestMetadata2", 11, 12, SampleMetadataScope::kThread);
1766 profiler2_metadata_applied.Signal();
1767 profiler1_metadata_applied.Wait();
1770 target_thread2.Start();
1772 target_thread1.Join();
1773 target_thread2.Join();
1775 // Wait for the profile to be captured before checking expectations.
1776 sampling_completed1.Wait();
1777 sampling_completed2.Wait();
1779 ASSERT_EQ(1u, profile1.profile_metadata.size());
1780 ASSERT_EQ(1u, profile2.profile_metadata.size());
1783 const MetadataRecorder::Item& item = profile1.profile_metadata[0];
1784 EXPECT_EQ(HashMetricName("TestMetadata1"), item.name_hash);
1785 ASSERT_TRUE(item.key.has_value());
1786 EXPECT_EQ(1, *item.key);
1787 EXPECT_EQ(2, item.value);
1790 const MetadataRecorder::Item& item = profile2.profile_metadata[0];
1791 EXPECT_EQ(HashMetricName("TestMetadata2"), item.name_hash);
1792 ASSERT_TRUE(item.key.has_value());
1793 EXPECT_EQ(11, *item.key);
1794 EXPECT_EQ(12, item.value);