Commit 9a2e4693 authored by Peter Marshall's avatar Peter Marshall Committed by Commit Bot

[tracing] Add a perfetto consumer base class

Split the JSONConsumer into a base case and subclass so that we can
implement different consumers without needing to repeat the code that
deals with the finished semaphore and endpoint setters/getters.

This makes it possible to add a test consumer that just holds the trace
events in memory in a later CL.

This CL re-uses the existing perfetto-consumer.h file to some extent,
but it was accidentally leftover from a previous CL where we stopped
using it and switched to the JSON consumer instead.

Cq-Include-Trybots: luci.v8.try:v8_linux64_perfetto_dbg_ng
Bug: v8:8339
Change-Id: I56c305833c8937da76a8e6defbe7a52c59b25106
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1621938
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61799}
parent 93526b85
...@@ -3659,6 +3659,8 @@ v8_component("v8_libplatform") { ...@@ -3659,6 +3659,8 @@ v8_component("v8_libplatform") {
] ]
if (v8_use_perfetto) { if (v8_use_perfetto) {
sources += [ sources += [
"src/libplatform/tracing/perfetto-consumer-base.cc",
"src/libplatform/tracing/perfetto-consumer-base.h",
"src/libplatform/tracing/perfetto-json-consumer.cc", "src/libplatform/tracing/perfetto-json-consumer.cc",
"src/libplatform/tracing/perfetto-json-consumer.h", "src/libplatform/tracing/perfetto-json-consumer.h",
"src/libplatform/tracing/perfetto-producer.cc", "src/libplatform/tracing/perfetto-producer.cc",
......
// Copyright 2019 the V8 project 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 "src/libplatform/tracing/perfetto-consumer-base.h"
#include "perfetto/trace/chrome/chrome_trace_packet.pb.h"
#include "perfetto/tracing/core/trace_packet.h"
#include "src/base/macros.h"
#include "src/base/platform/semaphore.h"
namespace v8 {
namespace platform {
namespace tracing {
PerfettoConsumerBase::PerfettoConsumerBase(base::Semaphore* finished)
: finished_semaphore_(finished) {}
void PerfettoConsumerBase::OnTraceData(
std::vector<::perfetto::TracePacket> packets, bool has_more) {
for (const ::perfetto::TracePacket& packet : packets) {
perfetto::protos::ChromeTracePacket proto_packet;
bool success = packet.Decode(&proto_packet);
USE(success);
DCHECK(success);
ProcessPacket(proto_packet);
}
// PerfettoTracingController::StopTracing() waits on this sempahore. This is
// so that we can ensure that this consumer has finished consuming all of the
// trace events from the buffer before the buffer is destroyed.
if (!has_more) finished_semaphore_->Signal();
}
} // namespace tracing
} // namespace platform
} // namespace v8
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_ #ifndef V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_BASE_H_
#define V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_ #define V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_BASE_H_
#include <memory> #include <memory>
...@@ -11,21 +11,30 @@ ...@@ -11,21 +11,30 @@
#include "perfetto/tracing/core/tracing_service.h" #include "perfetto/tracing/core/tracing_service.h"
#include "src/base/logging.h" #include "src/base/logging.h"
namespace perfetto {
namespace protos {
class ChromeTracePacket;
} // namespace protos
} // namespace perfetto
namespace v8 { namespace v8 {
namespace base {
class Semaphore;
}
namespace platform { namespace platform {
namespace tracing { namespace tracing {
// A dummy Consumer that does nothing because we write directly to a file using // A base class for custom Consumers within V8. Implements V8-specific logic
// the Service. This will be replaced later with a JSON consumer that writes // for interacting with the tracing controller and leaves the consumption of
// JSON to a stream, but we need a stand-in for now. // the trace events to the subclass.
// A Perfetto Consumer gets streamed trace events from the Service via // A Perfetto Consumer gets streamed trace events from the Service via
// OnTraceData(). A Consumer can be configured (via // OnTraceData(). A Consumer can be configured (via
// service_endpoint()->EnableTracing()) to listen to various different types of // service_endpoint()->EnableTracing()) to listen to various different types of
// trace events. The Consumer is responsible for producing whatever tracing // trace events. The Consumer is responsible for producing whatever tracing
// output the system should have - e.g. converting to JSON and writing it to a // output the system should have.
// file. class PerfettoConsumerBase : public ::perfetto::Consumer {
class PerfettoConsumer final : public ::perfetto::Consumer {
public: public:
using ServiceEndpoint = ::perfetto::TracingService::ConsumerEndpoint; using ServiceEndpoint = ::perfetto::TracingService::ConsumerEndpoint;
...@@ -34,19 +43,16 @@ class PerfettoConsumer final : public ::perfetto::Consumer { ...@@ -34,19 +43,16 @@ class PerfettoConsumer final : public ::perfetto::Consumer {
service_endpoint_ = std::move(endpoint); service_endpoint_ = std::move(endpoint);
} }
protected:
explicit PerfettoConsumerBase(base::Semaphore* finished);
private: private:
// ::perfetto::Consumer implementation // ::perfetto::Consumer implementation
void OnConnect() override {} void OnConnect() override {}
void OnDisconnect() override {} void OnDisconnect() override {}
void OnTracingDisabled() override {} void OnTracingDisabled() override {}
// Note: this callback will never be seen because in EnableTracing we set
// write_into_file=true. That flag essentially tells the service to directly
// write into the passed file descriptor, instead of returning the trace
// contents via IPC (which is what this method does).
void OnTraceData(std::vector<::perfetto::TracePacket> packets, void OnTraceData(std::vector<::perfetto::TracePacket> packets,
bool has_more) override { bool has_more) final;
UNREACHABLE();
}
void OnDetach(bool success) override {} void OnDetach(bool success) override {}
void OnAttach(bool success, const ::perfetto::TraceConfig&) override {} void OnAttach(bool success, const ::perfetto::TraceConfig&) override {}
void OnTraceStats(bool success, const ::perfetto::TraceStats&) override { void OnTraceStats(bool success, const ::perfetto::TraceStats&) override {
...@@ -56,11 +62,16 @@ class PerfettoConsumer final : public ::perfetto::Consumer { ...@@ -56,11 +62,16 @@ class PerfettoConsumer final : public ::perfetto::Consumer {
UNREACHABLE(); UNREACHABLE();
} }
// Subclasses override this method to respond to trace packets.
virtual void ProcessPacket(
const ::perfetto::protos::ChromeTracePacket& packet) = 0;
std::unique_ptr<ServiceEndpoint> service_endpoint_; std::unique_ptr<ServiceEndpoint> service_endpoint_;
base::Semaphore* finished_semaphore_;
}; };
} // namespace tracing } // namespace tracing
} // namespace platform } // namespace platform
} // namespace v8 } // namespace v8
#endif // V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_ #endif // V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_BASE_H_
...@@ -8,37 +8,21 @@ ...@@ -8,37 +8,21 @@
#include "base/trace_event/common/trace_event_common.h" #include "base/trace_event/common/trace_event_common.h"
#include "perfetto/trace/chrome/chrome_trace_packet.pb.h" #include "perfetto/trace/chrome/chrome_trace_packet.pb.h"
#include "perfetto/tracing/core/trace_packet.h"
#include "src/base/logging.h" #include "src/base/logging.h"
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/base/platform/semaphore.h"
namespace v8 { namespace v8 {
namespace platform { namespace platform {
namespace tracing { namespace tracing {
PerfettoJSONConsumer::PerfettoJSONConsumer(std::ostream* stream, PerfettoJSONConsumer::PerfettoJSONConsumer(base::Semaphore* finished,
base::Semaphore* finished) std::ostream* stream)
: stream_(stream), finished_semaphore_(finished) { : PerfettoConsumerBase(finished), stream_(stream) {
*stream_ << "{\"traceEvents\":["; *stream_ << "{\"traceEvents\":[";
} }
PerfettoJSONConsumer::~PerfettoJSONConsumer() { *stream_ << "]}"; } PerfettoJSONConsumer::~PerfettoJSONConsumer() { *stream_ << "]}"; }
void PerfettoJSONConsumer::OnTraceData(
std::vector<::perfetto::TracePacket> packets, bool has_more) {
for (const ::perfetto::TracePacket& packet : packets) {
perfetto::protos::ChromeTracePacket proto_packet;
bool success = packet.Decode(&proto_packet);
USE(success);
DCHECK(success);
ProcessPacket(proto_packet);
}
// Alert PerfettoTracingController that we are finished during StopTracing().
if (!has_more) finished_semaphore_->Signal();
}
// TODO(petermarshall): Clean up this code which was copied from trace-writer.cc // TODO(petermarshall): Clean up this code which was copied from trace-writer.cc
// once we've removed that file. // once we've removed that file.
......
...@@ -7,14 +7,9 @@ ...@@ -7,14 +7,9 @@
#include <ostream> #include <ostream>
#include "perfetto/tracing/core/consumer.h" #include "src/libplatform/tracing/perfetto-consumer-base.h"
#include "perfetto/tracing/core/tracing_service.h"
#include "src/base/logging.h"
namespace perfetto { namespace perfetto {
class TraceConfig;
class TracePacket;
namespace protos { namespace protos {
class ChromeTraceEvent_Arg; class ChromeTraceEvent_Arg;
class ChromeTracePacket; class ChromeTracePacket;
...@@ -22,61 +17,26 @@ class ChromeTracePacket; ...@@ -22,61 +17,26 @@ class ChromeTracePacket;
} // namespace perfetto } // namespace perfetto
namespace v8 { namespace v8 {
namespace base {
class Semaphore;
}
namespace platform { namespace platform {
namespace tracing { namespace tracing {
// A Perfetto Consumer gets streamed trace events from the Service via // A consumer that converts the proto trace data to JSON and writes it to a
// OnTraceData(). A Consumer can be configured (via // file.
// service_endpoint()->EnableTracing()) to listen to various different types of class PerfettoJSONConsumer final : public PerfettoConsumerBase {
// trace events. The Consumer is responsible for producing whatever tracing
// output the system should have - in this case, converting the proto trace data
// delivered via OnTraceData() to JSON and writing it to a file.
class PerfettoJSONConsumer final : public ::perfetto::Consumer {
public: public:
explicit PerfettoJSONConsumer(std::ostream* stream, PerfettoJSONConsumer(base::Semaphore* finished, std::ostream* stream);
base::Semaphore* finished);
~PerfettoJSONConsumer() override; ~PerfettoJSONConsumer() override;
using ServiceEndpoint = ::perfetto::TracingService::ConsumerEndpoint;
ServiceEndpoint* service_endpoint() const { return service_endpoint_.get(); }
void set_service_endpoint(std::unique_ptr<ServiceEndpoint> endpoint) {
service_endpoint_ = std::move(endpoint);
}
private: private:
// ::perfetto::Consumer implementation void ProcessPacket(
void OnConnect() override {} const ::perfetto::protos::ChromeTracePacket& packet) override;
void OnDisconnect() override {}
void OnTracingDisabled() override {}
void OnTraceData(std::vector<::perfetto::TracePacket> packets,
bool has_more) override;
void OnDetach(bool success) override {}
void OnAttach(bool success, const ::perfetto::TraceConfig&) override {}
void OnTraceStats(bool success, const ::perfetto::TraceStats&) override {
UNREACHABLE();
}
void OnObservableEvents(const ::perfetto::ObservableEvents&) override {
UNREACHABLE();
}
// Internal implementation // Internal implementation
void AppendJSONString(const char* str); void AppendJSONString(const char* str);
void AppendArgValue(const ::perfetto::protos::ChromeTraceEvent_Arg& arg); void AppendArgValue(const ::perfetto::protos::ChromeTraceEvent_Arg& arg);
void ProcessPacket(const ::perfetto::protos::ChromeTracePacket& packet);
std::ostream* stream_; std::ostream* stream_;
bool append_comma_ = false; bool append_comma_ = false;
std::unique_ptr<ServiceEndpoint> service_endpoint_;
base::Semaphore* finished_semaphore_;
}; };
} // namespace tracing } // namespace tracing
......
...@@ -45,7 +45,7 @@ void PerfettoTracingController::StartTracing( ...@@ -45,7 +45,7 @@ void PerfettoTracingController::StartTracing(
service_->SetSMBScrapingEnabled(true); service_->SetSMBScrapingEnabled(true);
producer_ = base::make_unique<PerfettoProducer>(this); producer_ = base::make_unique<PerfettoProducer>(this);
consumer_ = base::make_unique<PerfettoJSONConsumer>( consumer_ = base::make_unique<PerfettoJSONConsumer>(
output_stream, &consumer_finished_semaphore_); &consumer_finished_semaphore_, output_stream);
producer_->set_service_endpoint(service_->ConnectProducer( producer_->set_service_endpoint(service_->ConnectProducer(
producer_.get(), 0, "v8.perfetto-producer", 0, true)); producer_.get(), 0, "v8.perfetto-producer", 0, true));
...@@ -72,7 +72,7 @@ void PerfettoTracingController::StopTracing() { ...@@ -72,7 +72,7 @@ void PerfettoTracingController::StopTracing() {
// events that have been written by still-living TraceWriters. // events that have been written by still-living TraceWriters.
consumer_->service_endpoint()->DisableTracing(); consumer_->service_endpoint()->DisableTracing();
// Trigger the consumer to finish. This can trigger multiple calls to // Trigger the consumer to finish. This can trigger multiple calls to
// PerfettoJSONConsumer::OnTraceData(), with the final call passing has_more // PerfettoConsumerBase::OnTraceData(), with the final call passing has_more
// as false. // as false.
consumer_->service_endpoint()->ReadBuffers(); consumer_->service_endpoint()->ReadBuffers();
}); });
......
...@@ -23,7 +23,7 @@ namespace v8 { ...@@ -23,7 +23,7 @@ namespace v8 {
namespace platform { namespace platform {
namespace tracing { namespace tracing {
class PerfettoJSONConsumer; class PerfettoConsumerBase;
class PerfettoProducer; class PerfettoProducer;
class PerfettoTaskRunner; class PerfettoTaskRunner;
...@@ -61,7 +61,7 @@ class PerfettoTracingController { ...@@ -61,7 +61,7 @@ class PerfettoTracingController {
std::unique_ptr<::perfetto::TracingService> service_; std::unique_ptr<::perfetto::TracingService> service_;
std::unique_ptr<PerfettoProducer> producer_; std::unique_ptr<PerfettoProducer> producer_;
std::unique_ptr<PerfettoJSONConsumer> consumer_; std::unique_ptr<PerfettoConsumerBase> consumer_;
std::unique_ptr<PerfettoTaskRunner> task_runner_; std::unique_ptr<PerfettoTaskRunner> task_runner_;
base::Thread::LocalStorageKey writer_key_; base::Thread::LocalStorageKey writer_key_;
// A semaphore that is signalled when StartRecording is called. StartTracing // A semaphore that is signalled when StartRecording is called. StartTracing
......
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