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") {
]
if (v8_use_perfetto) {
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.h",
"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 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_
#define V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_
#ifndef V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_BASE_H_
#define V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_BASE_H_
#include <memory>
......@@ -11,21 +11,30 @@
#include "perfetto/tracing/core/tracing_service.h"
#include "src/base/logging.h"
namespace perfetto {
namespace protos {
class ChromeTracePacket;
} // namespace protos
} // namespace perfetto
namespace v8 {
namespace base {
class Semaphore;
}
namespace platform {
namespace tracing {
// A dummy Consumer that does nothing because we write directly to a file using
// the Service. This will be replaced later with a JSON consumer that writes
// JSON to a stream, but we need a stand-in for now.
// A base class for custom Consumers within V8. Implements V8-specific logic
// for interacting with the tracing controller and leaves the consumption of
// the trace events to the subclass.
// A Perfetto Consumer gets streamed trace events from the Service via
// OnTraceData(). A Consumer can be configured (via
// service_endpoint()->EnableTracing()) to listen to various different types of
// 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
// file.
class PerfettoConsumer final : public ::perfetto::Consumer {
// output the system should have.
class PerfettoConsumerBase : public ::perfetto::Consumer {
public:
using ServiceEndpoint = ::perfetto::TracingService::ConsumerEndpoint;
......@@ -34,19 +43,16 @@ class PerfettoConsumer final : public ::perfetto::Consumer {
service_endpoint_ = std::move(endpoint);
}
protected:
explicit PerfettoConsumerBase(base::Semaphore* finished);
private:
// ::perfetto::Consumer implementation
void OnConnect() override {}
void OnDisconnect() 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,
bool has_more) override {
UNREACHABLE();
}
bool has_more) final;
void OnDetach(bool success) override {}
void OnAttach(bool success, const ::perfetto::TraceConfig&) override {}
void OnTraceStats(bool success, const ::perfetto::TraceStats&) override {
......@@ -56,11 +62,16 @@ class PerfettoConsumer final : public ::perfetto::Consumer {
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_;
base::Semaphore* finished_semaphore_;
};
} // namespace tracing
} // namespace platform
} // namespace v8
#endif // V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_
#endif // V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_BASE_H_
......@@ -8,37 +8,21 @@
#include "base/trace_event/common/trace_event_common.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/macros.h"
#include "src/base/platform/semaphore.h"
namespace v8 {
namespace platform {
namespace tracing {
PerfettoJSONConsumer::PerfettoJSONConsumer(std::ostream* stream,
base::Semaphore* finished)
: stream_(stream), finished_semaphore_(finished) {
PerfettoJSONConsumer::PerfettoJSONConsumer(base::Semaphore* finished,
std::ostream* stream)
: PerfettoConsumerBase(finished), stream_(stream) {
*stream_ << "{\"traceEvents\":[";
}
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
// once we've removed that file.
......
......@@ -7,14 +7,9 @@
#include <ostream>
#include "perfetto/tracing/core/consumer.h"
#include "perfetto/tracing/core/tracing_service.h"
#include "src/base/logging.h"
#include "src/libplatform/tracing/perfetto-consumer-base.h"
namespace perfetto {
class TraceConfig;
class TracePacket;
namespace protos {
class ChromeTraceEvent_Arg;
class ChromeTracePacket;
......@@ -22,61 +17,26 @@ class ChromeTracePacket;
} // namespace perfetto
namespace v8 {
namespace base {
class Semaphore;
}
namespace platform {
namespace tracing {
// A Perfetto Consumer gets streamed trace events from the Service via
// OnTraceData(). A Consumer can be configured (via
// service_endpoint()->EnableTracing()) to listen to various different types of
// 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 {
// A consumer that converts the proto trace data to JSON and writes it to a
// file.
class PerfettoJSONConsumer final : public PerfettoConsumerBase {
public:
explicit PerfettoJSONConsumer(std::ostream* stream,
base::Semaphore* finished);
PerfettoJSONConsumer(base::Semaphore* finished, std::ostream* stream);
~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:
// ::perfetto::Consumer implementation
void OnConnect() 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();
}
void ProcessPacket(
const ::perfetto::protos::ChromeTracePacket& packet) override;
// Internal implementation
void AppendJSONString(const char* str);
void AppendArgValue(const ::perfetto::protos::ChromeTraceEvent_Arg& arg);
void ProcessPacket(const ::perfetto::protos::ChromeTracePacket& packet);
std::ostream* stream_;
bool append_comma_ = false;
std::unique_ptr<ServiceEndpoint> service_endpoint_;
base::Semaphore* finished_semaphore_;
};
} // namespace tracing
......
......@@ -45,7 +45,7 @@ void PerfettoTracingController::StartTracing(
service_->SetSMBScrapingEnabled(true);
producer_ = base::make_unique<PerfettoProducer>(this);
consumer_ = base::make_unique<PerfettoJSONConsumer>(
output_stream, &consumer_finished_semaphore_);
&consumer_finished_semaphore_, output_stream);
producer_->set_service_endpoint(service_->ConnectProducer(
producer_.get(), 0, "v8.perfetto-producer", 0, true));
......@@ -72,7 +72,7 @@ void PerfettoTracingController::StopTracing() {
// events that have been written by still-living TraceWriters.
consumer_->service_endpoint()->DisableTracing();
// 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.
consumer_->service_endpoint()->ReadBuffers();
});
......
......@@ -23,7 +23,7 @@ namespace v8 {
namespace platform {
namespace tracing {
class PerfettoJSONConsumer;
class PerfettoConsumerBase;
class PerfettoProducer;
class PerfettoTaskRunner;
......@@ -61,7 +61,7 @@ class PerfettoTracingController {
std::unique_ptr<::perfetto::TracingService> service_;
std::unique_ptr<PerfettoProducer> producer_;
std::unique_ptr<PerfettoJSONConsumer> consumer_;
std::unique_ptr<PerfettoConsumerBase> consumer_;
std::unique_ptr<PerfettoTaskRunner> task_runner_;
base::Thread::LocalStorageKey writer_key_;
// 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