author | Markus Stange <mstange@themasta.com> |
Tue, 30 May 2017 17:48:19 -0400 | |
changeset 361504 | c9669890cf99c9db2374cf81055c19cb42e382c4 |
parent 361503 | ac273d41a04478e7d380010cd1d1cab98d29a45c |
child 361505 | bb9f906e70e30d56c386717ee9a45b7d3c774573 |
push id | 90875 |
push user | cbook@mozilla.com |
push date | Wed, 31 May 2017 12:23:54 +0000 |
treeherder | mozilla-inbound@7061759a0b57 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | njn |
bugs | 1330184 |
milestone | 55.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/tools/profiler/tests/gtest/GeckoProfiler.cpp +++ b/tools/profiler/tests/gtest/GeckoProfiler.cpp @@ -12,16 +12,18 @@ #include "gtest/gtest.h" #include "GeckoProfiler.h" #include "ProfilerMarkerPayload.h" #include "jsapi.h" #include "js/Initialization.h" #include "mozilla/UniquePtrExtensions.h" #include "ProfileJSONWriter.h" +#include "nsIThread.h" +#include "nsThreadUtils.h" #include <string.h> // Note: profiler_init() has already been called in XRE_main(), so we can't // test it here. Likewise for profiler_shutdown(), and GeckoProfilerInitRAII // (which is just an RAII wrapper for profiler_init() and profiler_shutdown()). using namespace mozilla; @@ -163,16 +165,79 @@ TEST(GeckoProfiler, FeaturesAndParams) // These calls are no-ops. profiler_stop(); profiler_stop(); InactiveFeaturesAndParamsCheck(); } } +TEST(GeckoProfiler, DifferentThreads) +{ + InactiveFeaturesAndParamsCheck(); + + nsCOMPtr<nsIThread> thread; + nsresult rv = NS_NewNamedThread("GeckoProfGTest", getter_AddRefs(thread)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + // Control the profiler on a background thread and verify flags on the + // main thread. + { + uint32_t features = ProfilerFeature::JS | ProfilerFeature::Threads; + const char* filters[] = { "GeckoMain", "Compositor" }; + + thread->Dispatch(NS_NewRunnableFunction([&]() { + profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, + features, filters, MOZ_ARRAY_LENGTH(filters)); + }), NS_DISPATCH_SYNC); + + ASSERT_TRUE(profiler_is_active()); + ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::GPU)); + ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::Privacy)); + ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::Restyle)); + + ActiveParamsCheck(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, + features, filters, MOZ_ARRAY_LENGTH(filters)); + + thread->Dispatch(NS_NewRunnableFunction([&]() { + profiler_stop(); + }), NS_DISPATCH_SYNC); + + InactiveFeaturesAndParamsCheck(); + } + + // Control the profiler on the main thread and verify flags on a + // background thread. + { + uint32_t features = ProfilerFeature::JS | ProfilerFeature::Threads; + const char* filters[] = { "GeckoMain", "Compositor" }; + + profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, + features, filters, MOZ_ARRAY_LENGTH(filters)); + + thread->Dispatch(NS_NewRunnableFunction([&]() { + ASSERT_TRUE(profiler_is_active()); + ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::GPU)); + ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::Privacy)); + ASSERT_TRUE(!profiler_feature_active(ProfilerFeature::Restyle)); + + ActiveParamsCheck(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, + features, filters, MOZ_ARRAY_LENGTH(filters)); + }), NS_DISPATCH_SYNC); + + profiler_stop(); + + thread->Dispatch(NS_NewRunnableFunction([&]() { + InactiveFeaturesAndParamsCheck(); + }), NS_DISPATCH_SYNC); + } + + thread->Shutdown(); +} + TEST(GeckoProfiler, GetBacktrace) { ASSERT_TRUE(!profiler_get_backtrace()); { uint32_t features = ProfilerFeature::StackWalk; const char* filters[] = { "GeckoMain" }; @@ -347,16 +412,55 @@ TEST(GeckoProfiler, StreamJSONForThisPro UniquePtr<char[]> profile = w.WriteFunc()->CopyData(); ASSERT_TRUE(profile && profile[0] == '{'); profiler_stop(); ASSERT_TRUE(!profiler_stream_json_for_this_process(w)); } +TEST(GeckoProfiler, StreamJSONForThisProcessThreaded) +{ + // Same as the previous test, but calling some things on background threads. + nsCOMPtr<nsIThread> thread; + nsresult rv = NS_NewNamedThread("GeckoProfGTest", getter_AddRefs(thread)); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + uint32_t features = ProfilerFeature::StackWalk; + const char* filters[] = { "GeckoMain" }; + + SpliceableChunkedJSONWriter w; + ASSERT_TRUE(!profiler_stream_json_for_this_process(w)); + + // Start the profiler on the main thread. + profiler_start(PROFILER_DEFAULT_ENTRIES, PROFILER_DEFAULT_INTERVAL, + features, filters, MOZ_ARRAY_LENGTH(filters)); + + // Call profiler_stream_json_for_this_process on a background thread. + thread->Dispatch(NS_NewRunnableFunction([&]() { + w.Start(SpliceableJSONWriter::SingleLineStyle); + ASSERT_TRUE(profiler_stream_json_for_this_process(w)); + w.End(); + }), NS_DISPATCH_SYNC); + + UniquePtr<char[]> profile = w.WriteFunc()->CopyData(); + ASSERT_TRUE(profile && profile[0] == '{'); + + // Stop the profiler and call profiler_stream_json_for_this_process on a + // background thread. + thread->Dispatch(NS_NewRunnableFunction([&]() { + profiler_stop(); + ASSERT_TRUE(!profiler_stream_json_for_this_process(w)); + }), NS_DISPATCH_SYNC); + thread->Shutdown(); + + // Call profiler_stream_json_for_this_process on the main thread. + ASSERT_TRUE(!profiler_stream_json_for_this_process(w)); +} + TEST(GeckoProfiler, PseudoStack) { uint32_t features = ProfilerFeature::StackWalk; const char* filters[] = { "GeckoMain" }; PROFILER_LABEL("A", "B", js::ProfileEntry::Category::OTHER); PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);