Commit d54e5abb authored by Lloyd Pique's avatar Lloyd Pique Committed by Commit Bot

arc: Switch graphics tracing tool to use ARC_VSYNC

For displaying the vsync lines in the tool, we need the ideal vsync
timestamps. The tool was using the timestamps of the HW_VSYNC_0 events,
but this could be off and very jittery by several tenths of a
millisecond from the vsync event time just because those events are
written out by SurfaceFlinger when responding to the hardware composer
vsync callback.

The hardware composer vsync callback includes the actual vsync timestamp
as an argument, but this is not included in the existing event trace in
any way.

I went and added a new ARC_VSYNC event which includes the actual vsync
timestamp in the profile data, where it is stored in the string after
the event name. Reading this event and parsing out the actual timestamp
is much more accurate.

Switching the tracing tool to using the event means that the vsync lines
will be rendered with a consistent spacing, and represent the actual
vsync times now, instead of lagging behind by some variable amount.

Specifically this change

1) Modifies arc_tracing_event_matcher to allow for a prefix match, and
   not just an exact name match. Since the timestamp is part of the name
   string and is variable, a prefix match was required to match these
   events.
2) A unit test was added to cover the new matching behavior, and in
   implementing it I went ahead and added move constructors/assignment
   to ArcTracingEvent for convenience
3) Removes "disabled-by-default-android hal" from the trace options when
   the tool is used. It turned out this was including some events from
   HIDL ("HIDL::IComposerCallback::onVsync::passthrough"), which were
   emitted using atrace_begin/atrace_end, however which could actually
   execute on separate threads and break an assumption in the tracing
   tool that they were emitted by the same thread. Perhaps the Android
   HAL generator code could be adjusted to use atrace_async_begin and
   atrace_async_end instead, but since we do not seem to need the HAL
   events, it was easier to just disable their capture.
4) Switches the tracing model to look for the ARC_VSYNC events instead
   of the HW_VSYNC_0 events, including reading the timestamp out of the
   name string instead of using the misleading event timestamp.

BUG=b:132641796
TEST=unit_tests --gtest_filter=ArcTracingEventMatcherTest*
TEST=chrome://arc-graphics-tracing

Change-Id: I887a573c74035d783b918ca69c3dbb47fc1e5920
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1811936
Auto-Submit: Lloyd Pique <lpique@chromium.org>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarYury Khmel <khmel@chromium.org>
Commit-Queue: Lloyd Pique <lpique@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702301}
parent 794a2f14
...@@ -2477,6 +2477,7 @@ source_set("unit_tests") { ...@@ -2477,6 +2477,7 @@ source_set("unit_tests") {
"arc/tracing/arc_graphics_jank_detector_unittest.cc", "arc/tracing/arc_graphics_jank_detector_unittest.cc",
"arc/tracing/arc_system_model_unittest.cc", "arc/tracing/arc_system_model_unittest.cc",
"arc/tracing/arc_system_stat_collector_unittest.cc", "arc/tracing/arc_system_stat_collector_unittest.cc",
"arc/tracing/arc_tracing_event_matcher_unittest.cc",
"arc/tracing/arc_tracing_model_unittest.cc", "arc/tracing/arc_tracing_model_unittest.cc",
"arc/tracing/arc_value_event_unittest.cc", "arc/tracing/arc_value_event_unittest.cc",
"arc/tts/arc_tts_service_unittest.cc", "arc/tts/arc_tts_service_unittest.cc",
......
...@@ -65,6 +65,10 @@ ArcTracingEvent::ArcTracingEvent(base::Value dictionary) ...@@ -65,6 +65,10 @@ ArcTracingEvent::ArcTracingEvent(base::Value dictionary)
ArcTracingEvent::~ArcTracingEvent() = default; ArcTracingEvent::~ArcTracingEvent() = default;
ArcTracingEvent::ArcTracingEvent(ArcTracingEvent&&) = default;
ArcTracingEvent& ArcTracingEvent::operator=(ArcTracingEvent&&) = default;
int ArcTracingEvent::GetPid() const { int ArcTracingEvent::GetPid() const {
return GetIntegerFromDictionary(GetDictionary(), kKeyPid, return GetIntegerFromDictionary(GetDictionary(), kKeyPid,
0 /* default_value */); 0 /* default_value */);
......
...@@ -32,6 +32,9 @@ class ArcTracingEvent { ...@@ -32,6 +32,9 @@ class ArcTracingEvent {
explicit ArcTracingEvent(base::Value dictionary); explicit ArcTracingEvent(base::Value dictionary);
~ArcTracingEvent(); ~ArcTracingEvent();
ArcTracingEvent(ArcTracingEvent&&);
ArcTracingEvent& operator=(ArcTracingEvent&&);
// Gets process id of the event. Returns 0 if not set. // Gets process id of the event. Returns 0 if not set.
int GetPid() const; int GetPid() const;
// Sets process id of the event. // Sets process id of the event.
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "chrome/browser/chromeos/arc/tracing/arc_tracing_event_matcher.h" #include "chrome/browser/chromeos/arc/tracing/arc_tracing_event_matcher.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "chrome/browser/chromeos/arc/tracing/arc_tracing_event.h" #include "chrome/browser/chromeos/arc/tracing/arc_tracing_event.h"
...@@ -18,17 +19,22 @@ ArcTracingEventMatcher::ArcTracingEventMatcher(const std::string& data) { ...@@ -18,17 +19,22 @@ ArcTracingEventMatcher::ArcTracingEventMatcher(const std::string& data) {
name_ = data.substr(position + 1); name_ = data.substr(position + 1);
DCHECK(!category_.empty()); DCHECK(!category_.empty());
position = name_.find('('); position = name_.find('(');
if (position == std::string::npos) if (position != std::string::npos) {
return; DCHECK_EQ(')', name_.back());
for (const std::string& arg : base::SplitString(
name_.substr(position + 1, name_.length() - position - 2), ";",
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
std::string::size_type separator = arg.find('=');
args_[arg.substr(0, separator)] = arg.substr(separator + 1);
}
name_ = name_.substr(0, position);
}
DCHECK_EQ(')', name_.back()); // If name_ ends with a '*', use a prefix match
for (const std::string& arg : base::SplitString( if (!name_.empty() && name_.back() == '*') {
name_.substr(position + 1, name_.length() - position - 2), ";", name_.pop_back();
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { name_prefix_match_ = true;
std::string::size_type separator = arg.find('=');
args_[arg.substr(0, separator)] = arg.substr(separator + 1);
} }
name_ = name_.substr(0, position);
} }
ArcTracingEventMatcher& ArcTracingEventMatcher::SetPhase(char phase) { ArcTracingEventMatcher& ArcTracingEventMatcher::SetPhase(char phase) {
...@@ -60,7 +66,9 @@ bool ArcTracingEventMatcher::Match(const ArcTracingEvent& event) const { ...@@ -60,7 +66,9 @@ bool ArcTracingEventMatcher::Match(const ArcTracingEvent& event) const {
return false; return false;
if (!category_.empty() && event.GetCategory() != category_) if (!category_.empty() && event.GetCategory() != category_)
return false; return false;
if (!name_.empty() && event.GetName() != name_) if (!name_.empty() && !name_prefix_match_ && event.GetName() != name_)
return false;
if (name_prefix_match_ && (event.GetName().find(name_) != 0))
return false; return false;
for (const auto& arg : args_) { for (const auto& arg : args_) {
if (event.GetArgAsString(arg.first, std::string() /* default_value */) != if (event.GetArgAsString(arg.first, std::string() /* default_value */) !=
...@@ -71,4 +79,16 @@ bool ArcTracingEventMatcher::Match(const ArcTracingEvent& event) const { ...@@ -71,4 +79,16 @@ bool ArcTracingEventMatcher::Match(const ArcTracingEvent& event) const {
return true; return true;
} }
base::Optional<int64_t> ArcTracingEventMatcher::ReadAndroidEventInt64(
const ArcTracingEvent& event) const {
if (!name_prefix_match_ || (event.GetName().find(name_) != 0))
return base::nullopt;
int64_t value = 0;
if (!base::StringToInt64(event.GetName().data() + name_.size(), &value))
return base::nullopt;
return base::make_optional(value);
}
} // namespace arc } // namespace arc
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <string> #include <string>
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h"
namespace arc { namespace arc {
...@@ -20,14 +21,19 @@ class ArcTracingEvent; ...@@ -20,14 +21,19 @@ class ArcTracingEvent;
class ArcTracingEventMatcher { class ArcTracingEventMatcher {
public: public:
ArcTracingEventMatcher(); ArcTracingEventMatcher();
// Format category:name(arg_name=arg_value;..) For example: // Format category:name[*]?(arg_name=arg_value;..)
// For example:
// exo:Surface::Attach // exo:Surface::Attach
// exo:Surface::Attach(buffer_id=0x7f9f5110690) // exo:Surface::Attach(buffer_id=0x7f9f5110690)
// android:HW_VSYNC_0|*
explicit ArcTracingEventMatcher(const std::string& data); explicit ArcTracingEventMatcher(const std::string& data);
// Returns true in case |event| matches criteria set. // Returns true in case |event| matches criteria set.
bool Match(const ArcTracingEvent& event) const; bool Match(const ArcTracingEvent& event) const;
base::Optional<int64_t> ReadAndroidEventInt64(
const ArcTracingEvent& event) const;
// Sets the expected phase. Tested event does not match if its phase does not // Sets the expected phase. Tested event does not match if its phase does not
// match |phase|. This is an optional criteria. // match |phase|. This is an optional criteria.
ArcTracingEventMatcher& SetPhase(char phase); ArcTracingEventMatcher& SetPhase(char phase);
...@@ -50,6 +56,8 @@ class ArcTracingEventMatcher { ...@@ -50,6 +56,8 @@ class ArcTracingEventMatcher {
std::string category_; std::string category_;
// Defines the name to match. // Defines the name to match.
std::string name_; std::string name_;
// If true, name_ is a prefix to match instead of the entire string.
bool name_prefix_match_ = false;
// Defines set of arguments to match if needed. // Defines set of arguments to match if needed.
std::map<std::string, std::string> args_; std::map<std::string, std::string> args_;
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/arc/tracing/arc_tracing_event_matcher.h"
#include "base/json/json_reader.h"
#include "chrome/browser/chromeos/arc/tracing/arc_tracing_event.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace arc {
namespace {
ArcTracingEvent MakeEvent(const char* json_str) {
return ArcTracingEvent(base::JSONReader::Read(json_str).value());
}
} // namespace
using ArcTracingEventMatcherTest = testing::Test;
TEST_F(ArcTracingEventMatcherTest, CategoryNameMatch) {
ArcTracingEventMatcher matcher("exo:Surface::Attach");
EXPECT_TRUE(
matcher.Match(MakeEvent(R"({"cat":"exo","name":"Surface::Attach"})")));
EXPECT_FALSE(
matcher.Match(MakeEvent(R"({"cat":"exo","name":"Surface::Attac"})")));
EXPECT_FALSE(
matcher.Match(MakeEvent(R"({"cat":"exo","name":"Surface::AttacH"})")));
EXPECT_FALSE(
matcher.Match(MakeEvent(R"({"cat":"exo","name":"Surface::Attach2"})")));
EXPECT_FALSE(matcher.Match(
MakeEvent(R"({"cat":"android","name":"Surface::Attach"})")));
}
TEST_F(ArcTracingEventMatcherTest, CategoryNamePrefixMatch) {
ArcTracingEventMatcher matcher("android:ARC_VSYNC|*");
EXPECT_FALSE(
matcher.Match(MakeEvent(R"({"cat":"android","name":"ARC_VSYNC"})")));
EXPECT_TRUE(
matcher.Match(MakeEvent(R"({"cat":"android","name":"ARC_VSYNC|"})")));
EXPECT_TRUE(
matcher.Match(MakeEvent(R"({"cat":"android","name":"ARC_VSYNC|123"})")));
EXPECT_TRUE(
matcher.Match(MakeEvent(R"({"cat":"android","name":"ARC_VSYNC|abc"})")));
EXPECT_FALSE(
matcher.Match(MakeEvent(R"({"cat":"android","name":"XARC_VSYNC|123"})")));
}
TEST_F(ArcTracingEventMatcherTest, CategoryNamePrefixAndroidInt64) {
ArcTracingEventMatcher matcher("android:ARC_VSYNC|*");
EXPECT_EQ(base::nullopt, matcher.ReadAndroidEventInt64(
MakeEvent(R"({"name":"ARC_VSYNC"})")));
EXPECT_EQ(base::nullopt, matcher.ReadAndroidEventInt64(
MakeEvent(R"({"name":"ARC_VSYNC|"})")));
EXPECT_EQ(base::nullopt, matcher.ReadAndroidEventInt64(
MakeEvent(R"({"name":"ARC_VSYNC|abc"})")));
EXPECT_EQ(
base::make_optional(0),
matcher.ReadAndroidEventInt64(MakeEvent(R"({"name":"ARC_VSYNC|0"})")));
EXPECT_EQ(base::make_optional(777777777777LL),
matcher.ReadAndroidEventInt64(
MakeEvent(R"({"name":"ARC_VSYNC|777777777777"})")));
EXPECT_EQ(base::make_optional(-777777777777LL),
matcher.ReadAndroidEventInt64(
MakeEvent(R"({"name":"ARC_VSYNC|-777777777777"})")));
}
} // namespace arc
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <set> #include <set>
#include "base/bind.h" #include "base/bind.h"
#include "base/callback.h"
#include "base/json/json_reader.h" #include "base/json/json_reader.h"
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
...@@ -83,8 +84,8 @@ constexpr char kHandleMessageInvalidateQuery[] = ...@@ -83,8 +84,8 @@ constexpr char kHandleMessageInvalidateQuery[] =
"android:onMessageReceived/android:handleMessageInvalidate"; "android:onMessageReceived/android:handleMessageInvalidate";
constexpr char kChromeTopEventsQuery[] = constexpr char kChromeTopEventsQuery[] =
"viz,benchmark:Graphics.Pipeline.DrawAndSwap"; "viz,benchmark:Graphics.Pipeline.DrawAndSwap";
constexpr char kVsyncQuery0[] = "android:HW_VSYNC_0|0"; constexpr char kSurfaceFlingerVsyncHandlerQuery[] = "android:HW_VSYNC_0|*";
constexpr char kVsyncQuery1[] = "android:HW_VSYNC_0|1"; constexpr char kArcVsyncTimestampQuery[] = "android:ARC_VSYNC|*";
constexpr char kBarrierFlushMatcher[] = "gpu:CommandBufferStub::OnAsyncFlush"; constexpr char kBarrierFlushMatcher[] = "gpu:CommandBufferStub::OnAsyncFlush";
...@@ -106,115 +107,133 @@ constexpr ssize_t kInvalidBufferIndex = -1; ...@@ -106,115 +107,133 @@ constexpr ssize_t kInvalidBufferIndex = -1;
class BufferGraphicsEventMapper { class BufferGraphicsEventMapper {
public: public:
struct MappingRule { struct MappingRule {
MappingRule(BufferEventType map_start, BufferEventType map_finish) using EventTimeCallback =
: map_start(map_start), map_finish(map_finish) {} base::RepeatingCallback<uint64_t(const ArcTracingEventMatcher&,
const ArcTracingEvent& event)>;
MappingRule(std::unique_ptr<ArcTracingEventMatcher> matcher,
BufferEventType map_start,
BufferEventType map_finish,
EventTimeCallback start_time_callback = EventTimeCallback())
: matcher(std::move(matcher)),
map_start(map_start),
map_finish(map_finish),
event_start_time_callback(start_time_callback) {}
bool Produce(const ArcTracingEvent& event,
ArcTracingGraphicsModel::BufferEvents* collector) const {
if (!matcher->Match(event))
return false;
if (map_start != BufferEventType::kNone) {
uint64_t start_timestamp = event.GetTimestamp();
if (event_start_time_callback) {
start_timestamp = event_start_time_callback.Run(*matcher, event);
}
collector->push_back(
ArcTracingGraphicsModel::BufferEvent(map_start, start_timestamp));
}
if (map_finish != BufferEventType::kNone) {
collector->push_back(ArcTracingGraphicsModel::BufferEvent(
map_finish, event.GetEndTimestamp()));
}
return true;
}
std::unique_ptr<ArcTracingEventMatcher> matcher;
BufferEventType map_start; BufferEventType map_start;
BufferEventType map_finish; BufferEventType map_finish;
EventTimeCallback event_start_time_callback;
}; };
using MappingRules = std::vector< using MappingRules = std::vector<MappingRule>;
std::pair<std::unique_ptr<ArcTracingEventMatcher>, MappingRule>>;
BufferGraphicsEventMapper() { BufferGraphicsEventMapper() {
// exo rules // exo rules
rules_.emplace_back(std::make_pair( rules_.emplace_back(MappingRule(
std::make_unique<ArcTracingEventMatcher>(kExoSurfaceAttachMatcher), std::make_unique<ArcTracingEventMatcher>(kExoSurfaceAttachMatcher),
MappingRule(BufferEventType::kExoSurfaceAttach, BufferEventType::kExoSurfaceAttach, BufferEventType::kNone));
BufferEventType::kNone))); rules_.emplace_back(MappingRule(std::make_unique<ArcTracingEventMatcher>(
rules_.emplace_back( kExoBufferProduceResourceMatcher),
std::make_pair(std::make_unique<ArcTracingEventMatcher>( BufferEventType::kExoProduceResource,
kExoBufferProduceResourceMatcher), BufferEventType::kNone));
MappingRule(BufferEventType::kExoProduceResource, rules_.emplace_back(MappingRule(std::make_unique<ArcTracingEventMatcher>(
BufferEventType::kNone))); kExoBufferReleaseContentsMatcher),
rules_.emplace_back(std::make_pair( BufferEventType::kNone,
std::make_unique<ArcTracingEventMatcher>( BufferEventType::kExoReleased));
kExoBufferReleaseContentsMatcher), rules_.emplace_back(MappingRule(
MappingRule(BufferEventType::kNone, BufferEventType::kExoReleased)));
rules_.emplace_back(std::make_pair(
std::make_unique<ArcTracingEventMatcher>("exo:BufferInUse(step=bound)"), std::make_unique<ArcTracingEventMatcher>("exo:BufferInUse(step=bound)"),
MappingRule(BufferEventType::kExoBound, BufferEventType::kNone))); BufferEventType::kExoBound, BufferEventType::kNone));
rules_.emplace_back( rules_.emplace_back(MappingRule(std::make_unique<ArcTracingEventMatcher>(
std::make_pair(std::make_unique<ArcTracingEventMatcher>( "exo:BufferInUse(step=pending_query)"),
"exo:BufferInUse(step=pending_query)"), BufferEventType::kExoPendingQuery,
MappingRule(BufferEventType::kExoPendingQuery, BufferEventType::kNone));
BufferEventType::kNone)));
// gpu rules // gpu rules
rules_.emplace_back( rules_.emplace_back(MappingRule(
std::make_pair(std::make_unique<ArcTracingEventMatcher>( std::make_unique<ArcTracingEventMatcher>(
"gpu:CommandBufferProxyImpl::OrderingBarrier"), "gpu:CommandBufferProxyImpl::OrderingBarrier"),
MappingRule(BufferEventType::kChromeBarrierOrder, BufferEventType::kChromeBarrierOrder, BufferEventType::kNone));
BufferEventType::kNone))); rules_.emplace_back(MappingRule(
rules_.emplace_back(std::make_pair(
std::make_unique<ArcTracingEventMatcher>(kBarrierFlushMatcher), std::make_unique<ArcTracingEventMatcher>(kBarrierFlushMatcher),
MappingRule(BufferEventType::kNone, BufferEventType::kNone, BufferEventType::kChromeBarrierFlush));
BufferEventType::kChromeBarrierFlush)));
// android rules // android rules
rules_.emplace_back(std::make_pair( rules_.emplace_back(MappingRule(
std::make_unique<ArcTracingEventMatcher>(kDequeueBufferQuery), std::make_unique<ArcTracingEventMatcher>(kDequeueBufferQuery),
MappingRule(BufferEventType::kBufferQueueDequeueStart, BufferEventType::kBufferQueueDequeueStart,
BufferEventType::kBufferQueueDequeueDone))); BufferEventType::kBufferQueueDequeueDone));
rules_.emplace_back(std::make_pair( rules_.emplace_back(
std::make_unique<ArcTracingEventMatcher>(kQueueBufferQuery), MappingRule(std::make_unique<ArcTracingEventMatcher>(kQueueBufferQuery),
MappingRule(BufferEventType::kBufferQueueQueueStart, BufferEventType::kBufferQueueQueueStart,
BufferEventType::kBufferQueueQueueDone))); BufferEventType::kBufferQueueQueueDone));
rules_.emplace_back(std::make_pair( rules_.emplace_back(MappingRule(
std::make_unique<ArcTracingEventMatcher>("android:acquireBuffer"), std::make_unique<ArcTracingEventMatcher>("android:acquireBuffer"),
MappingRule(BufferEventType::kBufferQueueAcquire, BufferEventType::kBufferQueueAcquire, BufferEventType::kNone));
BufferEventType::kNone))); rules_.push_back(MappingRule(
rules_.push_back(std::make_pair(
std::make_unique<ArcTracingEventMatcher>("android:releaseBuffer"), std::make_unique<ArcTracingEventMatcher>("android:releaseBuffer"),
MappingRule(BufferEventType::kNone, BufferEventType::kNone, BufferEventType::kBufferQueueReleased));
BufferEventType::kBufferQueueReleased))); rules_.emplace_back(
rules_.emplace_back(std::make_pair( MappingRule(std::make_unique<ArcTracingEventMatcher>(
std::make_unique<ArcTracingEventMatcher>( "android:handleMessageInvalidate"),
"android:handleMessageInvalidate"), BufferEventType::kSurfaceFlingerInvalidationStart,
MappingRule(BufferEventType::kSurfaceFlingerInvalidationStart, BufferEventType::kSurfaceFlingerInvalidationDone));
BufferEventType::kSurfaceFlingerInvalidationDone))); rules_.emplace_back(
rules_.emplace_back(std::make_pair( MappingRule(std::make_unique<ArcTracingEventMatcher>(
std::make_unique<ArcTracingEventMatcher>( "android:handleMessageRefresh"),
"android:handleMessageRefresh"), BufferEventType::kSurfaceFlingerCompositionStart,
MappingRule(BufferEventType::kSurfaceFlingerCompositionStart, BufferEventType::kSurfaceFlingerCompositionDone));
BufferEventType::kSurfaceFlingerCompositionDone)));
rules_.push_back(std::make_pair(
std::make_unique<ArcTracingEventMatcher>(kVsyncQuery0),
MappingRule(BufferEventType::kVsync, BufferEventType::kNone)));
rules_.push_back(std::make_pair(
std::make_unique<ArcTracingEventMatcher>(kVsyncQuery1),
MappingRule(BufferEventType::kVsync, BufferEventType::kNone)));
// viz,benchmark rules // viz,benchmark rules
auto matcher = std::make_unique<ArcTracingEventMatcher>( auto matcher = std::make_unique<ArcTracingEventMatcher>(
"viz,benchmark:Graphics.Pipeline.DrawAndSwap"); "viz,benchmark:Graphics.Pipeline.DrawAndSwap");
matcher->SetPhase(TRACE_EVENT_PHASE_ASYNC_BEGIN); matcher->SetPhase(TRACE_EVENT_PHASE_ASYNC_BEGIN);
rules_.emplace_back(std::make_pair( rules_.emplace_back(MappingRule(std::move(matcher),
std::move(matcher), BufferEventType::kChromeOSDraw,
MappingRule(BufferEventType::kChromeOSDraw, BufferEventType::kNone))); BufferEventType::kNone));
rules_.emplace_back(std::make_pair( rules_.emplace_back(MappingRule(
std::make_unique<ArcTracingEventMatcher>( std::make_unique<ArcTracingEventMatcher>(
"viz,benchmark:Graphics.Pipeline.DrawAndSwap(step=Draw)"), "viz,benchmark:Graphics.Pipeline.DrawAndSwap(step=Draw)"),
MappingRule(BufferEventType::kNone, BufferEventType::kNone))); BufferEventType::kNone, BufferEventType::kNone));
rules_.emplace_back(std::make_pair( rules_.emplace_back(MappingRule(
std::make_unique<ArcTracingEventMatcher>( std::make_unique<ArcTracingEventMatcher>(
"viz,benchmark:Graphics.Pipeline.DrawAndSwap(step=Swap)"), "viz,benchmark:Graphics.Pipeline.DrawAndSwap(step=Swap)"),
MappingRule(BufferEventType::kChromeOSSwap, BufferEventType::kNone))); BufferEventType::kChromeOSSwap, BufferEventType::kNone));
rules_.emplace_back(std::make_pair( rules_.emplace_back(MappingRule(
std::make_unique<ArcTracingEventMatcher>( std::make_unique<ArcTracingEventMatcher>(
"viz,benchmark:Graphics.Pipeline.DrawAndSwap(step=WaitForAck)"), "viz,benchmark:Graphics.Pipeline.DrawAndSwap(step=WaitForAck)"),
MappingRule(BufferEventType::kChromeOSWaitForAck, BufferEventType::kChromeOSWaitForAck, BufferEventType::kNone));
BufferEventType::kNone))); rules_.emplace_back(MappingRule(
rules_.emplace_back( std::make_unique<ArcTracingEventMatcher>(
std::make_pair(std::make_unique<ArcTracingEventMatcher>( "viz,benchmark:Graphics.Pipeline.DrawAndSwap(step="
"viz,benchmark:Graphics.Pipeline.DrawAndSwap(step=" "WaitForPresentation)"),
"WaitForPresentation)"), BufferEventType::kChromeOSPresentationDone, BufferEventType::kNone));
MappingRule(BufferEventType::kChromeOSPresentationDone,
BufferEventType::kNone)));
matcher = std::make_unique<ArcTracingEventMatcher>( matcher = std::make_unique<ArcTracingEventMatcher>(
"viz,benchmark:Graphics.Pipeline.DrawAndSwap"); "viz,benchmark:Graphics.Pipeline.DrawAndSwap");
matcher->SetPhase(TRACE_EVENT_PHASE_ASYNC_END); matcher->SetPhase(TRACE_EVENT_PHASE_ASYNC_END);
rules_.emplace_back(std::make_pair( rules_.emplace_back(MappingRule(std::move(matcher), BufferEventType::kNone,
std::move(matcher), MappingRule(BufferEventType::kNone, BufferEventType::kChromeOSSwapDone));
BufferEventType::kChromeOSSwapDone)));
} }
~BufferGraphicsEventMapper() = default; ~BufferGraphicsEventMapper() = default;
...@@ -222,17 +241,8 @@ class BufferGraphicsEventMapper { ...@@ -222,17 +241,8 @@ class BufferGraphicsEventMapper {
void Produce(const ArcTracingEvent& event, void Produce(const ArcTracingEvent& event,
ArcTracingGraphicsModel::BufferEvents* collector) const { ArcTracingGraphicsModel::BufferEvents* collector) const {
for (const auto& rule : rules_) { for (const auto& rule : rules_) {
if (!rule.first->Match(event)) if (rule.Produce(event, collector))
continue; return;
if (rule.second.map_start != BufferEventType::kNone) {
collector->push_back(ArcTracingGraphicsModel::BufferEvent(
rule.second.map_start, event.GetTimestamp()));
}
if (rule.second.map_finish != BufferEventType::kNone) {
collector->push_back(ArcTracingGraphicsModel::BufferEvent(
rule.second.map_finish, event.GetEndTimestamp()));
}
return;
} }
LOG(ERROR) << "Unsupported event: " << event.ToString(); LOG(ERROR) << "Unsupported event: " << event.ToString();
} }
...@@ -1321,10 +1331,58 @@ void GetAndroidTopEvents(const ArcTracingModel& common_model, ...@@ -1321,10 +1331,58 @@ void GetAndroidTopEvents(const ArcTracingModel& common_model,
GetEventMapper().Produce(*event, &result->buffer_events()[0]); GetEventMapper().Produce(*event, &result->buffer_events()[0]);
} }
for (const ArcTracingEvent* event : common_model.Select(kVsyncQuery0)) const BufferGraphicsEventMapper::MappingRule
GetEventMapper().Produce(*event, &result->global_events()); mapArcTimestampTraceEventToVsyncTimestamp(
for (const ArcTracingEvent* event : common_model.Select(kVsyncQuery1)) std::make_unique<ArcTracingEventMatcher>(kArcVsyncTimestampQuery),
GetEventMapper().Produce(*event, &result->global_events()); BufferEventType::kVsyncTimestamp, BufferEventType::kNone,
base::BindRepeating([](const ArcTracingEventMatcher& matcher,
const ArcTracingEvent& event) {
// kVsyncTimestamp is special in that we get the actual/ideal
// vsync timestamp which is provided as extra metadata encoded in
// the event name string, rather than looking at the the timestamp
// at which the event was recorded.
base::Optional<int64_t> timestamp =
matcher.ReadAndroidEventInt64(event);
// The encoded int64 timestamp is in nanoseconds. Convert to
// microseconds as that is what the event timestamps are in.
return timestamp ? (*timestamp / 1000) : event.GetTimestamp();
}));
bool hasArcVsyncTimestampEvents = false;
for (const ArcTracingEvent* event :
common_model.Select(kArcVsyncTimestampQuery)) {
if (mapArcTimestampTraceEventToVsyncTimestamp.Produce(
*event, &result->global_events())) {
hasArcVsyncTimestampEvents = true;
}
}
if (!hasArcVsyncTimestampEvents) {
// For backwards compatibility, if there are no events that match
// kArcVsyncTimestampQuery, we use the timestamp of the events that match
// kSurfaceFlingerVsyncHandlerQuery as the kVsyncTimestamp event, though
// this does not accurately represent the vsync event timestamp.
const BufferGraphicsEventMapper::MappingRule
mapVsyncHandlerTraceToVsyncTimestamp(
std::make_unique<ArcTracingEventMatcher>(
kSurfaceFlingerVsyncHandlerQuery),
BufferEventType::kVsyncTimestamp, BufferEventType::kNone);
for (const ArcTracingEvent* event :
common_model.Select(kSurfaceFlingerVsyncHandlerQuery))
mapVsyncHandlerTraceToVsyncTimestamp.Produce(*event,
&result->global_events());
}
const BufferGraphicsEventMapper::MappingRule
mapVsyncHandlerTraceToVsyncHandlerEvent(
std::make_unique<ArcTracingEventMatcher>(
kSurfaceFlingerVsyncHandlerQuery),
BufferEventType::kSurfaceFlingerVsyncHandler, BufferEventType::kNone);
for (const ArcTracingEvent* event :
common_model.Select(kSurfaceFlingerVsyncHandlerQuery))
mapVsyncHandlerTraceToVsyncHandlerEvent.Produce(*event,
&result->global_events());
SortBufferEventsByTimestamp(&result->buffer_events()[0]); SortBufferEventsByTimestamp(&result->buffer_events()[0]);
...@@ -1391,10 +1449,8 @@ bool LoadEvents(const base::Value* value, ...@@ -1391,10 +1449,8 @@ bool LoadEvents(const base::Value* value,
BufferEventType::kExoJank) && BufferEventType::kExoJank) &&
!IsInRange(type, BufferEventType::kChromeBarrierOrder, !IsInRange(type, BufferEventType::kChromeBarrierOrder,
BufferEventType::kChromeBarrierFlush) && BufferEventType::kChromeBarrierFlush) &&
!IsInRange(type, BufferEventType::kVsync, !IsInRange(type, BufferEventType::kSurfaceFlingerVsyncHandler,
BufferEventType::kSurfaceFlingerCompositionDone) && BufferEventType::kVsyncTimestamp) &&
!IsInRange(type, BufferEventType::kVsync,
BufferEventType::kSurfaceFlingerCompositionJank) &&
!IsInRange(type, BufferEventType::kChromeOSDraw, !IsInRange(type, BufferEventType::kChromeOSDraw,
BufferEventType::kChromeOSJank) && BufferEventType::kChromeOSJank) &&
!IsInRange(type, BufferEventType::kCustomEvent, !IsInRange(type, BufferEventType::kCustomEvent,
...@@ -1698,7 +1754,7 @@ void ArcTracingGraphicsModel::VsyncTrim() { ...@@ -1698,7 +1754,7 @@ void ArcTracingGraphicsModel::VsyncTrim() {
int64_t trim_timestamp = -1; int64_t trim_timestamp = -1;
for (const auto& it : android_top_level_.global_events()) { for (const auto& it : android_top_level_.global_events()) {
if (it.type == BufferEventType::kVsync) { if (it.type == BufferEventType::kVsyncTimestamp) {
trim_timestamp = it.timestamp; trim_timestamp = it.timestamp;
break; break;
} }
......
...@@ -64,12 +64,13 @@ class ArcTracingGraphicsModel { ...@@ -64,12 +64,13 @@ class ArcTracingGraphicsModel {
kChromeBarrierFlush, // 301 kChromeBarrierFlush, // 301
// Android Surface Flinger top level events. // Android Surface Flinger top level events.
kVsync = 400, // 400 kSurfaceFlingerVsyncHandler = 400, // 400
kSurfaceFlingerInvalidationStart, // 401 kSurfaceFlingerInvalidationStart, // 401
kSurfaceFlingerInvalidationDone, // 402 kSurfaceFlingerInvalidationDone, // 402
kSurfaceFlingerCompositionStart, // 403 kSurfaceFlingerCompositionStart, // 403
kSurfaceFlingerCompositionDone, // 404 kSurfaceFlingerCompositionDone, // 404
kSurfaceFlingerCompositionJank, // 405, kSurfaceFlingerCompositionJank, // 405,
kVsyncTimestamp, // 406,
// Chrome OS top level events. // Chrome OS top level events.
kChromeOSDraw = 500, // 500 kChromeOSDraw = 500, // 500
......
...@@ -183,13 +183,14 @@ TEST_F(ArcTracingModelTest, TopLevel) { ...@@ -183,13 +183,14 @@ TEST_F(ArcTracingModelTest, TopLevel) {
GraphicsEventType::kSurfaceFlingerInvalidationDone, GraphicsEventType::kSurfaceFlingerInvalidationDone,
GraphicsEventType::kSurfaceFlingerCompositionStart, GraphicsEventType::kSurfaceFlingerCompositionStart,
GraphicsEventType::kSurfaceFlingerCompositionDone})); GraphicsEventType::kSurfaceFlingerCompositionDone}));
EXPECT_TRUE(ValidateGrahpicsEvents( EXPECT_TRUE(
graphics_model.android_top_level().global_events(), ValidateGrahpicsEvents(graphics_model.android_top_level().global_events(),
{GraphicsEventType::kVsync, {GraphicsEventType::kSurfaceFlingerVsyncHandler,
GraphicsEventType::kSurfaceFlingerCompositionJank})); GraphicsEventType::kSurfaceFlingerCompositionJank,
GraphicsEventType::kVsyncTimestamp}));
ASSERT_FALSE(graphics_model.android_top_level().global_events().empty()); ASSERT_FALSE(graphics_model.android_top_level().global_events().empty());
// Check trimmed by VSYNC. // Check trimmed by VSYNC.
EXPECT_EQ(GraphicsEventType::kVsync, EXPECT_EQ(GraphicsEventType::kSurfaceFlingerVsyncHandler,
graphics_model.android_top_level().global_events()[0].type); graphics_model.android_top_level().global_events()[0].type);
EXPECT_EQ(0U, EXPECT_EQ(0U,
graphics_model.android_top_level().global_events()[0].timestamp); graphics_model.android_top_level().global_events()[0].timestamp);
......
...@@ -68,8 +68,8 @@ var eventAttributes = { ...@@ -68,8 +68,8 @@ var eventAttributes = {
// kChromeBarrierFlush // kChromeBarrierFlush
301: {color: unusedColor, name: 'barrier flush'}, 301: {color: unusedColor, name: 'barrier flush'},
// kVsync // kSurfaceFlingerVsyncHandler
400: {color: '#ff3300', name: 'vsync', width: 0.5}, 400: {color: '#993300', name: 'vsync handler', width: 1.0},
// kSurfaceFlingerInvalidationStart // kSurfaceFlingerInvalidationStart
401: {color: '#ff9933', name: 'invalidation start'}, 401: {color: '#ff9933', name: 'invalidation start'},
// kSurfaceFlingerInvalidationDone // kSurfaceFlingerInvalidationDone
...@@ -85,6 +85,8 @@ var eventAttributes = { ...@@ -85,6 +85,8 @@ var eventAttributes = {
width: 1.0, width: 1.0,
radius: 4.0 radius: 4.0
}, },
// kVsyncTimestamp
406: {color: '#ff3300', name: 'vsync', width: 0.5},
// kChromeOSDraw // kChromeOSDraw
500: {color: '#3399ff', name: 'draw'}, 500: {color: '#3399ff', name: 'draw'},
...@@ -977,7 +979,7 @@ class EventBands { ...@@ -977,7 +979,7 @@ class EventBands {
var globalEvent = globalEvents[i]; var globalEvent = globalEvents[i];
var globalEventType = globalEvent[0]; var globalEventType = globalEvent[0];
var globalEventTimestamp = globalEvent[1]; var globalEventTimestamp = globalEvent[1];
if (globalEventType == 400 /* kVsync */) { if (globalEventType == 406 /* kVsyncTimestamp */) {
// -1 to prevent VSYNC detects itself. In last case, previous VSYNC // -1 to prevent VSYNC detects itself. In last case, previous VSYNC
// would be chosen. // would be chosen.
globalEventTimestamp -= 1; globalEventTimestamp -= 1;
...@@ -1368,8 +1370,8 @@ class CpuDetailedInfoView extends DetailedInfoView { ...@@ -1368,8 +1370,8 @@ class CpuDetailedInfoView extends DetailedInfoView {
} }
var vsyncEvents = new Events( var vsyncEvents = new Events(
overviewBand.model.android.global_events, 400 /* kVsync */, overviewBand.model.android.global_events, 406 /* kVsyncTimestamp */,
400 /* kVsync */); 406 /* kVsyncTimestamp */);
bands.setVSync(vsyncEvents); bands.setVSync(vsyncEvents);
// Add center and boundary lines. // Add center and boundary lines.
...@@ -1649,7 +1651,8 @@ function setGraphicBuffersModel(model) { ...@@ -1649,7 +1651,8 @@ function setGraphicBuffersModel(model) {
var chartHeight = 48; var chartHeight = 48;
var vsyncEvents = new Events( var vsyncEvents = new Events(
model.android.global_events, 400 /* kVsync */, 400 /* kVsync */); model.android.global_events, 406 /* kVsyncTimestamp */,
406 /* kVsyncTimestamp */);
var cpusTitle = new EventBandTitle(parent, 'CPUs', 'arc-events-band-title'); var cpusTitle = new EventBandTitle(parent, 'CPUs', 'arc-events-band-title');
var cpusBands = new CpuEventBands( var cpusBands = new CpuEventBands(
...@@ -1730,6 +1733,12 @@ function setGraphicBuffersModel(model) { ...@@ -1730,6 +1733,12 @@ function setGraphicBuffersModel(model) {
topBandPadding); topBandPadding);
// Add vsync events // Add vsync events
androidBands.setVSync(vsyncEvents); androidBands.setVSync(vsyncEvents);
// Add vsync handler events
var androidVsyncHandling = new Events(
model.android.global_events, 400 /* kSurfaceFlingerVsyncHandler */,
400 /* kSurfaceFlingerVsyncHandler */);
androidBands.addGlobal(androidVsyncHandling);
// Add jank events
var androidJanks = new Events( var androidJanks = new Events(
model.android.global_events, 405 /* kSurfaceFlingerCompositionJank */, model.android.global_events, 405 /* kSurfaceFlingerCompositionJank */,
405 /* kSurfaceFlingerCompositionJank */); 405 /* kSurfaceFlingerCompositionJank */);
......
...@@ -404,7 +404,7 @@ void ArcGraphicsTracingHandler::StartTracing() { ...@@ -404,7 +404,7 @@ void ArcGraphicsTracingHandler::StartTracing() {
base::trace_event::TraceConfig config( base::trace_event::TraceConfig config(
"-*,exo,viz,toplevel,gpu,cc,blink,disabled-by-default-android " "-*,exo,viz,toplevel,gpu,cc,blink,disabled-by-default-android "
"gfx,disabled-by-default-android hal,disabled-by-default-android view", "gfx,disabled-by-default-android view",
base::trace_event::RECORD_CONTINUOUSLY); base::trace_event::RECORD_CONTINUOUSLY);
config.EnableSystrace(); config.EnableSystrace();
// By default, systracing starts pre-defined set of categories with predefined // By default, systracing starts pre-defined set of categories with predefined
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment