mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 1735697 - profiler_is_being_profiled checks for pauses, and can check another thread - r=florian
If the profiler is paused, then really, threads are not *being* profiled. profiler_is_active_and_unpaused() was added, to help with non-MOZ_GECKO_PROFILER builds. (Note: baseprofiler::profiler_thread_is_being_profiled(ProfilerThreadId) is not possible to implement, but it's not needed anyway.) Differential Revision: https://phabricator.services.mozilla.com/D128707
This commit is contained in:
parent
a685378366
commit
8bf5fd4b34
@ -31,6 +31,7 @@
|
||||
namespace mozilla::baseprofiler {
|
||||
|
||||
[[nodiscard]] inline bool profiler_is_active() { return false; }
|
||||
[[nodiscard]] inline bool profiler_is_active_and_unpaused() { return false; }
|
||||
|
||||
} // namespace mozilla::baseprofiler
|
||||
|
||||
@ -309,6 +310,11 @@ MFBT_API bool IsThreadBeingProfiled();
|
||||
return baseprofiler::detail::RacyFeatures::IsActive();
|
||||
}
|
||||
|
||||
// Same as profiler_is_active(), but also checks if the profiler is not paused.
|
||||
[[nodiscard]] inline bool profiler_is_active_and_unpaused() {
|
||||
return baseprofiler::detail::RacyFeatures::IsActiveAndUnpaused();
|
||||
}
|
||||
|
||||
// Same as profiler_is_active(), but with the same extra checks that determine
|
||||
// if the profiler would currently store markers. So this should be used before
|
||||
// doing some potentially-expensive work that's used in a marker. E.g.:
|
||||
@ -320,10 +326,11 @@ MFBT_API bool IsThreadBeingProfiled();
|
||||
return baseprofiler::detail::RacyFeatures::IsActiveAndUnpaused();
|
||||
}
|
||||
|
||||
// Is the profiler active, and is the current thread being profiled?
|
||||
// (Same caveats and recommented usage as profiler_is_active().)
|
||||
// Is the profiler active and unpaused, and is the current thread being
|
||||
// profiled? (Same caveats and recommented usage as profiler_is_active().)
|
||||
[[nodiscard]] inline bool profiler_thread_is_being_profiled() {
|
||||
return profiler_is_active() && baseprofiler::detail::IsThreadBeingProfiled();
|
||||
return baseprofiler::detail::RacyFeatures::IsActiveAndUnpaused() &&
|
||||
baseprofiler::detail::IsThreadBeingProfiled();
|
||||
}
|
||||
|
||||
// Is the profiler active and paused? Returns false if the profiler is inactive.
|
||||
|
@ -4082,6 +4082,8 @@ void TestProfiler() {
|
||||
printf("baseprofiler_pause()...\n");
|
||||
baseprofiler::profiler_pause();
|
||||
|
||||
MOZ_RELEASE_ASSERT(!baseprofiler::profiler_thread_is_being_profiled());
|
||||
|
||||
Maybe<baseprofiler::ProfilerBufferInfo> info =
|
||||
baseprofiler::profiler_get_buffer_info();
|
||||
MOZ_RELEASE_ASSERT(info.isSome());
|
||||
|
@ -163,6 +163,7 @@ using ProfilingStateChangeCallback = std::function<void(ProfilingState)>;
|
||||
#ifndef MOZ_GECKO_PROFILER
|
||||
|
||||
[[nodiscard]] inline bool profiler_is_active() { return false; }
|
||||
[[nodiscard]] inline bool profiler_is_active_and_unpaused() { return false; }
|
||||
[[nodiscard]] inline bool profiler_can_accept_markers() { return false; }
|
||||
[[nodiscard]] inline bool profiler_feature_active(uint32_t aFeature) {
|
||||
return false;
|
||||
@ -301,6 +302,11 @@ class RacyFeatures {
|
||||
return mozilla::profiler::detail::RacyFeatures::IsActive();
|
||||
}
|
||||
|
||||
// Same as profiler_is_active(), but also checks if the profiler is not paused.
|
||||
[[nodiscard]] inline bool profiler_is_active_and_unpaused() {
|
||||
return mozilla::profiler::detail::RacyFeatures::IsActiveAndUnpaused();
|
||||
}
|
||||
|
||||
// Same as profiler_is_active(), but with the same extra checks that determine
|
||||
// if the profiler would currently store markers. So this should be used before
|
||||
// doing some potentially-expensive work that's used in a marker. E.g.:
|
||||
|
@ -22,17 +22,45 @@
|
||||
mozilla::profiler::ThreadRegistration::IsRegistered();
|
||||
}
|
||||
|
||||
// Is the profiler active, and is the current thread being profiled?
|
||||
// (Same caveats and recommented usage as profiler_is_active().)
|
||||
// Is the profiler active and unpaused, and is the current thread being
|
||||
// profiled? (Same caveats and recommented usage as profiler_is_active().)
|
||||
[[nodiscard]] inline bool profiler_thread_is_being_profiled() {
|
||||
return profiler_is_active() &&
|
||||
return profiler_is_active_and_unpaused() &&
|
||||
mozilla::profiler::ThreadRegistration::WithOnThreadRefOr(
|
||||
[](mozilla::profiler::ThreadRegistration::OnThreadRef aTR) {
|
||||
return aTR.UnlockedConstReaderAndAtomicRWCRef()
|
||||
.IsBeingProfiled();
|
||||
},
|
||||
false);
|
||||
;
|
||||
}
|
||||
|
||||
// Is the profiler active and unpaused, and is the given thread being profiled?
|
||||
// (Same caveats and recommented usage as profiler_is_active().)
|
||||
// Safe to use with the current thread id, or unspecified ProfilerThreadId (same
|
||||
// as current thread id).
|
||||
[[nodiscard]] inline bool profiler_thread_is_being_profiled(
|
||||
const ProfilerThreadId& aThreadId) {
|
||||
if (!profiler_is_active_and_unpaused()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aThreadId.IsSpecified() || aThreadId == profiler_current_thread_id()) {
|
||||
// For the current thread id, use the ThreadRegistration directly, it is
|
||||
// more efficient.
|
||||
return mozilla::profiler::ThreadRegistration::WithOnThreadRefOr(
|
||||
[](mozilla::profiler::ThreadRegistration::OnThreadRef aTR) {
|
||||
return aTR.UnlockedConstReaderAndAtomicRWCRef().IsBeingProfiled();
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
// For other threads, go through the ThreadRegistry.
|
||||
return mozilla::profiler::ThreadRegistry::WithOffThreadRefOr(
|
||||
aThreadId,
|
||||
[](mozilla::profiler::ThreadRegistry::OffThreadRef aTR) {
|
||||
return aTR.UnlockedConstReaderAndAtomicRWCRef().IsBeingProfiled();
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
// Is the current thread registered and sleeping?
|
||||
|
@ -1754,17 +1754,87 @@ TEST(GeckoProfiler, GetBacktrace)
|
||||
|
||||
TEST(GeckoProfiler, Pause)
|
||||
{
|
||||
profiler_init_main_thread_id();
|
||||
ASSERT_TRUE(profiler_is_main_thread())
|
||||
<< "This test must run on the main thread";
|
||||
|
||||
uint32_t features = ProfilerFeature::StackWalk;
|
||||
const char* filters[] = {"GeckoMain"};
|
||||
const char* filters[] = {"GeckoMain", "Profiled GeckoProfiler.Pause"};
|
||||
|
||||
ASSERT_TRUE(!profiler_is_paused());
|
||||
ASSERT_TRUE(!profiler_can_accept_markers());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
|
||||
std::thread{[&]() {
|
||||
{
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
{
|
||||
AUTO_PROFILER_REGISTER_THREAD(
|
||||
"Ignored GeckoProfiler.Pause - before start");
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
{
|
||||
AUTO_PROFILER_REGISTER_THREAD(
|
||||
"Profiled GeckoProfiler.Pause - before start");
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
}}.join();
|
||||
|
||||
profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, features,
|
||||
filters, MOZ_ARRAY_LENGTH(filters), 0);
|
||||
|
||||
ASSERT_TRUE(!profiler_is_paused());
|
||||
ASSERT_TRUE(profiler_can_accept_markers());
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
|
||||
std::thread{[&]() {
|
||||
{
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
{
|
||||
AUTO_PROFILER_REGISTER_THREAD(
|
||||
"Ignored GeckoProfiler.Pause - after start");
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
{
|
||||
AUTO_PROFILER_REGISTER_THREAD(
|
||||
"Profiled GeckoProfiler.Pause - after start");
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
}}.join();
|
||||
|
||||
// Check that we are writing samples while not paused.
|
||||
Maybe<ProfilerBufferInfo> info1 = profiler_get_buffer_info();
|
||||
@ -1782,6 +1852,40 @@ TEST(GeckoProfiler, Pause)
|
||||
|
||||
ASSERT_TRUE(profiler_is_paused());
|
||||
ASSERT_TRUE(!profiler_can_accept_markers());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
|
||||
std::thread{[&]() {
|
||||
{
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
{
|
||||
AUTO_PROFILER_REGISTER_THREAD(
|
||||
"Ignored GeckoProfiler.Pause - after pause");
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
{
|
||||
AUTO_PROFILER_REGISTER_THREAD(
|
||||
"Profiled GeckoProfiler.Pause - after pause");
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
}}.join();
|
||||
|
||||
// Check that we are not writing samples while paused.
|
||||
info1 = profiler_get_buffer_info();
|
||||
@ -1802,11 +1906,75 @@ TEST(GeckoProfiler, Pause)
|
||||
|
||||
ASSERT_TRUE(!profiler_is_paused());
|
||||
ASSERT_TRUE(profiler_can_accept_markers());
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
|
||||
std::thread{[&]() {
|
||||
{
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
{
|
||||
AUTO_PROFILER_REGISTER_THREAD(
|
||||
"Ignored GeckoProfiler.Pause - after resume");
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
{
|
||||
AUTO_PROFILER_REGISTER_THREAD(
|
||||
"Profiled GeckoProfiler.Pause - after resume");
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
}}.join();
|
||||
|
||||
profiler_stop();
|
||||
|
||||
ASSERT_TRUE(!profiler_is_paused());
|
||||
ASSERT_TRUE(!profiler_can_accept_markers());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
|
||||
std::thread{[&]() {
|
||||
{
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
{
|
||||
AUTO_PROFILER_REGISTER_THREAD("Ignored GeckoProfiler.Pause - after stop");
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
{
|
||||
AUTO_PROFILER_REGISTER_THREAD(
|
||||
"Profiled GeckoProfiler.Pause - after stop");
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled());
|
||||
ASSERT_TRUE(!profiler_thread_is_being_profiled(ProfilerThreadId{}));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_current_thread_id()));
|
||||
ASSERT_TRUE(
|
||||
!profiler_thread_is_being_profiled(profiler_main_thread_id()));
|
||||
}
|
||||
}}.join();
|
||||
}
|
||||
|
||||
TEST(GeckoProfiler, Markers)
|
||||
|
Loading…
Reference in New Issue
Block a user