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:
Chinmay Garde
2015-08-13 12:58:54 -07:00
16 changed files with 277 additions and 142 deletions
+1 -1
View File
@@ -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',
+41
View File
@@ -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
+3
View File
@@ -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();
+8
View File
@@ -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
+3
View File
@@ -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
View File
@@ -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)
-19
View File
@@ -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__) */
-120
View File
@@ -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
+4
View File
@@ -85,5 +85,9 @@ Shell& Shell::Shared() {
return *g_shell;
}
TracingController& Shell::tracing_controller() {
return tracing_controller_;
}
} // namespace shell
} // namespace sky
+4
View File
@@ -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);
};
+14
View File
@@ -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
+4
View File
@@ -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();
+120
View File
@@ -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
+61
View File
@@ -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__) */
+8
View File
@@ -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
+4
View File
@@ -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;