| Index: runtime/observatory/lib/src/repositories/sample_profile.dart
|
| diff --git a/runtime/observatory/lib/src/repositories/sample_profile.dart b/runtime/observatory/lib/src/repositories/sample_profile.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..57521398484f5c402bb1069d60c19a0d750056b5
|
| --- /dev/null
|
| +++ b/runtime/observatory/lib/src/repositories/sample_profile.dart
|
| @@ -0,0 +1,137 @@
|
| +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file
|
| +
|
| +part of repositories;
|
| +
|
| +String _tagToString(M.SampleProfileTag tag) {
|
| + switch (tag) {
|
| + case M.SampleProfileTag.userVM: return 'UserVM';
|
| + case M.SampleProfileTag.userOnly: return 'UserOnly';
|
| + case M.SampleProfileTag.vmUser: return 'VMUser';
|
| + case M.SampleProfileTag.vmOnly: return 'VMOnly';
|
| + case M.SampleProfileTag.none: return 'None';
|
| + }
|
| + throw new Exception('Unknown SampleProfileTag: $tag');
|
| +}
|
| +
|
| +class SampleProfileLoadingProgressEvent
|
| + implements M.SampleProfileLoadingProgressEvent {
|
| + final SampleProfileLoadingProgress progress;
|
| + SampleProfileLoadingProgressEvent(this.progress);
|
| +}
|
| +
|
| +class SampleProfileLoadingProgress extends M.SampleProfileLoadingProgress {
|
| + StreamController<SampleProfileLoadingProgressEvent> _onProgress =
|
| + new StreamController<SampleProfileLoadingProgressEvent>.broadcast();
|
| + Stream<SampleProfileLoadingProgressEvent> get onProgress =>
|
| + _onProgress.stream;
|
| +
|
| + final S.Isolate isolate;
|
| + final S.Class cls;
|
| + final M.SampleProfileTag tag;
|
| + final bool clear;
|
| +
|
| + M.SampleProfileLoadingStatus _status = M.SampleProfileLoadingStatus.fetching;
|
| + double _progress = 0.0;
|
| + final Stopwatch _fetchingTime = new Stopwatch();
|
| + final Stopwatch _loadingTime = new Stopwatch();
|
| + CpuProfile _profile;
|
| +
|
| + M.SampleProfileLoadingStatus get status => _status;
|
| + double get progress => _progress;
|
| + Duration get fetchingTime => _fetchingTime.elapsed;
|
| + Duration get loadingTime => _loadingTime.elapsed;
|
| + CpuProfile get profile => _profile;
|
| +
|
| + SampleProfileLoadingProgress(this.isolate, this.tag,
|
| + this.clear, {this.cls}) {
|
| + _run();
|
| + }
|
| +
|
| + Future _run() async {
|
| + _fetchingTime.start();
|
| + try {
|
| + if (clear) {
|
| + await isolate.invokeRpc('_clearCpuProfile', { });
|
| + }
|
| +
|
| + final response = cls != null
|
| + ? await cls.getAllocationSamples(_tagToString(tag))
|
| + : await isolate.invokeRpc('_getCpuProfile',
|
| + { 'tags': _tagToString(tag) });
|
| +
|
| + _fetchingTime.stop();
|
| + _loadingTime.start();
|
| + _status = M.SampleProfileLoadingStatus.loading;
|
| + _triggerOnProgress();
|
| +
|
| + CpuProfile profile = new CpuProfile();
|
| +
|
| + Stream<double> progress = profile.loadProgress(isolate, response);
|
| + progress.listen((value) { _progress = value; _triggerOnProgress(); });
|
| +
|
| + await progress.drain();
|
| +
|
| + profile.buildFunctionCallerAndCallees();
|
| + _profile = profile;
|
| +
|
| + _loadingTime.stop();
|
| + _status = M.SampleProfileLoadingStatus.loaded;
|
| + _triggerOnProgress();
|
| + } catch (e) {
|
| + if (e is S.ServerRpcException) {
|
| + if (e.code == S.ServerRpcException.kFeatureDisabled) {
|
| + _status = M.SampleProfileLoadingStatus.disabled;
|
| + _triggerOnProgress();
|
| + }
|
| + }
|
| + rethrow;
|
| + } finally {
|
| + _onProgress.close();
|
| + }
|
| + }
|
| +
|
| + void _triggerOnProgress() {
|
| + _onProgress.add(new SampleProfileLoadingProgressEvent(this));
|
| + }
|
| +
|
| + void reuse() {
|
| + _onProgress =
|
| + new StreamController<SampleProfileLoadingProgressEvent>.broadcast();
|
| + (() async {
|
| + _triggerOnProgress();
|
| + _onProgress.close();
|
| + }());
|
| + }
|
| +}
|
| +
|
| +class IsolateSampleProfileRepository
|
| + implements M.IsolateSampleProfileRepository {
|
| + SampleProfileLoadingProgress _last;
|
| +
|
| + Stream<SampleProfileLoadingProgressEvent> get(M.IsolateRef i,
|
| + M.SampleProfileTag t, {bool clear: false, bool forceFetch: false}) {
|
| + assert(clear != null);
|
| + assert(forceFetch != null);
|
| + S.Isolate isolate = i as S.Isolate;
|
| + assert(isolate != null);
|
| + if (_last != null && !clear && !forceFetch && _last.isolate == isolate) {
|
| + _last.reuse();
|
| + } else {
|
| + _last = new SampleProfileLoadingProgress(isolate, t, clear);
|
| + }
|
| + return _last.onProgress;
|
| + }
|
| +}
|
| +
|
| +class ClassSampleProfileRepository
|
| + implements M.ClassSampleProfileRepository {
|
| + Stream<SampleProfileLoadingProgressEvent> get(M.ClassRef c,
|
| + M.SampleProfileTag t, {bool clear: false}) {
|
| + S.Class cls = c as S.Class;
|
| + assert(cls != null);
|
| + return new SampleProfileLoadingProgress(cls.isolate, t,
|
| + clear, cls: cls).onProgress;
|
| + }
|
| +}
|
|
|