Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(238)

Side by Side Diff: base/profiler/stack_sampling_profiler_unittest.cc

Issue 2554123002: Support parallel captures from the StackSamplingProfiler. (Closed)
Patch Set: addressed review comments by wittman Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/profiler/stack_sampling_profiler.cc ('k') | base/threading/thread_restrictions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stddef.h> 5 #include <stddef.h>
6 #include <stdint.h> 6 #include <stdint.h>
7 7
8 #include <cstdlib> 8 #include <cstdlib>
9 #include <memory> 9 #include <memory>
10 #include <utility> 10 #include <utility>
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 // asynchronous library loading has completed before walking the stack. If 437 // asynchronous library loading has completed before walking the stack. If
438 // false, the unloading may still be occurring during the stack walk. 438 // false, the unloading may still be occurring during the stack walk.
439 void TestLibraryUnload(bool wait_until_unloaded) { 439 void TestLibraryUnload(bool wait_until_unloaded) {
440 // Test delegate that supports intervening between the copying of the stack 440 // Test delegate that supports intervening between the copying of the stack
441 // and the walking of the stack. 441 // and the walking of the stack.
442 class StackCopiedSignaler : public NativeStackSamplerTestDelegate { 442 class StackCopiedSignaler : public NativeStackSamplerTestDelegate {
443 public: 443 public:
444 StackCopiedSignaler(WaitableEvent* stack_copied, 444 StackCopiedSignaler(WaitableEvent* stack_copied,
445 WaitableEvent* start_stack_walk, 445 WaitableEvent* start_stack_walk,
446 bool wait_to_walk_stack) 446 bool wait_to_walk_stack)
447 : stack_copied_(stack_copied), start_stack_walk_(start_stack_walk), 447 : stack_copied_(stack_copied),
448 wait_to_walk_stack_(wait_to_walk_stack) { 448 start_stack_walk_(start_stack_walk),
449 } 449 wait_to_walk_stack_(wait_to_walk_stack) {}
450 450
451 void OnPreStackWalk() override { 451 void OnPreStackWalk() override {
452 stack_copied_->Signal(); 452 stack_copied_->Signal();
453 if (wait_to_walk_stack_) 453 if (wait_to_walk_stack_)
454 start_stack_walk_->Wait(); 454 start_stack_walk_->Wait();
455 } 455 }
456 456
457 private: 457 private:
458 WaitableEvent* const stack_copied_; 458 WaitableEvent* const stack_copied_;
459 WaitableEvent* const start_stack_walk_; 459 WaitableEvent* const start_stack_walk_;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 sample, &TargetThread::SignalAndWaitUntilSignaled); 616 sample, &TargetThread::SignalAndWaitUntilSignaled);
617 ASSERT_TRUE(loc != sample.frames.end()) 617 ASSERT_TRUE(loc != sample.frames.end())
618 << "Function at " 618 << "Function at "
619 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>( 619 << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
620 &TargetThread::SignalAndWaitUntilSignaled)) 620 &TargetThread::SignalAndWaitUntilSignaled))
621 << " was not found in stack:\n" 621 << " was not found in stack:\n"
622 << FormatSampleForDiagnosticOutput(sample, profile.modules); 622 << FormatSampleForDiagnosticOutput(sample, profile.modules);
623 FilePath executable_path; 623 FilePath executable_path;
624 EXPECT_TRUE(PathService::Get(FILE_EXE, &executable_path)); 624 EXPECT_TRUE(PathService::Get(FILE_EXE, &executable_path));
625 EXPECT_EQ(executable_path, profile.modules[loc->module_index].filename); 625 EXPECT_EQ(executable_path, profile.modules[loc->module_index].filename);
626
627 // Ensure the sampling thread is still running at this point.
628 ASSERT_TRUE(StackSamplingProfiler::IsSamplingThreadRunningForTesting());
629
630 // Shutdown the sampler as though the process were about to exit.
631 StackSamplingProfiler::Shutdown();
632 EXPECT_FALSE(StackSamplingProfiler::IsSamplingThreadRunningForTesting());
633
634 // Shutdown is a permanent thing in general but this needs to be undone so
635 // other tests can run.
636 StackSamplingProfiler::UndoShutdownForTesting();
637 EXPECT_FALSE(StackSamplingProfiler::IsSamplingThreadRunningForTesting());
626 } 638 }
627 639
628 // Checks that annotations are recorded in samples. 640 // Checks that annotations are recorded in samples.
629 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) 641 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
630 #define MAYBE_Annotations Annotations 642 #define MAYBE_Annotations Annotations
631 #else 643 #else
632 #define MAYBE_Annotations DISABLED_Annotations 644 #define MAYBE_Annotations DISABLED_Annotations
633 #endif 645 #endif
634 TEST(StackSamplingProfilerTest, MAYBE_Annotations) { 646 TEST(StackSamplingProfilerTest, MAYBE_Annotations) {
635 StackSamplingProfiler::ResetAnnotationsForTesting(); 647 StackSamplingProfiler::ResetAnnotationsForTesting();
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 reinterpret_cast<const void*>(&TargetThread::CallWithAlloca)) 725 reinterpret_cast<const void*>(&TargetThread::CallWithAlloca))
714 << " was not found in stack:\n" 726 << " was not found in stack:\n"
715 << FormatSampleForDiagnosticOutput(sample, profile.modules); 727 << FormatSampleForDiagnosticOutput(sample, profile.modules);
716 728
717 // These frames should be adjacent on the stack. 729 // These frames should be adjacent on the stack.
718 EXPECT_EQ(1, alloca_frame - end_frame) 730 EXPECT_EQ(1, alloca_frame - end_frame)
719 << "Stack:\n" 731 << "Stack:\n"
720 << FormatSampleForDiagnosticOutput(sample, profile.modules); 732 << FormatSampleForDiagnosticOutput(sample, profile.modules);
721 } 733 }
722 734
723 // Checks that the fire-and-forget interface works.
724 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
725 #define MAYBE_StartAndRunAsync StartAndRunAsync
726 #else
727 #define MAYBE_StartAndRunAsync DISABLED_StartAndRunAsync
728 #endif
729 TEST(StackSamplingProfilerTest, MAYBE_StartAndRunAsync) {
730 // StartAndRunAsync requires the caller to have a message loop.
731 MessageLoop message_loop;
732
733 SamplingParams params;
734 params.samples_per_burst = 1;
735
736 CallStackProfiles profiles;
737 WithTargetThread([&params, &profiles](PlatformThreadId target_thread_id) {
738 WaitableEvent sampling_thread_completed(
739 WaitableEvent::ResetPolicy::AUTOMATIC,
740 WaitableEvent::InitialState::NOT_SIGNALED);
741 const StackSamplingProfiler::CompletedCallback callback =
742 Bind(&SaveProfilesAndSignalEvent, Unretained(&profiles),
743 Unretained(&sampling_thread_completed));
744 StackSamplingProfiler::StartAndRunAsync(target_thread_id, params, callback);
745 RunLoop().RunUntilIdle();
746 sampling_thread_completed.Wait();
747 });
748
749 ASSERT_EQ(1u, profiles.size());
750 }
751
752 // Checks that the expected number of profiles and samples are present in the 735 // Checks that the expected number of profiles and samples are present in the
753 // call stack profiles produced. 736 // call stack profiles produced.
754 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) 737 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
755 #define MAYBE_MultipleProfilesAndSamples MultipleProfilesAndSamples 738 #define MAYBE_MultipleProfilesAndSamples MultipleProfilesAndSamples
756 #else 739 #else
757 #define MAYBE_MultipleProfilesAndSamples DISABLED_MultipleProfilesAndSamples 740 #define MAYBE_MultipleProfilesAndSamples DISABLED_MultipleProfilesAndSamples
758 #endif 741 #endif
759 TEST(StackSamplingProfilerTest, MAYBE_MultipleProfilesAndSamples) { 742 TEST(StackSamplingProfilerTest, MAYBE_MultipleProfilesAndSamples) {
760 SamplingParams params; 743 SamplingParams params;
761 params.burst_interval = params.sampling_interval = 744 params.burst_interval = params.sampling_interval =
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 }); 836 });
854 } 837 }
855 838
856 // Checks that the same profiler may be run multiple times. 839 // Checks that the same profiler may be run multiple times.
857 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) 840 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
858 #define MAYBE_CanRunMultipleTimes CanRunMultipleTimes 841 #define MAYBE_CanRunMultipleTimes CanRunMultipleTimes
859 #else 842 #else
860 #define MAYBE_CanRunMultipleTimes DISABLED_CanRunMultipleTimes 843 #define MAYBE_CanRunMultipleTimes DISABLED_CanRunMultipleTimes
861 #endif 844 #endif
862 TEST(StackSamplingProfilerTest, MAYBE_CanRunMultipleTimes) { 845 TEST(StackSamplingProfilerTest, MAYBE_CanRunMultipleTimes) {
846 StackSamplingProfiler::SetSamplingThreadIdleShutdownTimeForTesting(0);
847
863 SamplingParams params; 848 SamplingParams params;
864 params.sampling_interval = TimeDelta::FromMilliseconds(0); 849 params.sampling_interval = TimeDelta::FromMilliseconds(0);
865 params.samples_per_burst = 1; 850 params.samples_per_burst = 1;
866 851
867 std::vector<CallStackProfile> profiles; 852 std::vector<CallStackProfile> profiles;
868 CaptureProfiles(params, AVeryLongTimeDelta(), &profiles); 853 CaptureProfiles(params, AVeryLongTimeDelta(), &profiles);
869 ASSERT_EQ(1u, profiles.size()); 854 ASSERT_EQ(1u, profiles.size());
870 855
871 profiles.clear(); 856 profiles.clear();
872 CaptureProfiles(params, AVeryLongTimeDelta(), &profiles); 857 CaptureProfiles(params, AVeryLongTimeDelta(), &profiles);
873 ASSERT_EQ(1u, profiles.size()); 858 ASSERT_EQ(1u, profiles.size());
859
860 // Capture thread should still be running at this point.
861 ASSERT_TRUE(StackSamplingProfiler::IsSamplingThreadRunningForTesting());
862
863 // Initiate an "idle" shutdown. The task will be run immediately but on
864 // another thread so wait for it to complete.
865 StackSamplingProfiler::InitiateSamplingThreadIdleShutdownForTesting();
866 while (StackSamplingProfiler::IsSamplingThreadRunningForTesting())
867 PlatformThread::YieldCurrentThread();
868
869 // Ensure another capture will start the sampling thread and run.
870 profiles.clear();
871 CaptureProfiles(params, AVeryLongTimeDelta(), &profiles);
872 ASSERT_EQ(1u, profiles.size());
873 EXPECT_TRUE(StackSamplingProfiler::IsSamplingThreadRunningForTesting());
874 } 874 }
875 875
876 // Checks that requests to start profiling while another profile is taking place 876 // Checks that multiple sampling requests execute in parallel.
877 // are ignored.
878 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) 877 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
879 #define MAYBE_ConcurrentProfiling ConcurrentProfiling 878 #define MAYBE_ConcurrentProfiling ConcurrentProfiling
880 #else 879 #else
881 #define MAYBE_ConcurrentProfiling DISABLED_ConcurrentProfiling 880 #define MAYBE_ConcurrentProfiling DISABLED_ConcurrentProfiling
882 #endif 881 #endif
883 TEST(StackSamplingProfilerTest, MAYBE_ConcurrentProfiling) { 882 TEST(StackSamplingProfilerTest, MAYBE_ConcurrentProfiling) {
884 WithTargetThread([](PlatformThreadId target_thread_id) { 883 WithTargetThread([](PlatformThreadId target_thread_id) {
885 SamplingParams params[2]; 884 SamplingParams params[2];
886 params[0].initial_delay = TimeDelta::FromMilliseconds(10); 885 params[0].initial_delay = TimeDelta::FromMilliseconds(10);
887 params[0].sampling_interval = TimeDelta::FromMilliseconds(0); 886 params[0].sampling_interval = TimeDelta::FromMilliseconds(1);
888 params[0].samples_per_burst = 1; 887 params[0].samples_per_burst = 10;
889 888
890 params[1].sampling_interval = TimeDelta::FromMilliseconds(0); 889 params[0].initial_delay = TimeDelta::FromMilliseconds(10);
891 params[1].samples_per_burst = 1; 890 params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
891 params[1].samples_per_burst = 10;
892 892
893 CallStackProfiles profiles[2]; 893 CallStackProfiles profiles[2];
894 std::vector<std::unique_ptr<WaitableEvent>> sampling_completed(2); 894 std::vector<std::unique_ptr<WaitableEvent>> sampling_completed(2);
895 std::vector<std::unique_ptr<StackSamplingProfiler>> profiler(2); 895 std::vector<std::unique_ptr<StackSamplingProfiler>> profiler(2);
896 for (int i = 0; i < 2; ++i) { 896 for (int i = 0; i < 2; ++i) {
897 sampling_completed[i] = 897 sampling_completed[i] =
898 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::AUTOMATIC, 898 MakeUnique<WaitableEvent>(WaitableEvent::ResetPolicy::AUTOMATIC,
899 WaitableEvent::InitialState::NOT_SIGNALED); 899 WaitableEvent::InitialState::NOT_SIGNALED);
900 const StackSamplingProfiler::CompletedCallback callback = 900 const StackSamplingProfiler::CompletedCallback callback =
901 Bind(&SaveProfilesAndSignalEvent, Unretained(&profiles[i]), 901 Bind(&SaveProfilesAndSignalEvent, Unretained(&profiles[i]),
(...skipping 10 matching lines...) Expand all
912 std::transform( 912 std::transform(
913 sampling_completed.begin(), sampling_completed.end(), 913 sampling_completed.begin(), sampling_completed.end(),
914 sampling_completed_rawptrs.begin(), 914 sampling_completed_rawptrs.begin(),
915 [](const std::unique_ptr<WaitableEvent>& elem) { return elem.get(); }); 915 [](const std::unique_ptr<WaitableEvent>& elem) { return elem.get(); });
916 // Wait for one profiler to finish. 916 // Wait for one profiler to finish.
917 size_t completed_profiler = 917 size_t completed_profiler =
918 WaitableEvent::WaitMany(sampling_completed_rawptrs.data(), 2); 918 WaitableEvent::WaitMany(sampling_completed_rawptrs.data(), 2);
919 EXPECT_EQ(1u, profiles[completed_profiler].size()); 919 EXPECT_EQ(1u, profiles[completed_profiler].size());
920 920
921 size_t other_profiler = 1 - completed_profiler; 921 size_t other_profiler = 1 - completed_profiler;
922 // Give the other profiler a chance to run and observe that it hasn't. 922 // Give the other profiler a chance to finish and verify it does so.
923 EXPECT_FALSE(sampling_completed[other_profiler]->TimedWait( 923 EXPECT_TRUE(sampling_completed[other_profiler]->TimedWait(
924 TimeDelta::FromMilliseconds(25))); 924 TimeDelta::FromMilliseconds(250)));
925
926 // Start the other profiler again and it should run.
927 profiler[other_profiler]->Start();
928 sampling_completed[other_profiler]->Wait();
929 EXPECT_EQ(1u, profiles[other_profiler].size());
930 }); 925 });
931 } 926 }
932 927
933 // Checks that a stack that runs through another library produces a stack with 928 // Checks that a stack that runs through another library produces a stack with
934 // the expected functions. 929 // the expected functions.
935 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) 930 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
936 #define MAYBE_OtherLibrary OtherLibrary 931 #define MAYBE_OtherLibrary OtherLibrary
937 #else 932 #else
938 #define MAYBE_OtherLibrary DISABLED_OtherLibrary 933 #define MAYBE_OtherLibrary DISABLED_OtherLibrary
939 #endif 934 #endif
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1017 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED) 1012 #if defined(STACK_SAMPLING_PROFILER_SUPPORTED)
1018 #define MAYBE_UnloadedLibrary UnloadedLibrary 1013 #define MAYBE_UnloadedLibrary UnloadedLibrary
1019 #else 1014 #else
1020 #define MAYBE_UnloadedLibrary DISABLED_UnloadedLibrary 1015 #define MAYBE_UnloadedLibrary DISABLED_UnloadedLibrary
1021 #endif 1016 #endif
1022 TEST(StackSamplingProfilerTest, MAYBE_UnloadedLibrary) { 1017 TEST(StackSamplingProfilerTest, MAYBE_UnloadedLibrary) {
1023 TestLibraryUnload(true); 1018 TestLibraryUnload(true);
1024 } 1019 }
1025 1020
1026 } // namespace base 1021 } // namespace base
OLDNEW
« no previous file with comments | « base/profiler/stack_sampling_profiler.cc ('k') | base/threading/thread_restrictions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698