diff options
Diffstat (limited to 'deps/v8/src/libplatform/tracing')
16 files changed, 120 insertions, 708 deletions
diff --git a/deps/v8/src/libplatform/tracing/OWNERS b/deps/v8/src/libplatform/tracing/OWNERS new file mode 100644 index 0000000000..507f904088 --- /dev/null +++ b/deps/v8/src/libplatform/tracing/OWNERS @@ -0,0 +1 @@ +petermarshall@chromium.org diff --git a/deps/v8/src/libplatform/tracing/json-trace-event-listener.cc b/deps/v8/src/libplatform/tracing/json-trace-event-listener.cc index 99db86a7d1..94b74ef255 100644 --- a/deps/v8/src/libplatform/tracing/json-trace-event-listener.cc +++ b/deps/v8/src/libplatform/tracing/json-trace-event-listener.cc @@ -8,6 +8,8 @@ #include "base/trace_event/common/trace_event_common.h" #include "perfetto/trace/chrome/chrome_trace_packet.pb.h" +#include "perfetto/trace/trace.pb.h" +#include "perfetto/tracing.h" #include "src/base/logging.h" #include "src/base/macros.h" @@ -111,7 +113,7 @@ void JSONTraceEventListener::AppendArgValue( } void JSONTraceEventListener::ProcessPacket( - const ::perfetto::protos::ChromeTracePacket& packet) { + const ::perfetto::protos::TracePacket& packet) { for (const ::perfetto::protos::ChromeTraceEvent& event : packet.chrome_events().trace_events()) { if (append_comma_) *stream_ << ","; diff --git a/deps/v8/src/libplatform/tracing/json-trace-event-listener.h b/deps/v8/src/libplatform/tracing/json-trace-event-listener.h index fc4979f14c..d13332871f 100644 --- a/deps/v8/src/libplatform/tracing/json-trace-event-listener.h +++ b/deps/v8/src/libplatform/tracing/json-trace-event-listener.h @@ -26,10 +26,9 @@ class JSONTraceEventListener final : public TraceEventListener { explicit JSONTraceEventListener(std::ostream* stream); ~JSONTraceEventListener() override; - private: - void ProcessPacket( - const ::perfetto::protos::ChromeTracePacket& packet) override; + void ProcessPacket(const ::perfetto::protos::TracePacket& packet) override; + private: // Internal implementation void AppendJSONString(const char* str); void AppendArgValue(const ::perfetto::protos::ChromeTraceEvent_Arg& arg); diff --git a/deps/v8/src/libplatform/tracing/perfetto-consumer.cc b/deps/v8/src/libplatform/tracing/perfetto-consumer.cc deleted file mode 100644 index 8071fe52d5..0000000000 --- a/deps/v8/src/libplatform/tracing/perfetto-consumer.cc +++ /dev/null @@ -1,44 +0,0 @@ -// 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.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" -#include "src/libplatform/tracing/trace-event-listener.h" - -namespace v8 { -namespace platform { -namespace tracing { - -PerfettoConsumer::PerfettoConsumer(base::Semaphore* finished) - : finished_semaphore_(finished) {} - -void PerfettoConsumer::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); - - for (TraceEventListener* listener : listeners_) { - listener->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(); -} - -void PerfettoConsumer::AddTraceEventListener(TraceEventListener* listener) { - listeners_.push_back(listener); -} - -} // namespace tracing -} // namespace platform -} // namespace v8 diff --git a/deps/v8/src/libplatform/tracing/perfetto-consumer.h b/deps/v8/src/libplatform/tracing/perfetto-consumer.h deleted file mode 100644 index 83d0c48c1b..0000000000 --- a/deps/v8/src/libplatform/tracing/perfetto-consumer.h +++ /dev/null @@ -1,80 +0,0 @@ -// 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. - -#ifndef V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_ -#define V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_ - -#include <memory> - -#include "perfetto/tracing/core/consumer.h" -#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 { - -class TraceEventListener; - -// 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. - -// Implements the V8-specific logic for interacting with the tracing controller -// and directs trace events to the added TraceEventListeners. -class PerfettoConsumer final : public ::perfetto::Consumer { - public: - explicit PerfettoConsumer(base::Semaphore* finished); - - using ServiceEndpoint = ::perfetto::TracingService::ConsumerEndpoint; - - // Register a trace event listener that will receive trace events from this - // consumer. This can be called multiple times to register multiple listeners, - // but must be called before starting tracing. - void AddTraceEventListener(TraceEventListener* listener); - - 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(); - } - - std::unique_ptr<ServiceEndpoint> service_endpoint_; - base::Semaphore* finished_semaphore_; - std::vector<TraceEventListener*> listeners_; -}; - -} // namespace tracing -} // namespace platform -} // namespace v8 - -#endif // V8_LIBPLATFORM_TRACING_PERFETTO_CONSUMER_H_ diff --git a/deps/v8/src/libplatform/tracing/perfetto-producer.cc b/deps/v8/src/libplatform/tracing/perfetto-producer.cc deleted file mode 100644 index 814dca6b59..0000000000 --- a/deps/v8/src/libplatform/tracing/perfetto-producer.cc +++ /dev/null @@ -1,45 +0,0 @@ -// 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-producer.h" - -#include "perfetto/tracing/core/data_source_config.h" -#include "perfetto/tracing/core/data_source_descriptor.h" -#include "perfetto/tracing/core/trace_writer.h" -#include "src/libplatform/tracing/perfetto-tasks.h" -#include "src/libplatform/tracing/perfetto-tracing-controller.h" - -namespace v8 { -namespace platform { -namespace tracing { - -void PerfettoProducer::OnConnect() { - ::perfetto::DataSourceDescriptor ds_desc; - ds_desc.set_name("v8.trace_events"); - service_endpoint_->RegisterDataSource(ds_desc); -} - -void PerfettoProducer::StartDataSource( - ::perfetto::DataSourceInstanceID, const ::perfetto::DataSourceConfig& cfg) { - target_buffer_ = cfg.target_buffer(); - tracing_controller_->OnProducerReady(); -} - -void PerfettoProducer::StopDataSource(::perfetto::DataSourceInstanceID) { - target_buffer_ = 0; -} - -std::unique_ptr<::perfetto::TraceWriter> PerfettoProducer::CreateTraceWriter() - const { - CHECK_NE(0, target_buffer_); - return service_endpoint_->CreateTraceWriter(target_buffer_); -} - -PerfettoProducer::PerfettoProducer( - PerfettoTracingController* tracing_controller) - : tracing_controller_(tracing_controller) {} - -} // namespace tracing -} // namespace platform -} // namespace v8 diff --git a/deps/v8/src/libplatform/tracing/perfetto-producer.h b/deps/v8/src/libplatform/tracing/perfetto-producer.h deleted file mode 100644 index 2a363e8bf8..0000000000 --- a/deps/v8/src/libplatform/tracing/perfetto-producer.h +++ /dev/null @@ -1,70 +0,0 @@ -// 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. - -#ifndef V8_LIBPLATFORM_TRACING_PERFETTO_PRODUCER_H_ -#define V8_LIBPLATFORM_TRACING_PERFETTO_PRODUCER_H_ - -#include <atomic> -#include <memory> - -#include "perfetto/tracing/core/producer.h" -#include "perfetto/tracing/core/tracing_service.h" -#include "src/base/logging.h" - -namespace v8 { -namespace platform { -namespace tracing { - -class PerfettoTracingController; - -class PerfettoProducer final : public ::perfetto::Producer { - public: - using ServiceEndpoint = ::perfetto::TracingService::ProducerEndpoint; - - explicit PerfettoProducer(PerfettoTracingController* tracing_controller); - - ServiceEndpoint* service_endpoint() const { return service_endpoint_.get(); } - void set_service_endpoint(std::unique_ptr<ServiceEndpoint> endpoint) { - service_endpoint_ = std::move(endpoint); - } - - // Create a TraceWriter for the calling thread. The TraceWriter is a - // thread-local object that writes data into a buffer which is shared between - // all TraceWriters for a given PerfettoProducer instance. Can only be called - // after the StartDataSource() callback has been received from the service, as - // this provides the buffer. - std::unique_ptr<::perfetto::TraceWriter> CreateTraceWriter() const; - - private: - // ::perfetto::Producer implementation - void OnConnect() override; - void OnDisconnect() override {} - void OnTracingSetup() override {} - void SetupDataSource(::perfetto::DataSourceInstanceID, - const ::perfetto::DataSourceConfig&) override {} - void StartDataSource(::perfetto::DataSourceInstanceID, - const ::perfetto::DataSourceConfig& cfg) override; - void StopDataSource(::perfetto::DataSourceInstanceID) override; - // TODO(petermarshall): Implement Flush(). A final flush happens when the - // TraceWriter object for each thread is destroyed, but this will be more - // efficient. - void Flush(::perfetto::FlushRequestID, - const ::perfetto::DataSourceInstanceID*, size_t) override {} - - void ClearIncrementalState( - const ::perfetto::DataSourceInstanceID* data_source_ids, - size_t num_data_sources) override { - UNREACHABLE(); - } - - std::unique_ptr<ServiceEndpoint> service_endpoint_; - uint32_t target_buffer_ = 0; - PerfettoTracingController* tracing_controller_; -}; - -} // namespace tracing -} // namespace platform -} // namespace v8 - -#endif // V8_LIBPLATFORM_TRACING_PERFETTO_PRODUCER_H_ diff --git a/deps/v8/src/libplatform/tracing/perfetto-shared-memory.cc b/deps/v8/src/libplatform/tracing/perfetto-shared-memory.cc deleted file mode 100644 index 6c31c05070..0000000000 --- a/deps/v8/src/libplatform/tracing/perfetto-shared-memory.cc +++ /dev/null @@ -1,28 +0,0 @@ -// 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-shared-memory.h" - -#include "src/base/platform/platform.h" -#include "src/base/template-utils.h" - -namespace v8 { -namespace platform { -namespace tracing { - -PerfettoSharedMemory::PerfettoSharedMemory(size_t size) - : size_(size), - paged_memory_(::perfetto::base::PagedMemory::Allocate(size)) { - // TODO(956543): Find a cross-platform solution. - // TODO(petermarshall): Don't assume that size is page-aligned. -} - -std::unique_ptr<::perfetto::SharedMemory> -PerfettoSharedMemoryFactory::CreateSharedMemory(size_t size) { - return base::make_unique<PerfettoSharedMemory>(size); -} - -} // namespace tracing -} // namespace platform -} // namespace v8 diff --git a/deps/v8/src/libplatform/tracing/perfetto-shared-memory.h b/deps/v8/src/libplatform/tracing/perfetto-shared-memory.h deleted file mode 100644 index 7a987cc7f0..0000000000 --- a/deps/v8/src/libplatform/tracing/perfetto-shared-memory.h +++ /dev/null @@ -1,45 +0,0 @@ -// 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. - -#ifndef V8_LIBPLATFORM_TRACING_PERFETTO_SHARED_MEMORY_H_ -#define V8_LIBPLATFORM_TRACING_PERFETTO_SHARED_MEMORY_H_ - -#include "perfetto/tracing/core/shared_memory.h" - -#include "third_party/perfetto/include/perfetto/base/paged_memory.h" - -namespace v8 { -namespace platform { -namespace tracing { - -// Perfetto requires a shared memory implementation for multi-process embedders -// but V8 is single process. We implement it here using PagedMemory from -// perfetto. -class PerfettoSharedMemory : public ::perfetto::SharedMemory { - public: - explicit PerfettoSharedMemory(size_t size); - - // The PagedMemory destructor will free the underlying memory when this object - // is destroyed. - - void* start() const override { return paged_memory_.Get(); } - size_t size() const override { return size_; } - - private: - size_t size_; - ::perfetto::base::PagedMemory paged_memory_; -}; - -class PerfettoSharedMemoryFactory : public ::perfetto::SharedMemory::Factory { - public: - ~PerfettoSharedMemoryFactory() override = default; - std::unique_ptr<::perfetto::SharedMemory> CreateSharedMemory( - size_t size) override; -}; - -} // namespace tracing -} // namespace platform -} // namespace v8 - -#endif // V8_LIBPLATFORM_TRACING_PERFETTO_SHARED_MEMORY_H_ diff --git a/deps/v8/src/libplatform/tracing/perfetto-tasks.cc b/deps/v8/src/libplatform/tracing/perfetto-tasks.cc deleted file mode 100644 index 70d00ed626..0000000000 --- a/deps/v8/src/libplatform/tracing/perfetto-tasks.cc +++ /dev/null @@ -1,52 +0,0 @@ -// 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-tasks.h" - -#include "src/base/platform/semaphore.h" -#include "src/base/platform/time.h" - -namespace v8 { -namespace platform { -namespace tracing { - -PerfettoTaskRunner::PerfettoTaskRunner() : runner_(1, DefaultTimeFunction) {} - -PerfettoTaskRunner::~PerfettoTaskRunner() { runner_.Terminate(); } - -// static -double PerfettoTaskRunner::DefaultTimeFunction() { - return (base::TimeTicks::HighResolutionNow() - base::TimeTicks()) - .InSecondsF(); -} - -void PerfettoTaskRunner::PostTask(std::function<void()> f) { - runner_.PostTask(base::make_unique<TracingTask>(std::move(f))); -} - -void PerfettoTaskRunner::PostDelayedTask(std::function<void()> f, - uint32_t delay_ms) { - double delay_in_seconds = - delay_ms / static_cast<double>(base::Time::kMillisecondsPerSecond); - runner_.PostDelayedTask(base::make_unique<TracingTask>(std::move(f)), - delay_in_seconds); -} - -bool PerfettoTaskRunner::RunsTasksOnCurrentThread() const { - return runner_.RunsTasksOnCurrentThread(); -} - -void PerfettoTaskRunner::FinishImmediateTasks() { - DCHECK(!RunsTasksOnCurrentThread()); - base::Semaphore semaphore(0); - // PostTask has guaranteed ordering so this will be the last task executed. - runner_.PostTask( - base::make_unique<TracingTask>([&semaphore] { semaphore.Signal(); })); - - semaphore.Wait(); -} - -} // namespace tracing -} // namespace platform -} // namespace v8 diff --git a/deps/v8/src/libplatform/tracing/perfetto-tasks.h b/deps/v8/src/libplatform/tracing/perfetto-tasks.h deleted file mode 100644 index 054a9e157a..0000000000 --- a/deps/v8/src/libplatform/tracing/perfetto-tasks.h +++ /dev/null @@ -1,55 +0,0 @@ -// 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. - -#ifndef V8_LIBPLATFORM_TRACING_PERFETTO_TASKS_H_ -#define V8_LIBPLATFORM_TRACING_PERFETTO_TASKS_H_ - -#include <functional> - -#include "include/v8-platform.h" -#include "perfetto/base/task_runner.h" -#include "src/libplatform/default-worker-threads-task-runner.h" - -namespace v8 { -namespace platform { -namespace tracing { - -class TracingTask : public Task { - public: - explicit TracingTask(std::function<void()> f) : f_(std::move(f)) {} - - void Run() override { f_(); } - - private: - std::function<void()> f_; -}; - -class PerfettoTaskRunner : public ::perfetto::base::TaskRunner { - public: - PerfettoTaskRunner(); - ~PerfettoTaskRunner() override; - - // ::perfetto::base::TaskRunner implementation - void PostTask(std::function<void()> f) override; - void PostDelayedTask(std::function<void()> f, uint32_t delay_ms) override; - void AddFileDescriptorWatch(int fd, std::function<void()>) override { - UNREACHABLE(); - } - void RemoveFileDescriptorWatch(int fd) override { UNREACHABLE(); } - bool RunsTasksOnCurrentThread() const override; - - // PerfettoTaskRunner implementation - void FinishImmediateTasks(); - - private: - static double DefaultTimeFunction(); - - DefaultWorkerThreadsTaskRunner runner_; -}; - -} // namespace tracing -} // namespace platform -} // namespace v8 - -#endif // V8_LIBPLATFORM_TRACING_PERFETTO_TASKS_H_ diff --git a/deps/v8/src/libplatform/tracing/perfetto-tracing-controller.cc b/deps/v8/src/libplatform/tracing/perfetto-tracing-controller.cc deleted file mode 100644 index 9b62c2ae78..0000000000 --- a/deps/v8/src/libplatform/tracing/perfetto-tracing-controller.cc +++ /dev/null @@ -1,130 +0,0 @@ -// 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-tracing-controller.h" - -#include "perfetto/tracing/core/trace_config.h" -#include "perfetto/tracing/core/trace_writer.h" -#include "perfetto/tracing/core/tracing_service.h" -#include "src/libplatform/tracing/perfetto-consumer.h" -#include "src/libplatform/tracing/perfetto-producer.h" -#include "src/libplatform/tracing/perfetto-shared-memory.h" -#include "src/libplatform/tracing/perfetto-tasks.h" -#include "src/libplatform/tracing/trace-event-listener.h" - -namespace v8 { -namespace platform { -namespace tracing { - -PerfettoTracingController::PerfettoTracingController() - : writer_key_(base::Thread::CreateThreadLocalKey()), - producer_ready_semaphore_(0), - consumer_finished_semaphore_(0) {} - -void PerfettoTracingController::StartTracing( - const ::perfetto::TraceConfig& trace_config) { - DCHECK(!task_runner_); - task_runner_ = base::make_unique<PerfettoTaskRunner>(); - // The Perfetto service expects calls on the task runner thread which is why - // the setup below occurs in posted tasks. - task_runner_->PostTask([&trace_config, this] { - std::unique_ptr<::perfetto::SharedMemory::Factory> shmem_factory = - base::make_unique<PerfettoSharedMemoryFactory>(); - - service_ = ::perfetto::TracingService::CreateInstance( - std::move(shmem_factory), task_runner_.get()); - // This allows Perfetto to recover trace events that were written by - // TraceWriters which have not yet been deleted. This allows us to keep - // TraceWriters alive past the end of tracing, rather than having to delete - // them all when tracing stops which would require synchronization on every - // trace event. Eventually we will delete TraceWriters when threads die, but - // for now we just leak all TraceWriters. - service_->SetSMBScrapingEnabled(true); - producer_ = base::make_unique<PerfettoProducer>(this); - consumer_ = - base::make_unique<PerfettoConsumer>(&consumer_finished_semaphore_); - - for (TraceEventListener* listener : listeners_) { - consumer_->AddTraceEventListener(listener); - } - - producer_->set_service_endpoint(service_->ConnectProducer( - producer_.get(), 0, "v8.perfetto-producer", 0, true)); - - consumer_->set_service_endpoint( - service_->ConnectConsumer(consumer_.get(), 0)); - - // We need to wait for the OnConnected() callbacks of the producer and - // consumer to be called. - consumer_->service_endpoint()->EnableTracing(trace_config); - }); - - producer_ready_semaphore_.Wait(); -} - -void PerfettoTracingController::StopTracing() { - // Finish all of the tasks such as existing AddTraceEvent calls. These - // require the data structures below to work properly, so keep them alive - // until the tasks are done. - task_runner_->FinishImmediateTasks(); - - task_runner_->PostTask([this] { - // Trigger shared memory buffer scraping which will get all pending trace - // events that have been written by still-living TraceWriters. - consumer_->service_endpoint()->DisableTracing(); - // Trigger the consumer to finish. This can trigger multiple calls to - // PerfettoConsumer::OnTraceData(), with the final call passing has_more - // as false. - consumer_->service_endpoint()->ReadBuffers(); - }); - - // Wait until the final OnTraceData() call with has_more=false has completed. - consumer_finished_semaphore_.Wait(); - - task_runner_->PostTask([this] { - consumer_.reset(); - producer_.reset(); - service_.reset(); - }); - - // Finish the above task, and any callbacks that were triggered. - task_runner_->FinishImmediateTasks(); - task_runner_.reset(); -} - -void PerfettoTracingController::AddTraceEventListener( - TraceEventListener* listener) { - listeners_.push_back(listener); -} - -PerfettoTracingController::~PerfettoTracingController() { - base::Thread::DeleteThreadLocalKey(writer_key_); -} - -::perfetto::TraceWriter* -PerfettoTracingController::GetOrCreateThreadLocalWriter() { - // TODO(petermarshall): Use some form of thread-local destructor so that - // repeatedly created threads don't cause excessive leaking of TraceWriters. - if (base::Thread::HasThreadLocal(writer_key_)) { - return static_cast<::perfetto::TraceWriter*>( - base::Thread::GetExistingThreadLocal(writer_key_)); - } - - // We leak the TraceWriter objects created for each thread. Perfetto has a - // way of getting events from leaked TraceWriters and we can avoid needing a - // lock on every trace event this way. - std::unique_ptr<::perfetto::TraceWriter> tw = producer_->CreateTraceWriter(); - ::perfetto::TraceWriter* writer = tw.release(); - - base::Thread::SetThreadLocal(writer_key_, writer); - return writer; -} - -void PerfettoTracingController::OnProducerReady() { - producer_ready_semaphore_.Signal(); -} - -} // namespace tracing -} // namespace platform -} // namespace v8 diff --git a/deps/v8/src/libplatform/tracing/perfetto-tracing-controller.h b/deps/v8/src/libplatform/tracing/perfetto-tracing-controller.h deleted file mode 100644 index 67a3c26cef..0000000000 --- a/deps/v8/src/libplatform/tracing/perfetto-tracing-controller.h +++ /dev/null @@ -1,86 +0,0 @@ -// 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. - -#ifndef V8_LIBPLATFORM_TRACING_PERFETTO_TRACING_CONTROLLER_H_ -#define V8_LIBPLATFORM_TRACING_PERFETTO_TRACING_CONTROLLER_H_ - -#include <atomic> -#include <fstream> -#include <memory> -#include <vector> - -#include "src/base/platform/platform.h" -#include "src/base/platform/semaphore.h" - -namespace perfetto { -class TraceConfig; -class TraceWriter; -class TracingService; -} // namespace perfetto - -namespace v8 { -namespace platform { -namespace tracing { - -class PerfettoConsumer; -class PerfettoProducer; -class PerfettoTaskRunner; -class TraceEventListener; - -// This is the top-level interface for performing tracing with perfetto. The -// user of this class should call StartTracing() to start tracing, and -// StopTracing() to stop it. To write trace events, the user can obtain a -// thread-local TraceWriter object using GetOrCreateThreadLocalWriter(). -class PerfettoTracingController { - public: - PerfettoTracingController(); - - // Blocks and sets up all required data structures for tracing. It is safe to - // call GetOrCreateThreadLocalWriter() to obtain thread-local TraceWriters for - // writing trace events once this call returns. Tracing output will be sent to - // the TraceEventListeners registered via AddTraceEventListener(). - void StartTracing(const ::perfetto::TraceConfig& trace_config); - - // Blocks and finishes all existing AddTraceEvent tasks. Stops the tracing - // thread. - void StopTracing(); - - // Register a trace event listener that will receive trace events. This can be - // called multiple times to register multiple listeners, but must be called - // before starting tracing. - void AddTraceEventListener(TraceEventListener* listener); - - ~PerfettoTracingController(); - - // Each thread that wants to trace should call this to get their TraceWriter. - // PerfettoTracingController creates and owns the TraceWriter. - ::perfetto::TraceWriter* GetOrCreateThreadLocalWriter(); - - private: - // Signals the producer_ready_semaphore_. - void OnProducerReady(); - - // PerfettoProducer is the only class allowed to call OnProducerReady(). - friend class PerfettoProducer; - - std::unique_ptr<::perfetto::TracingService> service_; - std::unique_ptr<PerfettoProducer> producer_; - std::unique_ptr<PerfettoConsumer> consumer_; - std::unique_ptr<PerfettoTaskRunner> task_runner_; - std::vector<TraceEventListener*> listeners_; - base::Thread::LocalStorageKey writer_key_; - // A semaphore that is signalled when StartRecording is called. StartTracing - // waits on this semaphore to be notified when the tracing service is ready to - // receive trace events. - base::Semaphore producer_ready_semaphore_; - base::Semaphore consumer_finished_semaphore_; - - DISALLOW_COPY_AND_ASSIGN(PerfettoTracingController); -}; - -} // namespace tracing -} // namespace platform -} // namespace v8 - -#endif // V8_LIBPLATFORM_TRACING_PERFETTO_TRACING_CONTROLLER_H_ diff --git a/deps/v8/src/libplatform/tracing/trace-event-listener.cc b/deps/v8/src/libplatform/tracing/trace-event-listener.cc new file mode 100644 index 0000000000..8224221228 --- /dev/null +++ b/deps/v8/src/libplatform/tracing/trace-event-listener.cc @@ -0,0 +1,27 @@ +// 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/trace-event-listener.h" + +#include "perfetto/trace/trace.pb.h" +#include "src/base/logging.h" + +namespace v8 { +namespace platform { +namespace tracing { + +void TraceEventListener::ParseFromArray(const std::vector<char>& array) { + perfetto::protos::Trace trace; + CHECK(trace.ParseFromArray(array.data(), static_cast<int>(array.size()))); + + for (int i = 0; i < trace.packet_size(); i++) { + // TODO(petermarshall): ChromeTracePacket instead. + const perfetto::protos::TracePacket& packet = trace.packet(i); + ProcessPacket(packet); + } +} + +} // namespace tracing +} // namespace platform +} // namespace v8 diff --git a/deps/v8/src/libplatform/tracing/trace-event-listener.h b/deps/v8/src/libplatform/tracing/trace-event-listener.h index 4acdb2935b..6a535c79c5 100644 --- a/deps/v8/src/libplatform/tracing/trace-event-listener.h +++ b/deps/v8/src/libplatform/tracing/trace-event-listener.h @@ -5,9 +5,11 @@ #ifndef V8_LIBPLATFORM_TRACING_TRACE_EVENT_LISTENER_H_ #define V8_LIBPLATFORM_TRACING_TRACE_EVENT_LISTENER_H_ +#include <vector> + namespace perfetto { namespace protos { -class ChromeTracePacket; +class TracePacket; } // namespace protos } // namespace perfetto @@ -23,8 +25,9 @@ namespace tracing { class TraceEventListener { public: virtual ~TraceEventListener() = default; - virtual void ProcessPacket( - const ::perfetto::protos::ChromeTracePacket& packet) = 0; + virtual void ProcessPacket(const ::perfetto::protos::TracePacket& packet) = 0; + + void ParseFromArray(const std::vector<char>& array); }; } // namespace tracing diff --git a/deps/v8/src/libplatform/tracing/tracing-controller.cc b/deps/v8/src/libplatform/tracing/tracing-controller.cc index 91d042ba1e..0700e34825 100644 --- a/deps/v8/src/libplatform/tracing/tracing-controller.cc +++ b/deps/v8/src/libplatform/tracing/tracing-controller.cc @@ -16,12 +16,25 @@ #include "base/trace_event/common/trace_event_common.h" #include "perfetto/trace/chrome/chrome_trace_event.pbzero.h" #include "perfetto/trace/trace_packet.pbzero.h" -#include "perfetto/tracing/core/data_source_config.h" -#include "perfetto/tracing/core/trace_config.h" -#include "perfetto/tracing/core/trace_packet.h" -#include "perfetto/tracing/core/trace_writer.h" +#include "perfetto/tracing.h" +#include "src/base/platform/platform.h" +#include "src/base/platform/semaphore.h" #include "src/libplatform/tracing/json-trace-event-listener.h" -#include "src/libplatform/tracing/perfetto-tracing-controller.h" +#endif // V8_USE_PERFETTO + +#ifdef V8_USE_PERFETTO +class V8DataSource : public perfetto::DataSource<V8DataSource> { + public: + void OnSetup(const SetupArgs&) override {} + void OnStart(const StartArgs&) override { started_.Signal(); } + void OnStop(const StopArgs&) override {} + + static v8::base::Semaphore started_; +}; + +v8::base::Semaphore V8DataSource::started_{0}; + +PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(V8DataSource); #endif // V8_USE_PERFETTO namespace v8 { @@ -79,6 +92,7 @@ void TracingController::InitializeForPerfetto(std::ostream* output_stream) { output_stream_ = output_stream; DCHECK_NOT_NULL(output_stream); DCHECK(output_stream->good()); + mutex_.reset(new base::Mutex()); } void TracingController::SetTraceEventListenerForTesting( @@ -133,7 +147,9 @@ void AddArgsToTraceProto( case TRACE_VALUE_TYPE_POINTER: arg->set_pointer_value(arg_value.as_uint); break; - // TODO(petermarshall): Treat copy strings specially. + // There is no difference between copy strings and regular strings for + // Perfetto; the set_string_value(const char*) API will copy the string + // into the protobuf by default. case TRACE_VALUE_TYPE_COPY_STRING: case TRACE_VALUE_TYPE_STRING: arg->set_string_value(arg_value.as_string); @@ -171,44 +187,40 @@ uint64_t TracingController::AddTraceEventWithTimestamp( int64_t cpu_now_us = CurrentCpuTimestampMicroseconds(); #ifdef V8_USE_PERFETTO - if (perfetto_recording_.load()) { // Don't use COMPLETE events with perfetto - instead transform them into // BEGIN/END pairs. This avoids the need for a thread-local stack of pending // trace events as perfetto does not support handles into the trace buffer. if (phase == TRACE_EVENT_PHASE_COMPLETE) phase = TRACE_EVENT_PHASE_BEGIN; - ::perfetto::TraceWriter* writer = - perfetto_tracing_controller_->GetOrCreateThreadLocalWriter(); - // TODO(petermarshall): We shouldn't start one packet for each event. - // We should try to bundle them together in one bundle. - auto packet = writer->NewTracePacket(); - auto* trace_event_bundle = packet->set_chrome_events(); - auto* trace_event = trace_event_bundle->add_trace_events(); - - trace_event->set_name(name); - trace_event->set_timestamp(timestamp); - trace_event->set_phase(phase); - trace_event->set_thread_id(base::OS::GetCurrentThreadId()); - trace_event->set_duration(0); - trace_event->set_thread_duration(0); - if (scope) trace_event->set_scope(scope); - trace_event->set_id(id); - trace_event->set_flags(flags); - if (category_enabled_flag) { - const char* category_group_name = - GetCategoryGroupName(category_enabled_flag); - DCHECK_NOT_NULL(category_group_name); - trace_event->set_category_group_name(category_group_name); - } - trace_event->set_process_id(base::OS::GetCurrentProcessId()); - trace_event->set_thread_timestamp(cpu_now_us); - trace_event->set_bind_id(bind_id); - AddArgsToTraceProto(trace_event, num_args, arg_names, arg_types, arg_values, - arg_convertables); + V8DataSource::Trace([&](V8DataSource::TraceContext ctx) { + auto packet = ctx.NewTracePacket(); + auto* trace_event_bundle = packet->set_chrome_events(); + auto* trace_event = trace_event_bundle->add_trace_events(); + + trace_event->set_name(name); + trace_event->set_timestamp(timestamp); + trace_event->set_phase(phase); + trace_event->set_thread_id(base::OS::GetCurrentThreadId()); + trace_event->set_duration(0); + trace_event->set_thread_duration(0); + if (scope) trace_event->set_scope(scope); + trace_event->set_id(id); + trace_event->set_flags(flags); + if (category_enabled_flag) { + const char* category_group_name = + GetCategoryGroupName(category_enabled_flag); + DCHECK_NOT_NULL(category_group_name); + trace_event->set_category_group_name(category_group_name); + } + trace_event->set_process_id(base::OS::GetCurrentProcessId()); + trace_event->set_thread_timestamp(cpu_now_us); + trace_event->set_bind_id(bind_id); - packet->Finalize(); - } -#endif // V8_USE_PERFETTO + AddArgsToTraceProto(trace_event, num_args, arg_names, arg_types, + arg_values, arg_convertables); + }); + return 0; +#else uint64_t handle = 0; if (recording_.load(std::memory_order_acquire)) { @@ -224,6 +236,7 @@ uint64_t TracingController::AddTraceEventWithTimestamp( } } return handle; +#endif // V8_USE_PERFETTO } void TracingController::UpdateTraceEventDuration( @@ -232,15 +245,8 @@ void TracingController::UpdateTraceEventDuration( int64_t cpu_now_us = CurrentCpuTimestampMicroseconds(); #ifdef V8_USE_PERFETTO - // TODO(petermarshall): Should we still record the end of unfinished events - // when tracing has stopped? - if (perfetto_recording_.load()) { - // TODO(petermarshall): We shouldn't start one packet for each event. We - // should try to bundle them together in one bundle. - ::perfetto::TraceWriter* writer = - perfetto_tracing_controller_->GetOrCreateThreadLocalWriter(); - - auto packet = writer->NewTracePacket(); + V8DataSource::Trace([&](V8DataSource::TraceContext ctx) { + auto packet = ctx.NewTracePacket(); auto* trace_event_bundle = packet->set_chrome_events(); auto* trace_event = trace_event_bundle->add_trace_events(); @@ -249,14 +255,13 @@ void TracingController::UpdateTraceEventDuration( trace_event->set_timestamp(now_us); trace_event->set_process_id(base::OS::GetCurrentProcessId()); trace_event->set_thread_timestamp(cpu_now_us); - - packet->Finalize(); - } -#endif // V8_USE_PERFETTO + }); +#else TraceObject* trace_object = trace_buffer_->GetEventByHandle(handle); if (!trace_object) return; trace_object->UpdateDuration(now_us, cpu_now_us); +#endif // V8_USE_PERFETTO } const char* TracingController::GetCategoryGroupName( @@ -277,24 +282,27 @@ const char* TracingController::GetCategoryGroupName( void TracingController::StartTracing(TraceConfig* trace_config) { #ifdef V8_USE_PERFETTO - perfetto_tracing_controller_ = base::make_unique<PerfettoTracingController>(); - - if (listener_for_testing_) { - perfetto_tracing_controller_->AddTraceEventListener(listener_for_testing_); - } DCHECK_NOT_NULL(output_stream_); DCHECK(output_stream_->good()); json_listener_ = base::make_unique<JSONTraceEventListener>(output_stream_); - perfetto_tracing_controller_->AddTraceEventListener(json_listener_.get()); - ::perfetto::TraceConfig perfetto_trace_config; + // TODO(petermarshall): Set other the params for the config. + ::perfetto::TraceConfig perfetto_trace_config; perfetto_trace_config.add_buffers()->set_size_kb(4096); auto* ds_config = perfetto_trace_config.add_data_sources()->mutable_config(); ds_config->set_name("v8.trace_events"); - // TODO(petermarshall): Set all the params from |perfetto_trace_config|. - perfetto_tracing_controller_->StartTracing(perfetto_trace_config); - perfetto_recording_.store(true); + perfetto::DataSourceDescriptor dsd; + dsd.set_name("v8.trace_events"); + V8DataSource::Register(dsd); + + tracing_session_ = + perfetto::Tracing::NewTrace(perfetto::BackendType::kUnspecifiedBackend); + tracing_session_->Setup(perfetto_trace_config); + // TODO(petermarshall): Switch to StartBlocking when available. + tracing_session_->Start(); + V8DataSource::started_.Wait(); + #endif // V8_USE_PERFETTO trace_config_.reset(trace_config); @@ -315,7 +323,6 @@ void TracingController::StopTracing() { if (!recording_.compare_exchange_strong(expected, false)) { return; } - DCHECK(trace_buffer_); UpdateCategoryGroupEnabledFlags(); std::unordered_set<v8::TracingController::TraceStateObserver*> observers_copy; { @@ -327,16 +334,24 @@ void TracingController::StopTracing() { } #ifdef V8_USE_PERFETTO - perfetto_recording_.store(false); - perfetto_tracing_controller_->StopTracing(); - perfetto_tracing_controller_.reset(); + base::Semaphore stopped_{0}; + tracing_session_->SetOnStopCallback([&stopped_]() { stopped_.Signal(); }); + tracing_session_->Stop(); + stopped_.Wait(); + + std::vector<char> trace = tracing_session_->ReadTraceBlocking(); + json_listener_->ParseFromArray(trace); + if (listener_for_testing_) listener_for_testing_->ParseFromArray(trace); + json_listener_.reset(); -#endif // V8_USE_PERFETTO +#else { base::MutexGuard lock(mutex_.get()); + DCHECK(trace_buffer_); trace_buffer_->Flush(); } +#endif // V8_USE_PERFETTO } void TracingController::UpdateCategoryGroupEnabledFlag(size_t category_index) { |