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
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6 #include <stdint.h>
7
8 #include <cstdlib>
9 #include <memory>
10 #include <set>
11 #include <utility>
12 #include <vector>
13
14 #include "base/bind.h"
15 #include "base/callback.h"
16 #include "base/compiler_specific.h"
17 #include "base/files/file_util.h"
18 #include "base/location.h"
19 #include "base/macros.h"
20 #include "base/memory/ptr_util.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/stl_util.h"
32 #include "base/strings/utf_string_conversions.h"
33 #include "base/synchronization/lock.h"
34 #include "base/synchronization/waitable_event.h"
35 #include "base/test/bind.h"
36 #include "base/threading/simple_thread.h"
37 #include "base/time/time.h"
38 #include "build/build_config.h"
39 #include "testing/gtest/include/gtest/gtest.h"
40
41 #if defined(OS_WIN)
42 #include <intrin.h>
43 #include <malloc.h>
44 #include <windows.h>
45 #elif !defined(OS_BSD)
46 #include <alloca.h>
47 #endif
48
49 // STACK_SAMPLING_PROFILER_SUPPORTED is used to conditionally enable the tests
50 // below for supported platforms (currently Win x64 and Mac x64).
51 #if (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) || \
52 (defined(OS_MAC) && defined(ARCH_CPU_X86_64)) || \
53 (defined(OS_ANDROID) && BUILDFLAG(ENABLE_ARM_CFI_TABLE))
54 #define STACK_SAMPLING_PROFILER_SUPPORTED 1
55 #endif
56
57 namespace base {
58
59 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
60 #define PROFILER_TEST_F(TestClass, TestName) TEST_F(TestClass, TestName)
61 #else
62 #define PROFILER_TEST_F(TestClass, TestName) \
63 TEST_F(TestClass, DISABLED_##TestName)
64 #endif
65
66 using SamplingParams = StackSamplingProfiler::SamplingParams;
67
68 namespace {
69
70 // State provided to the ProfileBuilder's ApplyMetadataRetrospectively function.
71 struct RetrospectiveMetadata {
72 TimeTicks period_start;
73 TimeTicks period_end;
74 MetadataRecorder::Item item;
75 };
76
77 // Profile consists of a set of samples and other sampling information.
78 struct Profile {
79 // The collected samples.
80 std::vector<std::vector<Frame>> samples;
81
82 // The number of invocations of RecordMetadata().
83 int record_metadata_count;
84
85 // The retrospective metadata requests.
86 std::vector<RetrospectiveMetadata> retrospective_metadata;
87
88 // Duration of this profile.
89 TimeDelta profile_duration;
90
91 // Time between samples.
92 TimeDelta sampling_period;
93 };
94
95 // The callback type used to collect a profile. The passed Profile is move-only.
96 // Other threads, including the UI thread, may block on callback completion so
97 // this should run as quickly as possible.
98 using ProfileCompletedCallback = OnceCallback<void(Profile)>;
99
100 // TestProfileBuilder collects samples produced by the profiler.
101 class TestProfileBuilder : public ProfileBuilder {
102 public:
103 TestProfileBuilder(ModuleCache* module_cache,
104 ProfileCompletedCallback callback);
105
106 ~TestProfileBuilder() override;
107
108 // ProfileBuilder:
109 ModuleCache* GetModuleCache() override;
110 void RecordMetadata(
111 const MetadataRecorder::MetadataProvider& metadata_provider) override;
112 void ApplyMetadataRetrospectively(
113 TimeTicks period_start,
114 TimeTicks period_end,
115 const MetadataRecorder::Item& item) override;
116 void OnSampleCompleted(std::vector<Frame> sample,
117 TimeTicks sample_timestamp) override;
118 void OnProfileCompleted(TimeDelta profile_duration,
119 TimeDelta sampling_period) override;
120
121 private:
122 ModuleCache* module_cache_;
123
124 // The set of recorded samples.
125 std::vector<std::vector<Frame>> samples_;
126
127 // The number of invocations of RecordMetadata().
128 int record_metadata_count_ = 0;
129
130 // The retrospective metadata requests.
131 std::vector<RetrospectiveMetadata> retrospective_metadata_;
132
133 // Callback made when sampling a profile completes.
134 ProfileCompletedCallback callback_;
135
136 DISALLOW_COPY_AND_ASSIGN(TestProfileBuilder);
137 };
138
TestProfileBuilder(ModuleCache * module_cache,ProfileCompletedCallback callback)139 TestProfileBuilder::TestProfileBuilder(ModuleCache* module_cache,
140 ProfileCompletedCallback callback)
141 : module_cache_(module_cache), callback_(std::move(callback)) {}
142
143 TestProfileBuilder::~TestProfileBuilder() = default;
144
GetModuleCache()145 ModuleCache* TestProfileBuilder::GetModuleCache() {
146 return module_cache_;
147 }
148
RecordMetadata(const MetadataRecorder::MetadataProvider & metadata_provider)149 void TestProfileBuilder::RecordMetadata(
150 const MetadataRecorder::MetadataProvider& metadata_provider) {
151 ++record_metadata_count_;
152 }
153
ApplyMetadataRetrospectively(TimeTicks period_start,TimeTicks period_end,const MetadataRecorder::Item & item)154 void TestProfileBuilder::ApplyMetadataRetrospectively(
155 TimeTicks period_start,
156 TimeTicks period_end,
157 const MetadataRecorder::Item& item) {
158 retrospective_metadata_.push_back(
159 RetrospectiveMetadata{period_start, period_end, item});
160 }
161
OnSampleCompleted(std::vector<Frame> sample,TimeTicks sample_timestamp)162 void TestProfileBuilder::OnSampleCompleted(std::vector<Frame> sample,
163 TimeTicks sample_timestamp) {
164 samples_.push_back(std::move(sample));
165 }
166
OnProfileCompleted(TimeDelta profile_duration,TimeDelta sampling_period)167 void TestProfileBuilder::OnProfileCompleted(TimeDelta profile_duration,
168 TimeDelta sampling_period) {
169 std::move(callback_).Run(Profile{samples_, record_metadata_count_,
170 retrospective_metadata_, profile_duration,
171 sampling_period});
172 }
173
174 // Unloads |library| and returns when it has completed unloading. Unloading a
175 // library is asynchronous on Windows, so simply calling UnloadNativeLibrary()
176 // is insufficient to ensure it's been unloaded.
SynchronousUnloadNativeLibrary(NativeLibrary library)177 void SynchronousUnloadNativeLibrary(NativeLibrary library) {
178 UnloadNativeLibrary(library);
179 #if defined(OS_WIN)
180 // NativeLibrary is a typedef for HMODULE, which is actually the base address
181 // of the module.
182 uintptr_t module_base_address = reinterpret_cast<uintptr_t>(library);
183 HMODULE module_handle;
184 // Keep trying to get the module handle until the call fails.
185 while (::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
186 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
187 reinterpret_cast<LPCTSTR>(module_base_address),
188 &module_handle) ||
189 ::GetLastError() != ERROR_MOD_NOT_FOUND) {
190 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
191 }
192 #elif defined(OS_APPLE) || defined(OS_ANDROID)
193 // Unloading a library on Mac and Android is synchronous.
194 #else
195 NOTIMPLEMENTED();
196 #endif
197 }
198
WithTargetThread(ProfileCallback profile_callback)199 void WithTargetThread(ProfileCallback profile_callback) {
200 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
201 WithTargetThread(&scenario, std::move(profile_callback));
202 }
203
204 struct TestProfilerInfo {
TestProfilerInfobase::__anon416616460111::TestProfilerInfo205 TestProfilerInfo(SamplingProfilerThreadToken thread_token,
206 const SamplingParams& params,
207 ModuleCache* module_cache,
208 StackSamplerTestDelegate* delegate = nullptr)
209 : completed(WaitableEvent::ResetPolicy::MANUAL,
210 WaitableEvent::InitialState::NOT_SIGNALED),
211 profiler(thread_token,
212 params,
213 std::make_unique<TestProfileBuilder>(
214 module_cache,
215 BindLambdaForTesting([this](Profile result_profile) {
216 profile = std::move(result_profile);
217 completed.Signal();
218 })),
219 CreateCoreUnwindersFactoryForTesting(module_cache),
220 RepeatingClosure(),
221 delegate) {}
222
223 // The order here is important to ensure objects being referenced don't get
224 // destructed until after the objects referencing them.
225 Profile profile;
226 WaitableEvent completed;
227 StackSamplingProfiler profiler;
228
229 private:
230 DISALLOW_COPY_AND_ASSIGN(TestProfilerInfo);
231 };
232
233 // Creates multiple profilers based on a vector of parameters.
CreateProfilers(SamplingProfilerThreadToken target_thread_token,const std::vector<SamplingParams> & params,ModuleCache * module_cache)234 std::vector<std::unique_ptr<TestProfilerInfo>> CreateProfilers(
235 SamplingProfilerThreadToken target_thread_token,
236 const std::vector<SamplingParams>& params,
237 ModuleCache* module_cache) {
238 DCHECK(!params.empty());
239
240 std::vector<std::unique_ptr<TestProfilerInfo>> profilers;
241 for (const auto& i : params) {
242 profilers.push_back(std::make_unique<TestProfilerInfo>(target_thread_token,
243 i, module_cache));
244 }
245
246 return profilers;
247 }
248
249 // Captures samples as specified by |params| on the TargetThread, and returns
250 // them. Waits up to |profiler_wait_time| for the profiler to complete.
CaptureSamples(const SamplingParams & params,TimeDelta profiler_wait_time,ModuleCache * module_cache)251 std::vector<std::vector<Frame>> CaptureSamples(const SamplingParams& params,
252 TimeDelta profiler_wait_time,
253 ModuleCache* module_cache) {
254 std::vector<std::vector<Frame>> samples;
255 WithTargetThread(BindLambdaForTesting(
256 [&](SamplingProfilerThreadToken target_thread_token) {
257 TestProfilerInfo info(target_thread_token, params, module_cache);
258 info.profiler.Start();
259 info.completed.TimedWait(profiler_wait_time);
260 info.profiler.Stop();
261 info.completed.Wait();
262 samples = std::move(info.profile.samples);
263 }));
264
265 return samples;
266 }
267
268 // Waits for one of multiple samplings to complete.
WaitForSamplingComplete(const std::vector<std::unique_ptr<TestProfilerInfo>> & infos)269 size_t WaitForSamplingComplete(
270 const std::vector<std::unique_ptr<TestProfilerInfo>>& infos) {
271 // Map unique_ptrs to something that WaitMany can accept.
272 std::vector<WaitableEvent*> sampling_completed_rawptrs(infos.size());
273 ranges::transform(infos, sampling_completed_rawptrs.begin(),
274 [](const std::unique_ptr<TestProfilerInfo>& info) {
275 return &info.get()->completed;
276 });
277 // Wait for one profiler to finish.
278 return WaitableEvent::WaitMany(sampling_completed_rawptrs.data(),
279 sampling_completed_rawptrs.size());
280 }
281
282 // Returns a duration that is longer than the test timeout. We would use
283 // TimeDelta::Max() but https://crbug.com/465948.
AVeryLongTimeDelta()284 TimeDelta AVeryLongTimeDelta() {
285 return TimeDelta::FromDays(1);
286 }
287
288 // Tests the scenario where the library is unloaded after copying the stack, but
289 // before walking it. If |wait_until_unloaded| is true, ensures that the
290 // asynchronous library loading has completed before walking the stack. If
291 // false, the unloading may still be occurring during the stack walk.
TestLibraryUnload(bool wait_until_unloaded,ModuleCache * module_cache)292 void TestLibraryUnload(bool wait_until_unloaded, ModuleCache* module_cache) {
293 // Test delegate that supports intervening between the copying of the stack
294 // and the walking of the stack.
295 class StackCopiedSignaler : public StackSamplerTestDelegate {
296 public:
297 StackCopiedSignaler(WaitableEvent* stack_copied,
298 WaitableEvent* start_stack_walk,
299 bool wait_to_walk_stack)
300 : stack_copied_(stack_copied),
301 start_stack_walk_(start_stack_walk),
302 wait_to_walk_stack_(wait_to_walk_stack) {}
303
304 void OnPreStackWalk() override {
305 stack_copied_->Signal();
306 if (wait_to_walk_stack_)
307 start_stack_walk_->Wait();
308 }
309
310 private:
311 WaitableEvent* const stack_copied_;
312 WaitableEvent* const start_stack_walk_;
313 const bool wait_to_walk_stack_;
314 };
315
316 SamplingParams params;
317 params.sampling_interval = TimeDelta::FromMilliseconds(0);
318 params.samples_per_profile = 1;
319
320 NativeLibrary other_library = LoadOtherLibrary();
321
322 UnwindScenario scenario(
323 BindRepeating(&CallThroughOtherLibrary, Unretained(other_library)));
324
325 UnwindScenario::SampleEvents events;
326 TargetThread target_thread(
327 BindLambdaForTesting([&]() { scenario.Execute(&events); }));
328
329 PlatformThreadHandle target_thread_handle;
330 EXPECT_TRUE(PlatformThread::Create(0, &target_thread, &target_thread_handle));
331
332 events.ready_for_sample.Wait();
333
334 WaitableEvent sampling_thread_completed(
335 WaitableEvent::ResetPolicy::MANUAL,
336 WaitableEvent::InitialState::NOT_SIGNALED);
337 Profile profile;
338
339 WaitableEvent stack_copied(WaitableEvent::ResetPolicy::MANUAL,
340 WaitableEvent::InitialState::NOT_SIGNALED);
341 WaitableEvent start_stack_walk(WaitableEvent::ResetPolicy::MANUAL,
342 WaitableEvent::InitialState::NOT_SIGNALED);
343 StackCopiedSignaler test_delegate(&stack_copied, &start_stack_walk,
344 wait_until_unloaded);
345 StackSamplingProfiler profiler(
346 target_thread.thread_token(), params,
347 std::make_unique<TestProfileBuilder>(
348 module_cache,
349 BindLambdaForTesting(
350 [&profile, &sampling_thread_completed](Profile result_profile) {
351 profile = std::move(result_profile);
352 sampling_thread_completed.Signal();
353 })),
354 CreateCoreUnwindersFactoryForTesting(module_cache), RepeatingClosure(),
355 &test_delegate);
356
357 profiler.Start();
358
359 // Wait for the stack to be copied and the target thread to be resumed.
360 stack_copied.Wait();
361
362 // Cause the target thread to finish, so that it's no longer executing code in
363 // the library we're about to unload.
364 events.sample_finished.Signal();
365 PlatformThread::Join(target_thread_handle);
366
367 // Unload the library now that it's not being used.
368 if (wait_until_unloaded)
369 SynchronousUnloadNativeLibrary(other_library);
370 else
371 UnloadNativeLibrary(other_library);
372
373 // Let the stack walk commence after unloading the library, if we're waiting
374 // on that event.
375 start_stack_walk.Signal();
376
377 // Wait for the sampling thread to complete and fill out |profile|.
378 sampling_thread_completed.Wait();
379
380 // Look up the sample.
381 ASSERT_EQ(1u, profile.samples.size());
382 const std::vector<Frame>& sample = profile.samples[0];
383
384 if (wait_until_unloaded) {
385 // We expect the stack to look something like this, with the frame in the
386 // now-unloaded library having a null module.
387 //
388 // ... WaitableEvent and system frames ...
389 // WaitForSample()
390 // TargetThread::OtherLibraryCallback
391 // <frame in unloaded library>
392 EXPECT_EQ(nullptr, sample.back().module)
393 << "Stack:\n"
394 << FormatSampleForDiagnosticOutput(sample);
395
396 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange()});
397 ExpectStackDoesNotContain(sample,
398 {scenario.GetSetupFunctionAddressRange(),
399 scenario.GetOuterFunctionAddressRange()});
400 } else {
401 // We didn't wait for the asynchronous unloading to complete, so the results
402 // are non-deterministic: if the library finished unloading we should have
403 // the same stack as |wait_until_unloaded|, if not we should have the full
404 // stack. The important thing is that we should not crash.
405
406 if (!sample.back().module) {
407 // This is the same case as |wait_until_unloaded|.
408 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange()});
409 ExpectStackDoesNotContain(sample,
410 {scenario.GetSetupFunctionAddressRange(),
411 scenario.GetOuterFunctionAddressRange()});
412 return;
413 }
414
415 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
416 scenario.GetSetupFunctionAddressRange(),
417 scenario.GetOuterFunctionAddressRange()});
418 }
419 }
420
421 // Provide a suitable (and clean) environment for the tests below. All tests
422 // must use this class to ensure that proper clean-up is done and thus be
423 // usable in a later test.
424 class StackSamplingProfilerTest : public testing::Test {
425 public:
SetUp()426 void SetUp() override {
427 // The idle-shutdown time is too long for convenient (and accurate) testing.
428 // That behavior is checked instead by artificially triggering it through
429 // the TestPeer.
430 StackSamplingProfiler::TestPeer::DisableIdleShutdown();
431 }
432
TearDown()433 void TearDown() override {
434 // Be a good citizen and clean up after ourselves. This also re-enables the
435 // idle-shutdown behavior.
436 StackSamplingProfiler::TestPeer::Reset();
437 }
438
439 protected:
module_cache()440 ModuleCache* module_cache() { return &module_cache_; }
441
442 private:
443 ModuleCache module_cache_;
444 };
445
446 } // namespace
447
448 // Checks that the basic expected information is present in sampled frames.
449 //
450 // macOS ASAN is not yet supported - crbug.com/718628.
451 //
452 // TODO(https://crbug.com/1100175): Enable this test again for Android with
453 // ASAN. This is now disabled because the android-asan bot fails.
454 #if (defined(ADDRESS_SANITIZER) && defined(OS_APPLE)) || \
455 (defined(ADDRESS_SANITIZER) && defined(OS_ANDROID))
456 #define MAYBE_Basic DISABLED_Basic
457 #else
458 #define MAYBE_Basic Basic
459 #endif
PROFILER_TEST_F(StackSamplingProfilerTest,MAYBE_Basic)460 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_Basic) {
461 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
462 const std::vector<Frame>& sample = SampleScenario(&scenario, module_cache());
463
464 // Check that all the modules are valid.
465 for (const auto& frame : sample)
466 EXPECT_NE(nullptr, frame.module);
467
468 // The stack should contain a full unwind.
469 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
470 scenario.GetSetupFunctionAddressRange(),
471 scenario.GetOuterFunctionAddressRange()});
472 }
473
474 // A simple unwinder that always generates one frame then aborts the stack walk.
475 class TestAuxUnwinder : public Unwinder {
476 public:
TestAuxUnwinder(const Frame & frame_to_report,base::RepeatingClosure add_initial_modules_callback)477 TestAuxUnwinder(const Frame& frame_to_report,
478 base::RepeatingClosure add_initial_modules_callback)
479 : frame_to_report_(frame_to_report),
480 add_initial_modules_callback_(std::move(add_initial_modules_callback)) {
481 }
482
483 TestAuxUnwinder(const TestAuxUnwinder&) = delete;
484 TestAuxUnwinder& operator=(const TestAuxUnwinder&) = delete;
485
AddInitialModules(ModuleCache * module_cache)486 void AddInitialModules(ModuleCache* module_cache) override {
487 if (add_initial_modules_callback_)
488 add_initial_modules_callback_.Run();
489 }
CanUnwindFrom(const Frame & current_frame) const490 bool CanUnwindFrom(const Frame& current_frame) const override { return true; }
491
TryUnwind(RegisterContext * thread_context,uintptr_t stack_top,ModuleCache * module_cache,std::vector<Frame> * stack) const492 UnwindResult TryUnwind(RegisterContext* thread_context,
493 uintptr_t stack_top,
494 ModuleCache* module_cache,
495 std::vector<Frame>* stack) const override {
496 stack->push_back(frame_to_report_);
497 return UnwindResult::ABORTED;
498 }
499
500 private:
501 const Frame frame_to_report_;
502 base::RepeatingClosure add_initial_modules_callback_;
503 };
504
505 // Checks that the profiler handles stacks containing dynamically-allocated
506 // stack memory.
507 // macOS ASAN is not yet supported - crbug.com/718628.
508 // Android is not supported since Chrome unwind tables don't support dynamic
509 // frames.
510 #if (defined(ADDRESS_SANITIZER) && defined(OS_APPLE)) || defined(OS_ANDROID)
511 #define MAYBE_Alloca DISABLED_Alloca
512 #else
513 #define MAYBE_Alloca Alloca
514 #endif
PROFILER_TEST_F(StackSamplingProfilerTest,MAYBE_Alloca)515 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_Alloca) {
516 UnwindScenario scenario(BindRepeating(&CallWithAlloca));
517 const std::vector<Frame>& sample = SampleScenario(&scenario, module_cache());
518
519 // The stack should contain a full unwind.
520 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
521 scenario.GetSetupFunctionAddressRange(),
522 scenario.GetOuterFunctionAddressRange()});
523 }
524
525 // Checks that a stack that runs through another library produces a stack with
526 // the expected functions.
527 // macOS ASAN is not yet supported - crbug.com/718628.
528 // Android is not supported when EXCLUDE_UNWIND_TABLES |other_library| doesn't
529 // have unwind tables.
530 // TODO(https://crbug.com/1100175): Enable this test again for Android with
531 // ASAN. This is now disabled because the android-asan bot fails.
532 #if (defined(ADDRESS_SANITIZER) && defined(OS_APPLE)) || \
533 (defined(OS_ANDROID) && BUILDFLAG(EXCLUDE_UNWIND_TABLES)) || \
534 (defined(OS_ANDROID) && defined(ADDRESS_SANITIZER))
535 #define MAYBE_OtherLibrary DISABLED_OtherLibrary
536 #else
537 #define MAYBE_OtherLibrary OtherLibrary
538 #endif
PROFILER_TEST_F(StackSamplingProfilerTest,MAYBE_OtherLibrary)539 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_OtherLibrary) {
540 ScopedNativeLibrary other_library(LoadOtherLibrary());
541 UnwindScenario scenario(
542 BindRepeating(&CallThroughOtherLibrary, Unretained(other_library.get())));
543 const std::vector<Frame>& sample = SampleScenario(&scenario, module_cache());
544
545 // The stack should contain a full unwind.
546 ExpectStackContains(sample, {scenario.GetWaitForSampleAddressRange(),
547 scenario.GetSetupFunctionAddressRange(),
548 scenario.GetOuterFunctionAddressRange()});
549 }
550
551 // Checks that a stack that runs through a library that is unloading produces a
552 // stack, and doesn't crash.
553 // Unloading is synchronous on the Mac, so this test is inapplicable.
554 // Android is not supported when EXCLUDE_UNWIND_TABLES |other_library| doesn't
555 // have unwind tables.
556 // TODO(https://crbug.com/1100175): Enable this test again for Android with
557 // ASAN. This is now disabled because the android-asan bot fails.
558 #if defined(OS_APPLE) || \
559 (defined(OS_ANDROID) && BUILDFLAG(EXCLUDE_UNWIND_TABLES)) || \
560 (defined(OS_ANDROID) && defined(ADDRESS_SANITIZER))
561 #define MAYBE_UnloadingLibrary DISABLED_UnloadingLibrary
562 #else
563 #define MAYBE_UnloadingLibrary UnloadingLibrary
564 #endif
PROFILER_TEST_F(StackSamplingProfilerTest,MAYBE_UnloadingLibrary)565 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_UnloadingLibrary) {
566 TestLibraryUnload(false, module_cache());
567 }
568
569 // Checks that a stack that runs through a library that has been unloaded
570 // produces a stack, and doesn't crash.
571 // macOS ASAN is not yet supported - crbug.com/718628.
572 // Android is not supported since modules are found before unwinding.
573 #if (defined(ADDRESS_SANITIZER) && defined(OS_APPLE)) || defined(OS_ANDROID)
574 #define MAYBE_UnloadedLibrary DISABLED_UnloadedLibrary
575 #else
576 #define MAYBE_UnloadedLibrary UnloadedLibrary
577 #endif
PROFILER_TEST_F(StackSamplingProfilerTest,MAYBE_UnloadedLibrary)578 PROFILER_TEST_F(StackSamplingProfilerTest, MAYBE_UnloadedLibrary) {
579 TestLibraryUnload(true, module_cache());
580 }
581
582 // Checks that a profiler can stop/destruct without ever having started.
PROFILER_TEST_F(StackSamplingProfilerTest,StopWithoutStarting)583 PROFILER_TEST_F(StackSamplingProfilerTest, StopWithoutStarting) {
584 WithTargetThread(BindLambdaForTesting(
585 [this](SamplingProfilerThreadToken target_thread_token) {
586 SamplingParams params;
587 params.sampling_interval = TimeDelta::FromMilliseconds(0);
588 params.samples_per_profile = 1;
589
590 Profile profile;
591 WaitableEvent sampling_completed(
592 WaitableEvent::ResetPolicy::MANUAL,
593 WaitableEvent::InitialState::NOT_SIGNALED);
594
595 StackSamplingProfiler profiler(
596 target_thread_token, params,
597 std::make_unique<TestProfileBuilder>(
598 module_cache(),
599 BindLambdaForTesting(
600 [&profile, &sampling_completed](Profile result_profile) {
601 profile = std::move(result_profile);
602 sampling_completed.Signal();
603 })),
604 CreateCoreUnwindersFactoryForTesting(module_cache()));
605
606 profiler.Stop(); // Constructed but never started.
607 EXPECT_FALSE(sampling_completed.IsSignaled());
608 }));
609 }
610
611 // Checks that its okay to stop a profiler before it finishes even when the
612 // sampling thread continues to run.
PROFILER_TEST_F(StackSamplingProfilerTest,StopSafely)613 PROFILER_TEST_F(StackSamplingProfilerTest, StopSafely) {
614 // Test delegate that counts samples.
615 class SampleRecordedCounter : public StackSamplerTestDelegate {
616 public:
617 SampleRecordedCounter() = default;
618
619 void OnPreStackWalk() override {
620 AutoLock lock(lock_);
621 ++count_;
622 }
623
624 size_t Get() {
625 AutoLock lock(lock_);
626 return count_;
627 }
628
629 private:
630 Lock lock_;
631 size_t count_ = 0;
632 };
633
634 WithTargetThread(BindLambdaForTesting(
635 [this](SamplingProfilerThreadToken target_thread_token) {
636 SamplingParams params[2];
637
638 // Providing an initial delay makes it more likely that both will be
639 // scheduled before either starts to run. Once started, samples will
640 // run ordered by their scheduled, interleaved times regardless of
641 // whatever interval the thread wakes up.
642 params[0].initial_delay = TimeDelta::FromMilliseconds(10);
643 params[0].sampling_interval = TimeDelta::FromMilliseconds(1);
644 params[0].samples_per_profile = 100000;
645
646 params[1].initial_delay = TimeDelta::FromMilliseconds(10);
647 params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
648 params[1].samples_per_profile = 100000;
649
650 SampleRecordedCounter samples_recorded[size(params)];
651
652 TestProfilerInfo profiler_info0(target_thread_token, params[0],
653 module_cache(), &samples_recorded[0]);
654 TestProfilerInfo profiler_info1(target_thread_token, params[1],
655 module_cache(), &samples_recorded[1]);
656
657 profiler_info0.profiler.Start();
658 profiler_info1.profiler.Start();
659
660 // Wait for both to start accumulating samples. Using a WaitableEvent is
661 // possible but gets complicated later on because there's no way of
662 // knowing if 0 or 1 additional sample will be taken after Stop() and
663 // thus no way of knowing how many Wait() calls to make on it.
664 while (samples_recorded[0].Get() == 0 || samples_recorded[1].Get() == 0)
665 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
666
667 // Ensure that the first sampler can be safely stopped while the second
668 // continues to run. The stopped first profiler will still have a
669 // RecordSampleTask pending that will do nothing when executed because
670 // the collection will have been removed by Stop().
671 profiler_info0.profiler.Stop();
672 profiler_info0.completed.Wait();
673 size_t count0 = samples_recorded[0].Get();
674 size_t count1 = samples_recorded[1].Get();
675
676 // Waiting for the second sampler to collect a couple samples ensures
677 // that the pending RecordSampleTask for the first has executed because
678 // tasks are always ordered by their next scheduled time.
679 while (samples_recorded[1].Get() < count1 + 2)
680 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
681
682 // Ensure that the first profiler didn't do anything since it was
683 // stopped.
684 EXPECT_EQ(count0, samples_recorded[0].Get());
685 }));
686 }
687
688 // Checks that no sample are captured if the profiling is stopped during the
689 // initial delay.
PROFILER_TEST_F(StackSamplingProfilerTest,StopDuringInitialDelay)690 PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInitialDelay) {
691 SamplingParams params;
692 params.initial_delay = TimeDelta::FromSeconds(60);
693
694 std::vector<std::vector<Frame>> samples =
695 CaptureSamples(params, TimeDelta::FromMilliseconds(0), module_cache());
696
697 EXPECT_TRUE(samples.empty());
698 }
699
700 // Checks that tasks can be stopped before completion and incomplete samples are
701 // captured.
PROFILER_TEST_F(StackSamplingProfilerTest,StopDuringInterSampleInterval)702 PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInterSampleInterval) {
703 // Test delegate that counts samples.
704 class SampleRecordedEvent : public StackSamplerTestDelegate {
705 public:
706 SampleRecordedEvent()
707 : sample_recorded_(WaitableEvent::ResetPolicy::MANUAL,
708 WaitableEvent::InitialState::NOT_SIGNALED) {}
709
710 void OnPreStackWalk() override { sample_recorded_.Signal(); }
711
712 void WaitForSample() { sample_recorded_.Wait(); }
713
714 private:
715 WaitableEvent sample_recorded_;
716 };
717
718 WithTargetThread(BindLambdaForTesting(
719 [this](SamplingProfilerThreadToken target_thread_token) {
720 SamplingParams params;
721
722 params.sampling_interval = AVeryLongTimeDelta();
723 params.samples_per_profile = 2;
724
725 SampleRecordedEvent samples_recorded;
726 TestProfilerInfo profiler_info(target_thread_token, params,
727 module_cache(), &samples_recorded);
728
729 profiler_info.profiler.Start();
730
731 // Wait for profiler to start accumulating samples.
732 samples_recorded.WaitForSample();
733
734 // Ensure that it can stop safely.
735 profiler_info.profiler.Stop();
736 profiler_info.completed.Wait();
737
738 EXPECT_EQ(1u, profiler_info.profile.samples.size());
739 }));
740 }
741
PROFILER_TEST_F(StackSamplingProfilerTest,GetNextSampleTime_NormalExecution)742 PROFILER_TEST_F(StackSamplingProfilerTest, GetNextSampleTime_NormalExecution) {
743 const auto& GetNextSampleTime =
744 StackSamplingProfiler::TestPeer::GetNextSampleTime;
745
746 const TimeTicks scheduled_current_sample_time = TimeTicks::UnixEpoch();
747 const TimeDelta sampling_interval = TimeDelta::FromMilliseconds(10);
748
749 // When executing the sample at exactly the scheduled time the next sample
750 // should be one interval later.
751 EXPECT_EQ(scheduled_current_sample_time + sampling_interval,
752 GetNextSampleTime(scheduled_current_sample_time, sampling_interval,
753 scheduled_current_sample_time));
754
755 // When executing the sample less than half an interval after the scheduled
756 // time the next sample also should be one interval later.
757 EXPECT_EQ(scheduled_current_sample_time + sampling_interval,
758 GetNextSampleTime(
759 scheduled_current_sample_time, sampling_interval,
760 scheduled_current_sample_time + 0.4 * sampling_interval));
761
762 // When executing the sample less than half an interval before the scheduled
763 // time the next sample also should be one interval later. This is not
764 // expected to occur in practice since delayed tasks never run early.
765 EXPECT_EQ(scheduled_current_sample_time + sampling_interval,
766 GetNextSampleTime(
767 scheduled_current_sample_time, sampling_interval,
768 scheduled_current_sample_time - 0.4 * sampling_interval));
769 }
770
PROFILER_TEST_F(StackSamplingProfilerTest,GetNextSampleTime_DelayedExecution)771 PROFILER_TEST_F(StackSamplingProfilerTest, GetNextSampleTime_DelayedExecution) {
772 const auto& GetNextSampleTime =
773 StackSamplingProfiler::TestPeer::GetNextSampleTime;
774
775 const TimeTicks scheduled_current_sample_time = TimeTicks::UnixEpoch();
776 const TimeDelta sampling_interval = TimeDelta::FromMilliseconds(10);
777
778 // When executing the sample between 0.5 and 1.5 intervals after the scheduled
779 // time the next sample should be two intervals later.
780 EXPECT_EQ(scheduled_current_sample_time + 2 * sampling_interval,
781 GetNextSampleTime(
782 scheduled_current_sample_time, sampling_interval,
783 scheduled_current_sample_time + 0.6 * sampling_interval));
784 EXPECT_EQ(scheduled_current_sample_time + 2 * sampling_interval,
785 GetNextSampleTime(
786 scheduled_current_sample_time, sampling_interval,
787 scheduled_current_sample_time + 1.0 * sampling_interval));
788 EXPECT_EQ(scheduled_current_sample_time + 2 * sampling_interval,
789 GetNextSampleTime(
790 scheduled_current_sample_time, sampling_interval,
791 scheduled_current_sample_time + 1.4 * sampling_interval));
792
793 // Similarly when executing the sample between 9.5 and 10.5 intervals after
794 // the scheduled time the next sample should be 11 intervals later.
795 EXPECT_EQ(scheduled_current_sample_time + 11 * sampling_interval,
796 GetNextSampleTime(
797 scheduled_current_sample_time, sampling_interval,
798 scheduled_current_sample_time + 9.6 * sampling_interval));
799 EXPECT_EQ(scheduled_current_sample_time + 11 * sampling_interval,
800 GetNextSampleTime(
801 scheduled_current_sample_time, sampling_interval,
802 scheduled_current_sample_time + 10.0 * sampling_interval));
803 EXPECT_EQ(scheduled_current_sample_time + 11 * sampling_interval,
804 GetNextSampleTime(
805 scheduled_current_sample_time, sampling_interval,
806 scheduled_current_sample_time + 10.4 * sampling_interval));
807 }
808
809 // Checks that we can destroy the profiler while profiling.
PROFILER_TEST_F(StackSamplingProfilerTest,DestroyProfilerWhileProfiling)810 PROFILER_TEST_F(StackSamplingProfilerTest, DestroyProfilerWhileProfiling) {
811 SamplingParams params;
812 params.sampling_interval = TimeDelta::FromMilliseconds(10);
813
814 Profile profile;
815 WithTargetThread(BindLambdaForTesting([&, this](SamplingProfilerThreadToken
816 target_thread_token) {
817 std::unique_ptr<StackSamplingProfiler> profiler;
818 auto profile_builder = std::make_unique<TestProfileBuilder>(
819 module_cache(),
820 BindLambdaForTesting([&profile](Profile result_profile) {
821 profile = std::move(result_profile);
822 }));
823 profiler.reset(new StackSamplingProfiler(
824 target_thread_token, params, std::move(profile_builder),
825 CreateCoreUnwindersFactoryForTesting(module_cache())));
826 profiler->Start();
827 profiler.reset();
828
829 // Wait longer than a sample interval to catch any use-after-free actions by
830 // the profiler thread.
831 PlatformThread::Sleep(TimeDelta::FromMilliseconds(50));
832 }));
833 }
834
835 // Checks that the different profilers may be run.
PROFILER_TEST_F(StackSamplingProfilerTest,CanRunMultipleProfilers)836 PROFILER_TEST_F(StackSamplingProfilerTest, CanRunMultipleProfilers) {
837 SamplingParams params;
838 params.sampling_interval = TimeDelta::FromMilliseconds(0);
839 params.samples_per_profile = 1;
840
841 std::vector<std::vector<Frame>> samples =
842 CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
843 ASSERT_EQ(1u, samples.size());
844
845 samples = CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
846 ASSERT_EQ(1u, samples.size());
847 }
848
849 // Checks that a sampler can be started while another is running.
PROFILER_TEST_F(StackSamplingProfilerTest,MultipleStart)850 PROFILER_TEST_F(StackSamplingProfilerTest, MultipleStart) {
851 WithTargetThread(BindLambdaForTesting(
852 [this](SamplingProfilerThreadToken target_thread_token) {
853 std::vector<SamplingParams> params(2);
854
855 params[0].initial_delay = AVeryLongTimeDelta();
856 params[0].samples_per_profile = 1;
857
858 params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
859 params[1].samples_per_profile = 1;
860
861 std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
862 CreateProfilers(target_thread_token, params, module_cache());
863
864 profiler_infos[0]->profiler.Start();
865 profiler_infos[1]->profiler.Start();
866 profiler_infos[1]->completed.Wait();
867 EXPECT_EQ(1u, profiler_infos[1]->profile.samples.size());
868 }));
869 }
870
871 // Checks that the profile duration and the sampling interval are calculated
872 // correctly. Also checks that RecordMetadata() is invoked each time a sample
873 // is recorded.
PROFILER_TEST_F(StackSamplingProfilerTest,ProfileGeneralInfo)874 PROFILER_TEST_F(StackSamplingProfilerTest, ProfileGeneralInfo) {
875 WithTargetThread(BindLambdaForTesting(
876 [this](SamplingProfilerThreadToken target_thread_token) {
877 SamplingParams params;
878 params.sampling_interval = TimeDelta::FromMilliseconds(1);
879 params.samples_per_profile = 3;
880
881 TestProfilerInfo profiler_info(target_thread_token, params,
882 module_cache());
883
884 profiler_info.profiler.Start();
885 profiler_info.completed.Wait();
886 EXPECT_EQ(3u, profiler_info.profile.samples.size());
887
888 // The profile duration should be greater than the total sampling
889 // intervals.
890 EXPECT_GT(profiler_info.profile.profile_duration,
891 profiler_info.profile.sampling_period * 3);
892
893 EXPECT_EQ(TimeDelta::FromMilliseconds(1),
894 profiler_info.profile.sampling_period);
895
896 // The number of invocations of RecordMetadata() should be equal to the
897 // number of samples recorded.
898 EXPECT_EQ(3, profiler_info.profile.record_metadata_count);
899 }));
900 }
901
902 // Checks that the sampling thread can shut down.
PROFILER_TEST_F(StackSamplingProfilerTest,SamplerIdleShutdown)903 PROFILER_TEST_F(StackSamplingProfilerTest, SamplerIdleShutdown) {
904 SamplingParams params;
905 params.sampling_interval = TimeDelta::FromMilliseconds(0);
906 params.samples_per_profile = 1;
907
908 std::vector<std::vector<Frame>> samples =
909 CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
910 ASSERT_EQ(1u, samples.size());
911
912 // Capture thread should still be running at this point.
913 ASSERT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
914
915 // Initiate an "idle" shutdown and ensure it happens. Idle-shutdown was
916 // disabled by the test fixture so the test will fail due to a timeout if
917 // it does not exit.
918 StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(false);
919
920 // While the shutdown has been initiated, the actual exit of the thread still
921 // happens asynchronously. Watch until the thread actually exits. This test
922 // will time-out in the case of failure.
923 while (StackSamplingProfiler::TestPeer::IsSamplingThreadRunning())
924 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
925 }
926
927 // Checks that additional requests will restart a stopped profiler.
PROFILER_TEST_F(StackSamplingProfilerTest,WillRestartSamplerAfterIdleShutdown)928 PROFILER_TEST_F(StackSamplingProfilerTest,
929 WillRestartSamplerAfterIdleShutdown) {
930 SamplingParams params;
931 params.sampling_interval = TimeDelta::FromMilliseconds(0);
932 params.samples_per_profile = 1;
933
934 std::vector<std::vector<Frame>> samples =
935 CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
936 ASSERT_EQ(1u, samples.size());
937
938 // Capture thread should still be running at this point.
939 ASSERT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
940
941 // Post a ShutdownTask on the sampling thread which, when executed, will
942 // mark the thread as EXITING and begin shut down of the thread.
943 StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(false);
944
945 // Ensure another capture will start the sampling thread and run.
946 samples = CaptureSamples(params, AVeryLongTimeDelta(), module_cache());
947 ASSERT_EQ(1u, samples.size());
948 EXPECT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
949 }
950
951 // Checks that it's safe to stop a task after it's completed and the sampling
952 // thread has shut-down for being idle.
PROFILER_TEST_F(StackSamplingProfilerTest,StopAfterIdleShutdown)953 PROFILER_TEST_F(StackSamplingProfilerTest, StopAfterIdleShutdown) {
954 WithTargetThread(BindLambdaForTesting(
955 [this](SamplingProfilerThreadToken target_thread_token) {
956 SamplingParams params;
957
958 params.sampling_interval = TimeDelta::FromMilliseconds(1);
959 params.samples_per_profile = 1;
960
961 TestProfilerInfo profiler_info(target_thread_token, params,
962 module_cache());
963
964 profiler_info.profiler.Start();
965 profiler_info.completed.Wait();
966
967 // Capture thread should still be running at this point.
968 ASSERT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
969
970 // Perform an idle shutdown.
971 StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(
972 false);
973
974 // Stop should be safe though its impossible to know at this moment if
975 // the sampling thread has completely exited or will just "stop soon".
976 profiler_info.profiler.Stop();
977 }));
978 }
979
980 // Checks that profilers can run both before and after the sampling thread has
981 // started.
PROFILER_TEST_F(StackSamplingProfilerTest,ProfileBeforeAndAfterSamplingThreadRunning)982 PROFILER_TEST_F(StackSamplingProfilerTest,
983 ProfileBeforeAndAfterSamplingThreadRunning) {
984 WithTargetThread(BindLambdaForTesting(
985 [this](SamplingProfilerThreadToken target_thread_token) {
986 std::vector<SamplingParams> params(2);
987
988 params[0].initial_delay = AVeryLongTimeDelta();
989 params[0].sampling_interval = TimeDelta::FromMilliseconds(1);
990 params[0].samples_per_profile = 1;
991
992 params[1].initial_delay = TimeDelta::FromMilliseconds(0);
993 params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
994 params[1].samples_per_profile = 1;
995
996 std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
997 CreateProfilers(target_thread_token, params, module_cache());
998
999 // First profiler is started when there has never been a sampling
1000 // thread.
1001 EXPECT_FALSE(
1002 StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
1003 profiler_infos[0]->profiler.Start();
1004 // Second profiler is started when sampling thread is already running.
1005 EXPECT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
1006 profiler_infos[1]->profiler.Start();
1007
1008 // Only the second profiler should finish before test times out.
1009 size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
1010 EXPECT_EQ(1U, completed_profiler);
1011 }));
1012 }
1013
1014 // Checks that an idle-shutdown task will abort if a new profiler starts
1015 // between when it was posted and when it runs.
PROFILER_TEST_F(StackSamplingProfilerTest,IdleShutdownAbort)1016 PROFILER_TEST_F(StackSamplingProfilerTest, IdleShutdownAbort) {
1017 WithTargetThread(BindLambdaForTesting(
1018 [this](SamplingProfilerThreadToken target_thread_token) {
1019 SamplingParams params;
1020
1021 params.sampling_interval = TimeDelta::FromMilliseconds(1);
1022 params.samples_per_profile = 1;
1023
1024 TestProfilerInfo profiler_info(target_thread_token, params,
1025 module_cache());
1026
1027 profiler_info.profiler.Start();
1028 profiler_info.completed.Wait();
1029 EXPECT_EQ(1u, profiler_info.profile.samples.size());
1030
1031 // Perform an idle shutdown but simulate that a new capture is started
1032 // before it can actually run.
1033 StackSamplingProfiler::TestPeer::PerformSamplingThreadIdleShutdown(
1034 true);
1035
1036 // Though the shutdown-task has been executed, any actual exit of the
1037 // thread is asynchronous so there is no way to detect that *didn't*
1038 // exit except to wait a reasonable amount of time and then check. Since
1039 // the thread was just running ("perform" blocked until it was), it
1040 // should finish almost immediately and without any waiting for tasks or
1041 // events.
1042 PlatformThread::Sleep(TimeDelta::FromMilliseconds(200));
1043 EXPECT_TRUE(StackSamplingProfiler::TestPeer::IsSamplingThreadRunning());
1044
1045 // Ensure that it's still possible to run another sampler.
1046 TestProfilerInfo another_info(target_thread_token, params,
1047 module_cache());
1048 another_info.profiler.Start();
1049 another_info.completed.Wait();
1050 EXPECT_EQ(1u, another_info.profile.samples.size());
1051 }));
1052 }
1053
1054 // Checks that synchronized multiple sampling requests execute in parallel.
PROFILER_TEST_F(StackSamplingProfilerTest,ConcurrentProfiling_InSync)1055 PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_InSync) {
1056 WithTargetThread(BindLambdaForTesting(
1057 [this](SamplingProfilerThreadToken target_thread_token) {
1058 std::vector<SamplingParams> params(2);
1059
1060 // Providing an initial delay makes it more likely that both will be
1061 // scheduled before either starts to run. Once started, samples will
1062 // run ordered by their scheduled, interleaved times regardless of
1063 // whatever interval the thread wakes up. Thus, total execution time
1064 // will be 10ms (delay) + 10x1ms (sampling) + 1/2 timer minimum
1065 // interval.
1066 params[0].initial_delay = TimeDelta::FromMilliseconds(10);
1067 params[0].sampling_interval = TimeDelta::FromMilliseconds(1);
1068 params[0].samples_per_profile = 9;
1069
1070 params[1].initial_delay = TimeDelta::FromMilliseconds(11);
1071 params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
1072 params[1].samples_per_profile = 8;
1073
1074 std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
1075 CreateProfilers(target_thread_token, params, module_cache());
1076
1077 profiler_infos[0]->profiler.Start();
1078 profiler_infos[1]->profiler.Start();
1079
1080 // Wait for one profiler to finish.
1081 size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
1082
1083 size_t other_profiler = 1 - completed_profiler;
1084 // Wait for the other profiler to finish.
1085 profiler_infos[other_profiler]->completed.Wait();
1086
1087 // Ensure each got the correct number of samples.
1088 EXPECT_EQ(9u, profiler_infos[0]->profile.samples.size());
1089 EXPECT_EQ(8u, profiler_infos[1]->profile.samples.size());
1090 }));
1091 }
1092
1093 // Checks that several mixed sampling requests execute in parallel.
PROFILER_TEST_F(StackSamplingProfilerTest,ConcurrentProfiling_Mixed)1094 PROFILER_TEST_F(StackSamplingProfilerTest, ConcurrentProfiling_Mixed) {
1095 WithTargetThread(BindLambdaForTesting(
1096 [this](SamplingProfilerThreadToken target_thread_token) {
1097 std::vector<SamplingParams> params(3);
1098
1099 params[0].initial_delay = TimeDelta::FromMilliseconds(8);
1100 params[0].sampling_interval = TimeDelta::FromMilliseconds(4);
1101 params[0].samples_per_profile = 10;
1102
1103 params[1].initial_delay = TimeDelta::FromMilliseconds(9);
1104 params[1].sampling_interval = TimeDelta::FromMilliseconds(3);
1105 params[1].samples_per_profile = 10;
1106
1107 params[2].initial_delay = TimeDelta::FromMilliseconds(10);
1108 params[2].sampling_interval = TimeDelta::FromMilliseconds(2);
1109 params[2].samples_per_profile = 10;
1110
1111 std::vector<std::unique_ptr<TestProfilerInfo>> profiler_infos =
1112 CreateProfilers(target_thread_token, params, module_cache());
1113
1114 for (auto& i : profiler_infos)
1115 i->profiler.Start();
1116
1117 // Wait for one profiler to finish.
1118 size_t completed_profiler = WaitForSamplingComplete(profiler_infos);
1119 EXPECT_EQ(10u,
1120 profiler_infos[completed_profiler]->profile.samples.size());
1121 // Stop and destroy all profilers, always in the same order. Don't
1122 // crash.
1123 for (auto& i : profiler_infos)
1124 i->profiler.Stop();
1125 for (auto& i : profiler_infos)
1126 i.reset();
1127 }));
1128 }
1129
1130 // Checks that different threads can be sampled in parallel.
PROFILER_TEST_F(StackSamplingProfilerTest,MultipleSampledThreads)1131 PROFILER_TEST_F(StackSamplingProfilerTest, MultipleSampledThreads) {
1132 UnwindScenario scenario1(BindRepeating(&CallWithPlainFunction));
1133 UnwindScenario::SampleEvents events1;
1134 TargetThread target_thread1(
1135 BindLambdaForTesting([&]() { scenario1.Execute(&events1); }));
1136 PlatformThreadHandle target_thread_handle1;
1137 EXPECT_TRUE(
1138 PlatformThread::Create(0, &target_thread1, &target_thread_handle1));
1139 events1.ready_for_sample.Wait();
1140
1141 UnwindScenario scenario2(BindRepeating(&CallWithPlainFunction));
1142 UnwindScenario::SampleEvents events2;
1143 TargetThread target_thread2(
1144 BindLambdaForTesting([&]() { scenario2.Execute(&events2); }));
1145
1146 PlatformThreadHandle target_thread_handle2;
1147 EXPECT_TRUE(
1148 PlatformThread::Create(0, &target_thread2, &target_thread_handle2));
1149 events2.ready_for_sample.Wait();
1150
1151 // Providing an initial delay makes it more likely that both will be
1152 // scheduled before either starts to run. Once started, samples will
1153 // run ordered by their scheduled, interleaved times regardless of
1154 // whatever interval the thread wakes up.
1155 SamplingParams params1, params2;
1156 params1.initial_delay = TimeDelta::FromMilliseconds(10);
1157 params1.sampling_interval = TimeDelta::FromMilliseconds(1);
1158 params1.samples_per_profile = 9;
1159 params2.initial_delay = TimeDelta::FromMilliseconds(10);
1160 params2.sampling_interval = TimeDelta::FromMilliseconds(1);
1161 params2.samples_per_profile = 8;
1162
1163 Profile profile1, profile2;
1164
1165 WaitableEvent sampling_thread_completed1(
1166 WaitableEvent::ResetPolicy::MANUAL,
1167 WaitableEvent::InitialState::NOT_SIGNALED);
1168 StackSamplingProfiler profiler1(
1169 target_thread1.thread_token(), params1,
1170 std::make_unique<TestProfileBuilder>(
1171 module_cache(),
1172 BindLambdaForTesting(
1173 [&profile1, &sampling_thread_completed1](Profile result_profile) {
1174 profile1 = std::move(result_profile);
1175 sampling_thread_completed1.Signal();
1176 })),
1177 CreateCoreUnwindersFactoryForTesting(module_cache()));
1178
1179 WaitableEvent sampling_thread_completed2(
1180 WaitableEvent::ResetPolicy::MANUAL,
1181 WaitableEvent::InitialState::NOT_SIGNALED);
1182 StackSamplingProfiler profiler2(
1183 target_thread2.thread_token(), params2,
1184 std::make_unique<TestProfileBuilder>(
1185 module_cache(),
1186 BindLambdaForTesting(
1187 [&profile2, &sampling_thread_completed2](Profile result_profile) {
1188 profile2 = std::move(result_profile);
1189 sampling_thread_completed2.Signal();
1190 })),
1191 CreateCoreUnwindersFactoryForTesting(module_cache()));
1192
1193 // Finally the real work.
1194 profiler1.Start();
1195 profiler2.Start();
1196 sampling_thread_completed1.Wait();
1197 sampling_thread_completed2.Wait();
1198 EXPECT_EQ(9u, profile1.samples.size());
1199 EXPECT_EQ(8u, profile2.samples.size());
1200
1201 events1.sample_finished.Signal();
1202 events2.sample_finished.Signal();
1203 PlatformThread::Join(target_thread_handle1);
1204 PlatformThread::Join(target_thread_handle2);
1205 }
1206
1207 // A simple thread that runs a profiler on another thread.
1208 class ProfilerThread : public SimpleThread {
1209 public:
ProfilerThread(const std::string & name,SamplingProfilerThreadToken thread_token,const SamplingParams & params,ModuleCache * module_cache)1210 ProfilerThread(const std::string& name,
1211 SamplingProfilerThreadToken thread_token,
1212 const SamplingParams& params,
1213 ModuleCache* module_cache)
1214 : SimpleThread(name, Options()),
1215 run_(WaitableEvent::ResetPolicy::MANUAL,
1216 WaitableEvent::InitialState::NOT_SIGNALED),
1217 completed_(WaitableEvent::ResetPolicy::MANUAL,
1218 WaitableEvent::InitialState::NOT_SIGNALED),
1219 profiler_(thread_token,
1220 params,
1221 std::make_unique<TestProfileBuilder>(
1222 module_cache,
1223 BindLambdaForTesting([this](Profile result_profile) {
1224 profile_ = std::move(result_profile);
1225 completed_.Signal();
1226 })),
1227 CreateCoreUnwindersFactoryForTesting(module_cache)) {}
Run()1228 void Run() override {
1229 run_.Wait();
1230 profiler_.Start();
1231 }
1232
Go()1233 void Go() { run_.Signal(); }
1234
Wait()1235 void Wait() { completed_.Wait(); }
1236
profile()1237 Profile& profile() { return profile_; }
1238
1239 private:
1240 WaitableEvent run_;
1241
1242 Profile profile_;
1243 WaitableEvent completed_;
1244 StackSamplingProfiler profiler_;
1245 };
1246
1247 // Checks that different threads can run samplers in parallel.
PROFILER_TEST_F(StackSamplingProfilerTest,MultipleProfilerThreads)1248 PROFILER_TEST_F(StackSamplingProfilerTest, MultipleProfilerThreads) {
1249 WithTargetThread(
1250 BindLambdaForTesting([](SamplingProfilerThreadToken target_thread_token) {
1251 // Providing an initial delay makes it more likely that both will be
1252 // scheduled before either starts to run. Once started, samples will
1253 // run ordered by their scheduled, interleaved times regardless of
1254 // whatever interval the thread wakes up.
1255 SamplingParams params1, params2;
1256 params1.initial_delay = TimeDelta::FromMilliseconds(10);
1257 params1.sampling_interval = TimeDelta::FromMilliseconds(1);
1258 params1.samples_per_profile = 9;
1259 params2.initial_delay = TimeDelta::FromMilliseconds(10);
1260 params2.sampling_interval = TimeDelta::FromMilliseconds(1);
1261 params2.samples_per_profile = 8;
1262
1263 // Start the profiler threads and give them a moment to get going.
1264 ModuleCache module_cache1;
1265 ProfilerThread profiler_thread1("profiler1", target_thread_token,
1266 params1, &module_cache1);
1267 ModuleCache module_cache2;
1268 ProfilerThread profiler_thread2("profiler2", target_thread_token,
1269 params2, &module_cache2);
1270 profiler_thread1.Start();
1271 profiler_thread2.Start();
1272 PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
1273
1274 // This will (approximately) synchronize the two threads.
1275 profiler_thread1.Go();
1276 profiler_thread2.Go();
1277
1278 // Wait for them both to finish and validate collection.
1279 profiler_thread1.Wait();
1280 profiler_thread2.Wait();
1281 EXPECT_EQ(9u, profiler_thread1.profile().samples.size());
1282 EXPECT_EQ(8u, profiler_thread2.profile().samples.size());
1283
1284 profiler_thread1.Join();
1285 profiler_thread2.Join();
1286 }));
1287 }
1288
PROFILER_TEST_F(StackSamplingProfilerTest,AddAuxUnwinder_BeforeStart)1289 PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_BeforeStart) {
1290 SamplingParams params;
1291 params.sampling_interval = TimeDelta::FromMilliseconds(0);
1292 params.samples_per_profile = 1;
1293
1294 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1295
1296 int add_initial_modules_invocation_count = 0;
1297 const auto add_initial_modules_callback =
1298 [&add_initial_modules_invocation_count]() {
1299 ++add_initial_modules_invocation_count;
1300 };
1301
1302 Profile profile;
1303 WithTargetThread(
1304 &scenario,
1305 BindLambdaForTesting(
1306 [&](SamplingProfilerThreadToken target_thread_token) {
1307 WaitableEvent sampling_thread_completed(
1308 WaitableEvent::ResetPolicy::MANUAL,
1309 WaitableEvent::InitialState::NOT_SIGNALED);
1310 StackSamplingProfiler profiler(
1311 target_thread_token, params,
1312 std::make_unique<TestProfileBuilder>(
1313 module_cache(),
1314 BindLambdaForTesting([&profile, &sampling_thread_completed](
1315 Profile result_profile) {
1316 profile = std::move(result_profile);
1317 sampling_thread_completed.Signal();
1318 })),
1319 CreateCoreUnwindersFactoryForTesting(module_cache()));
1320 profiler.AddAuxUnwinder(std::make_unique<TestAuxUnwinder>(
1321 Frame(23, nullptr),
1322 BindLambdaForTesting(add_initial_modules_callback)));
1323 profiler.Start();
1324 sampling_thread_completed.Wait();
1325 }));
1326
1327 ASSERT_EQ(1, add_initial_modules_invocation_count);
1328
1329 // The sample should have one frame from the context values and one from the
1330 // TestAuxUnwinder.
1331 ASSERT_EQ(1u, profile.samples.size());
1332 const std::vector<Frame>& frames = profile.samples[0];
1333
1334 ASSERT_EQ(2u, frames.size());
1335 EXPECT_EQ(23u, frames[1].instruction_pointer);
1336 EXPECT_EQ(nullptr, frames[1].module);
1337 }
1338
PROFILER_TEST_F(StackSamplingProfilerTest,AddAuxUnwinder_AfterStart)1339 PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_AfterStart) {
1340 SamplingParams params;
1341 params.sampling_interval = TimeDelta::FromMilliseconds(0);
1342 params.samples_per_profile = 1;
1343
1344 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1345
1346 int add_initial_modules_invocation_count = 0;
1347 const auto add_initial_modules_callback =
1348 [&add_initial_modules_invocation_count]() {
1349 ++add_initial_modules_invocation_count;
1350 };
1351
1352 Profile profile;
1353 WithTargetThread(
1354 &scenario,
1355 BindLambdaForTesting(
1356 [&](SamplingProfilerThreadToken target_thread_token) {
1357 WaitableEvent sampling_thread_completed(
1358 WaitableEvent::ResetPolicy::MANUAL,
1359 WaitableEvent::InitialState::NOT_SIGNALED);
1360 StackSamplingProfiler profiler(
1361 target_thread_token, params,
1362 std::make_unique<TestProfileBuilder>(
1363 module_cache(),
1364 BindLambdaForTesting([&profile, &sampling_thread_completed](
1365 Profile result_profile) {
1366 profile = std::move(result_profile);
1367 sampling_thread_completed.Signal();
1368 })),
1369 CreateCoreUnwindersFactoryForTesting(module_cache()));
1370 profiler.Start();
1371 profiler.AddAuxUnwinder(std::make_unique<TestAuxUnwinder>(
1372 Frame(23, nullptr),
1373 BindLambdaForTesting(add_initial_modules_callback)));
1374 sampling_thread_completed.Wait();
1375 }));
1376
1377 ASSERT_EQ(1, add_initial_modules_invocation_count);
1378
1379 // The sample should have one frame from the context values and one from the
1380 // TestAuxUnwinder.
1381 ASSERT_EQ(1u, profile.samples.size());
1382 const std::vector<Frame>& frames = profile.samples[0];
1383
1384 ASSERT_EQ(2u, frames.size());
1385 EXPECT_EQ(23u, frames[1].instruction_pointer);
1386 EXPECT_EQ(nullptr, frames[1].module);
1387 }
1388
PROFILER_TEST_F(StackSamplingProfilerTest,AddAuxUnwinder_AfterStop)1389 PROFILER_TEST_F(StackSamplingProfilerTest, AddAuxUnwinder_AfterStop) {
1390 SamplingParams params;
1391 params.sampling_interval = TimeDelta::FromMilliseconds(0);
1392 params.samples_per_profile = 1;
1393
1394 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1395
1396 Profile profile;
1397 WithTargetThread(
1398 &scenario,
1399 BindLambdaForTesting(
1400 [&](SamplingProfilerThreadToken target_thread_token) {
1401 WaitableEvent sampling_thread_completed(
1402 WaitableEvent::ResetPolicy::MANUAL,
1403 WaitableEvent::InitialState::NOT_SIGNALED);
1404 StackSamplingProfiler profiler(
1405 target_thread_token, params,
1406 std::make_unique<TestProfileBuilder>(
1407 module_cache(),
1408 BindLambdaForTesting([&profile, &sampling_thread_completed](
1409 Profile result_profile) {
1410 profile = std::move(result_profile);
1411 sampling_thread_completed.Signal();
1412 })),
1413 CreateCoreUnwindersFactoryForTesting(module_cache()));
1414 profiler.Start();
1415 profiler.Stop();
1416 profiler.AddAuxUnwinder(std::make_unique<TestAuxUnwinder>(
1417 Frame(23, nullptr), base::RepeatingClosure()));
1418 sampling_thread_completed.Wait();
1419 }));
1420
1421 // The AuxUnwinder should be accepted without error. It will have no effect
1422 // since the collection has stopped.
1423 }
1424
1425 // Checks that requests to apply metadata to past samples are passed on to the
1426 // profile builder.
PROFILER_TEST_F(StackSamplingProfilerTest,ApplyMetadataToPastSamples_PassedToProfileBuilder)1427 PROFILER_TEST_F(StackSamplingProfilerTest,
1428 ApplyMetadataToPastSamples_PassedToProfileBuilder) {
1429 // Runs the passed closure on the profiler thread after a sample is taken.
1430 class PostSampleInvoker : public StackSamplerTestDelegate {
1431 public:
1432 explicit PostSampleInvoker(RepeatingClosure post_sample_closure)
1433 : post_sample_closure_(std::move(post_sample_closure)) {}
1434
1435 void OnPreStackWalk() override { post_sample_closure_.Run(); }
1436
1437 private:
1438 RepeatingClosure post_sample_closure_;
1439 };
1440
1441 // Thread-safe representation of the times that samples were taken.
1442 class SynchronizedSampleTimes {
1443 public:
1444 void AddNow() {
1445 AutoLock lock(lock_);
1446 times_.push_back(TimeTicks::Now());
1447 }
1448
1449 std::vector<TimeTicks> GetTimes() {
1450 AutoLock lock(lock_);
1451 return times_;
1452 }
1453
1454 private:
1455 Lock lock_;
1456 std::vector<TimeTicks> times_;
1457 };
1458
1459 SamplingParams params;
1460 params.sampling_interval = TimeDelta::FromMilliseconds(10);
1461 // 10,000 samples ensures the profiler continues running until manually
1462 // stopped, after applying metadata.
1463 params.samples_per_profile = 10000;
1464
1465 UnwindScenario scenario(BindRepeating(&CallWithPlainFunction));
1466
1467 std::vector<TimeTicks> sample_times;
1468 Profile profile;
1469 WithTargetThread(
1470 &scenario,
1471 BindLambdaForTesting(
1472 [&](SamplingProfilerThreadToken target_thread_token) {
1473 SynchronizedSampleTimes synchronized_sample_times;
1474 WaitableEvent sample_seen(WaitableEvent::ResetPolicy::AUTOMATIC);
1475 PostSampleInvoker post_sample_invoker(BindLambdaForTesting([&]() {
1476 synchronized_sample_times.AddNow();
1477 sample_seen.Signal();
1478 }));
1479
1480 StackSamplingProfiler profiler(
1481 target_thread_token, params,
1482 std::make_unique<TestProfileBuilder>(
1483 module_cache(),
1484 BindLambdaForTesting([&profile](Profile result_profile) {
1485 profile = std::move(result_profile);
1486 })),
1487 CreateCoreUnwindersFactoryForTesting(module_cache()),
1488 RepeatingClosure(), &post_sample_invoker);
1489 profiler.Start();
1490 // Wait for 5 samples to be collected.
1491 for (int i = 0; i < 5; ++i)
1492 sample_seen.Wait();
1493 sample_times = synchronized_sample_times.GetTimes();
1494 // Record metadata on past samples, with and without a key value.
1495 // The range [times[1], times[3]] is guaranteed to include only
1496 // samples 2 and 3, and likewise [times[2], times[4]] is guaranteed
1497 // to include only samples 3 and 4.
1498 ApplyMetadataToPastSamples(sample_times[1], sample_times[3],
1499 "TestMetadata1", 10);
1500 ApplyMetadataToPastSamples(sample_times[2], sample_times[4],
1501 "TestMetadata2", 100, 11);
1502 profiler.Stop();
1503 }));
1504
1505 ASSERT_EQ(2u, profile.retrospective_metadata.size());
1506
1507 const RetrospectiveMetadata& metadata1 = profile.retrospective_metadata[0];
1508 EXPECT_EQ(sample_times[1], metadata1.period_start);
1509 EXPECT_EQ(sample_times[3], metadata1.period_end);
1510 EXPECT_EQ(HashMetricName("TestMetadata1"), metadata1.item.name_hash);
1511 EXPECT_FALSE(metadata1.item.key.has_value());
1512 EXPECT_EQ(10, metadata1.item.value);
1513
1514 const RetrospectiveMetadata& metadata2 = profile.retrospective_metadata[1];
1515 EXPECT_EQ(sample_times[2], metadata2.period_start);
1516 EXPECT_EQ(sample_times[4], metadata2.period_end);
1517 EXPECT_EQ(HashMetricName("TestMetadata2"), metadata2.item.name_hash);
1518 ASSERT_TRUE(metadata2.item.key.has_value());
1519 EXPECT_EQ(100, *metadata2.item.key);
1520 EXPECT_EQ(11, metadata2.item.value);
1521 }
1522
1523 } // namespace base
1524