mirror of
https://github.com/encounter/engine.git
synced 2026-03-30 11:09:55 -07:00
Merge pull request #578 from chinmaygarde/master
Make |TracingController| platform agnostic and enable collecting traces from base and the shell view dart isolate simultaneously
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
vars = {
|
||||
'chromium_git': 'https://chromium.googlesource.com',
|
||||
'skia_revision': '29ccdf86ab0a1649fd775c9431891bacb1391e99',
|
||||
'dart_revision': '2d6e6db8437eaaa364f3d5b599afb6804e93f65f',
|
||||
'dart_revision': 'cf41336f42713e64ef133f6f2f81ca81db022ad2',
|
||||
'dart_observatory_packages_revision': 'cdc4b3d4c15b9c0c8e7702dff127b440afbb7485',
|
||||
|
||||
'buildtools_revision': '5215ee866bc3e8eb4a7f124212845abf4029e60b',
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#include "base/logging.h"
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "dart/runtime/include/dart_tools_api.h"
|
||||
#include "mojo/common/data_pipe_utils.h"
|
||||
#include "mojo/public/cpp/system/data_pipe.h"
|
||||
#include "sky/engine/bindings/builtin.h"
|
||||
#include "sky/engine/bindings/builtin_natives.h"
|
||||
#include "sky/engine/bindings/builtin_sky.h"
|
||||
@@ -156,4 +159,42 @@ void DartController::InstallView(View* view) {
|
||||
builtin_sky_->InstallView(view);
|
||||
}
|
||||
|
||||
static void DartController_DartStreamConsumer(
|
||||
Dart_StreamConsumer_State state,
|
||||
const char* stream_name,
|
||||
uint8_t* buffer,
|
||||
intptr_t buffer_length,
|
||||
mojo::ScopedDataPipeProducerHandle *handle) {
|
||||
|
||||
if (!handle->is_valid()) {
|
||||
// Simple flush. Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == Dart_StreamConsumer_kData) {
|
||||
const std::string data(reinterpret_cast<const char*>(buffer),
|
||||
buffer_length);
|
||||
mojo::common::BlockingCopyFromString(data, *handle);
|
||||
}
|
||||
}
|
||||
|
||||
void DartController::StartTracing() {
|
||||
DartIsolateScope isolate_scope(dart_state()->isolate());
|
||||
DartApiScope dart_api_scope;
|
||||
|
||||
Dart_TimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
|
||||
}
|
||||
|
||||
void DartController::StopTracing(
|
||||
mojo::ScopedDataPipeProducerHandle producer) {
|
||||
DartIsolateScope isolate_scope(dart_state()->isolate());
|
||||
DartApiScope dart_api_scope;
|
||||
|
||||
Dart_TimelineSetRecordedStreams(DART_TIMELINE_STREAM_DISABLE);
|
||||
|
||||
auto callback =
|
||||
reinterpret_cast<Dart_StreamConsumer>(&DartController_DartStreamConsumer);
|
||||
Dart_TimelineGetTrace(callback, &producer);
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@@ -41,6 +41,9 @@ class DartController {
|
||||
|
||||
DOMDartState* dart_state() const { return dom_dart_state_.get(); }
|
||||
|
||||
void StartTracing();
|
||||
void StopTracing(mojo::ScopedDataPipeProducerHandle producer);
|
||||
|
||||
private:
|
||||
void DidLoadMainLibrary(String url);
|
||||
void DidLoadSnapshot();
|
||||
|
||||
@@ -101,4 +101,12 @@ void SkyView::ScheduleFrame() {
|
||||
client_->ScheduleFrame();
|
||||
}
|
||||
|
||||
void SkyView::StartDartTracing() {
|
||||
dart_controller_->StartTracing();
|
||||
}
|
||||
|
||||
void SkyView::StopDartTracing(mojo::ScopedDataPipeProducerHandle producer) {
|
||||
dart_controller_->StopTracing(producer.Pass());
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@@ -43,6 +43,9 @@ class SkyView {
|
||||
PassRefPtr<SkPicture> Paint();
|
||||
void HandleInputEvent(const WebInputEvent& event);
|
||||
|
||||
void StartDartTracing();
|
||||
void StopDartTracing(mojo::ScopedDataPipeProducerHandle producer);
|
||||
|
||||
private:
|
||||
explicit SkyView(SkyViewClient* client);
|
||||
|
||||
|
||||
+2
-2
@@ -48,6 +48,8 @@ source_set("common") {
|
||||
"shell_view.h",
|
||||
"switches.cc",
|
||||
"switches.h",
|
||||
"tracing_controller.cc",
|
||||
"tracing_controller.h",
|
||||
"ui/animator.cc",
|
||||
"ui/animator.h",
|
||||
"ui/engine.cc",
|
||||
@@ -191,8 +193,6 @@ if (is_android) {
|
||||
"mac/platform_service_provider_mac.cc",
|
||||
"mac/platform_view_mac.h",
|
||||
"mac/platform_view_mac.mm",
|
||||
"mac/tracing_controller.h",
|
||||
"mac/tracing_controller.mm",
|
||||
]
|
||||
set_sources_assignment_filter(sources_assignment_filter)
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
#ifndef __SKY_SHELL_MAC_TRACINGCONTROLLER__
|
||||
#define __SKY_SHELL_MAC_TRACINGCONTROLLER__
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface TracingController : NSObject
|
||||
|
||||
+ (instancetype)sharedController;
|
||||
|
||||
- (void)startTracing;
|
||||
- (void)stopTracing;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* defined(__SKY_SHELL_MAC_TRACINGCONTROLLER__) */
|
||||
@@ -1,120 +0,0 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
#import "tracing_controller.h"
|
||||
#include <string>
|
||||
#include "base/macros.h"
|
||||
#include "base/trace_event/trace_config.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
|
||||
@interface TracingController ()
|
||||
@property(nonatomic, retain) NSFileHandle* currentFileHandle;
|
||||
@end
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
|
||||
const char kStart[] = "{\"traceEvents\":[";
|
||||
const char kEnd[] = "]}";
|
||||
|
||||
static void Write(const std::string& data) {
|
||||
NSFileHandle* handle = [TracingController sharedController].currentFileHandle;
|
||||
[handle writeData:[NSData dataWithBytesNoCopy:(void*)data.data()
|
||||
length:data.size()
|
||||
freeWhenDone:false]];
|
||||
}
|
||||
|
||||
static void HandleChunk(const scoped_refptr<base::RefCountedString>& chunk,
|
||||
bool has_more_events) {
|
||||
Write(chunk->data());
|
||||
|
||||
if (has_more_events) {
|
||||
Write(",");
|
||||
} else {
|
||||
Write(kEnd);
|
||||
[TracingController sharedController].currentFileHandle = nil;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
||||
|
||||
@implementation TracingController
|
||||
|
||||
@synthesize currentFileHandle = _currentFileHandle;
|
||||
|
||||
+ (instancetype)sharedController {
|
||||
static TracingController* controller = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
controller = [[TracingController alloc] init];
|
||||
});
|
||||
return controller;
|
||||
}
|
||||
|
||||
- (void)startTracing {
|
||||
// Start Tracing
|
||||
NSLog(@"Staring Trace");
|
||||
|
||||
base::trace_event::TraceLog::GetInstance()->SetEnabled(
|
||||
base::trace_event::TraceConfig("*", base::trace_event::RECORD_UNTIL_FULL),
|
||||
base::trace_event::TraceLog::RECORDING_MODE);
|
||||
}
|
||||
|
||||
- (void)stopTracing {
|
||||
// Stop Tracing
|
||||
NSLog(@"Stopping Trace");
|
||||
base::trace_event::TraceLog::GetInstance()->SetDisabled();
|
||||
|
||||
// Save Trace File
|
||||
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
|
||||
NSUserDomainMask, YES);
|
||||
if (paths.count == 0) {
|
||||
NSLog(@"Error: Could not find documents directory to write the trace file "
|
||||
@"to");
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare a file path that looks sane in the documents directory
|
||||
NSURL* pathURL = [NSURL URLWithString:paths[0]];
|
||||
NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
|
||||
[formatter setDateFormat:@"hh_mm_s"];
|
||||
NSString* dateString =
|
||||
[NSString stringWithFormat:@"Trace_%@.json",
|
||||
[formatter stringFromDate:[NSDate date]]];
|
||||
[formatter release];
|
||||
NSURL* fileURL = [NSURL URLWithString:dateString relativeToURL:pathURL];
|
||||
NSError* error = nil;
|
||||
|
||||
// Create the file in the documents directory
|
||||
BOOL created =
|
||||
[[NSFileManager defaultManager] createFileAtPath:fileURL.absoluteString
|
||||
contents:nil
|
||||
attributes:nil];
|
||||
if (!created) {
|
||||
NSLog(@"Error: Could not create file for writing trace file to");
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch a write handle to the created file
|
||||
NSFileHandle* handle =
|
||||
[NSFileHandle fileHandleForWritingToURL:fileURL error:&error];
|
||||
if (error != nil) {
|
||||
NSLog(@"Error: Could not write trace file to documents directory: %@",
|
||||
error.localizedDescription);
|
||||
return;
|
||||
}
|
||||
|
||||
self.currentFileHandle = handle;
|
||||
sky::shell::Write(sky::shell::kStart);
|
||||
auto log = base::trace_event::TraceLog::GetInstance();
|
||||
log->Flush(base::Bind(&sky::shell::HandleChunk));
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_currentFileHandle release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -85,5 +85,9 @@ Shell& Shell::Shared() {
|
||||
return *g_shell;
|
||||
}
|
||||
|
||||
TracingController& Shell::tracing_controller() {
|
||||
return tracing_controller_;
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/threading/thread.h"
|
||||
#include "sky/shell/service_provider.h"
|
||||
#include "sky/shell/tracing_controller.h"
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
@@ -36,6 +37,8 @@ class Shell {
|
||||
return service_provider_context_.get();
|
||||
}
|
||||
|
||||
TracingController& tracing_controller();
|
||||
|
||||
private:
|
||||
explicit Shell(scoped_ptr<ServiceProviderContext> service_provider_context);
|
||||
|
||||
@@ -45,6 +48,7 @@ class Shell {
|
||||
scoped_ptr<base::Thread> gpu_thread_;
|
||||
scoped_ptr<base::Thread> ui_thread_;
|
||||
scoped_ptr<ServiceProviderContext> service_provider_context_;
|
||||
TracingController tracing_controller_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Shell);
|
||||
};
|
||||
|
||||
@@ -22,12 +22,14 @@ void Drop(scoped_ptr<T> ptr) { }
|
||||
|
||||
ShellView::ShellView(Shell& shell)
|
||||
: shell_(shell) {
|
||||
shell_.tracing_controller().RegisterShellView(this);
|
||||
rasterizer_.reset(new Rasterizer());
|
||||
CreateEngine();
|
||||
CreatePlatformView();
|
||||
}
|
||||
|
||||
ShellView::~ShellView() {
|
||||
shell_.tracing_controller().UnregisterShellView(this);
|
||||
shell_.gpu_task_runner()->PostTask(FROM_HERE,
|
||||
base::Bind(&Drop<Rasterizer>, base::Passed(&rasterizer_)));
|
||||
shell_.ui_task_runner()->PostTask(FROM_HERE,
|
||||
@@ -49,5 +51,17 @@ void ShellView::CreatePlatformView() {
|
||||
view_.reset(PlatformView::Create(config));
|
||||
}
|
||||
|
||||
void ShellView::StartDartTracing() {
|
||||
shell_.ui_task_runner()->PostTask(
|
||||
FROM_HERE, base::Bind(&Engine::StartDartTracing, engine_->GetWeakPtr()));
|
||||
}
|
||||
|
||||
void ShellView::StopDartTracing(
|
||||
mojo::ScopedDataPipeProducerHandle producer) {
|
||||
shell_.ui_task_runner()->PostTask(
|
||||
FROM_HERE, base::Bind(&Engine::StopDartTracing, engine_->GetWeakPtr(),
|
||||
base::Passed(&producer)));
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "mojo/public/cpp/system/data_pipe.h"
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
@@ -22,6 +23,9 @@ class ShellView {
|
||||
|
||||
PlatformView* view() const { return view_.get(); }
|
||||
|
||||
void StartDartTracing();
|
||||
void StopDartTracing(mojo::ScopedDataPipeProducerHandle producer);
|
||||
|
||||
private:
|
||||
void CreateEngine();
|
||||
void CreatePlatformView();
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
// Copyright 2015 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 "base/logging.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/trace_event/trace_config.h"
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "sky/shell/tracing_controller.h"
|
||||
#include "sky/shell/shell.h"
|
||||
#include <string>
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
|
||||
const char kBaseTraceStart[] = "{\"traceEvents\":[";
|
||||
const char kBaseTraceEnd[] = "]}";
|
||||
const char kSentinel[] = "\0";
|
||||
|
||||
TracingController::TracingController() : view_(nullptr) {}
|
||||
|
||||
TracingController::~TracingController() {}
|
||||
|
||||
void TracingController::StartTracing() {
|
||||
DLOG(INFO) << "Collecting Traces";
|
||||
|
||||
StartDartTracing();
|
||||
StartBaseTracing();
|
||||
}
|
||||
|
||||
void TracingController::StopTracing(const base::FilePath& path) {
|
||||
DLOG(INFO) << "Stopping trace collection";
|
||||
|
||||
trace_file_ = std::unique_ptr<base::File>(new base::File(
|
||||
path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE));
|
||||
|
||||
StopBaseTracing();
|
||||
}
|
||||
|
||||
void TracingController::OnDataAvailable(const void* data, size_t size) {
|
||||
if (trace_file_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace_file_->WriteAtCurrentPos(reinterpret_cast<const char*>(data), size);
|
||||
}
|
||||
|
||||
void TracingController::OnDataComplete() {
|
||||
trace_file_ = nullptr;
|
||||
drainer_ = nullptr;
|
||||
}
|
||||
|
||||
void TracingController::StartDartTracing() {
|
||||
if (view_ != nullptr) {
|
||||
view_->StartDartTracing();
|
||||
}
|
||||
}
|
||||
|
||||
void TracingController::StopDartTracing() {
|
||||
mojo::DataPipe pipe;
|
||||
drainer_ = std::unique_ptr<mojo::common::DataPipeDrainer>(
|
||||
new mojo::common::DataPipeDrainer(this, pipe.consumer_handle.Pass()));
|
||||
if (view_ != nullptr) {
|
||||
view_->StopDartTracing(pipe.producer_handle.Pass());
|
||||
}
|
||||
}
|
||||
|
||||
void TracingController::StartBaseTracing() {
|
||||
base::trace_event::TraceLog::GetInstance()->SetEnabled(
|
||||
base::trace_event::TraceConfig("*", base::trace_event::RECORD_UNTIL_FULL),
|
||||
base::trace_event::TraceLog::RECORDING_MODE);
|
||||
}
|
||||
|
||||
void TracingController::StopBaseTracing() {
|
||||
base::trace_event::TraceLog* log = base::trace_event::TraceLog::GetInstance();
|
||||
log->SetDisabled();
|
||||
|
||||
if (trace_file_ != nullptr) {
|
||||
trace_file_->WriteAtCurrentPos(kBaseTraceStart,
|
||||
sizeof(kBaseTraceStart) - 1);
|
||||
}
|
||||
log->Flush(base::Bind(&TracingController::OnBaseTraceChunk));
|
||||
}
|
||||
|
||||
void TracingController::OnBaseTraceChunk(
|
||||
const scoped_refptr<base::RefCountedString>& chunk,
|
||||
bool has_more_events) {
|
||||
// Unfortunately, there does not seem to be a way to pass a user args
|
||||
// reference to the callback. So we make this static and use the |Shared()|
|
||||
// accessor
|
||||
TracingController& controller = Shell::Shared().tracing_controller();
|
||||
|
||||
if (controller.trace_file_ != nullptr) {
|
||||
std::string& str = chunk->data();
|
||||
controller.trace_file_->WriteAtCurrentPos(str.data(), str.size());
|
||||
if (has_more_events) {
|
||||
controller.trace_file_->WriteAtCurrentPos(",", 1);
|
||||
} else {
|
||||
controller.trace_file_->WriteAtCurrentPos(kBaseTraceEnd,
|
||||
sizeof(kBaseTraceEnd) - 1);
|
||||
controller.trace_file_->WriteAtCurrentPos(kSentinel,
|
||||
sizeof(kSentinel) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_more_events) {
|
||||
controller.StopDartTracing();
|
||||
}
|
||||
}
|
||||
|
||||
void TracingController::RegisterShellView(ShellView* view) {
|
||||
view_ = view;
|
||||
}
|
||||
|
||||
void TracingController::UnregisterShellView(ShellView* view) {
|
||||
view_ = nullptr;
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2015 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.
|
||||
|
||||
#ifndef __SKY_SHELL_TRACING_CONTROLLER__
|
||||
#define __SKY_SHELL_TRACING_CONTROLLER__
|
||||
|
||||
#include "base/files/file.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted_memory.h"
|
||||
#include "mojo/common/data_pipe_drainer.h"
|
||||
#include "mojo/public/cpp/system/data_pipe.h"
|
||||
#include "sky/shell/shell_view.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace sky {
|
||||
namespace shell {
|
||||
|
||||
class TracingController : public mojo::common::DataPipeDrainer::Client {
|
||||
public:
|
||||
TracingController();
|
||||
~TracingController() override;
|
||||
|
||||
void RegisterShellView(ShellView* view);
|
||||
void UnregisterShellView(ShellView* view);
|
||||
|
||||
// Enable tracing in base as well as the dart isolates attached to the shell
|
||||
// views
|
||||
void StartTracing();
|
||||
|
||||
// Stop tracing in base as well as the dart isolates attached to shell views
|
||||
// and dump the resulting trace to the specified path. Traces from various
|
||||
// sources are separated by a NULL character in the resulting file and must
|
||||
// be merged before viewing in the trace viewer
|
||||
void StopTracing(const base::FilePath& path);
|
||||
|
||||
private:
|
||||
std::unique_ptr<mojo::common::DataPipeDrainer> drainer_;
|
||||
std::unique_ptr<base::File> trace_file_;
|
||||
// TODO: Currently, only the last shell view is traced. When the shell gains
|
||||
// the ability to host multiple shell views, references to each must be stored
|
||||
// instead and trace data from each serialized to the output trace.
|
||||
ShellView* view_;
|
||||
|
||||
void StartDartTracing();
|
||||
void StartBaseTracing();
|
||||
void StopDartTracing();
|
||||
void StopBaseTracing();
|
||||
void OnDataAvailable(const void* data, size_t num_bytes) override;
|
||||
void OnDataComplete() override;
|
||||
static void OnBaseTraceChunk(
|
||||
const scoped_refptr<base::RefCountedString>& chunk,
|
||||
bool has_more_events);
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TracingController);
|
||||
};
|
||||
} // namespace shell
|
||||
} // namespace sky
|
||||
|
||||
#endif /* defined(__SKY_SHELL_TRACING_CONTROLLER__) */
|
||||
@@ -257,5 +257,13 @@ void Engine::RequestNavigateHistory(int32_t delta) {
|
||||
NOTIMPLEMENTED();
|
||||
}
|
||||
|
||||
void Engine::StartDartTracing() {
|
||||
sky_view_->StartDartTracing();
|
||||
}
|
||||
|
||||
void Engine::StopDartTracing(mojo::ScopedDataPipeProducerHandle producer) {
|
||||
sky_view_->StopDartTracing(producer.Pass());
|
||||
}
|
||||
|
||||
} // namespace shell
|
||||
} // namespace sky
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "mojo/public/cpp/bindings/binding.h"
|
||||
#include "mojo/public/cpp/system/core.h"
|
||||
#include "mojo/public/cpp/system/data_pipe.h"
|
||||
#include "mojo/public/interfaces/application/service_provider.mojom.h"
|
||||
#include "mojo/services/asset_bundle/public/interfaces/asset_bundle.mojom.h"
|
||||
#include "mojo/services/navigation/public/interfaces/navigation.mojom.h"
|
||||
@@ -56,6 +57,9 @@ class Engine : public UIDelegate,
|
||||
void BeginFrame(base::TimeTicks frame_time);
|
||||
PassRefPtr<SkPicture> Paint();
|
||||
|
||||
void StartDartTracing();
|
||||
void StopDartTracing(mojo::ScopedDataPipeProducerHandle producer);
|
||||
|
||||
private:
|
||||
// UIDelegate implementation:
|
||||
void ConnectToEngine(mojo::InterfaceRequest<SkyEngine> request) override;
|
||||
|
||||
Reference in New Issue
Block a user