Chromium Code Reviews| 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..5bb54042a5aeccf6573b92ed91442c6650ee3525 |
| --- /dev/null |
| +++ b/runtime/observatory/lib/src/repositories/sample_profile.dart |
| @@ -0,0 +1,134 @@ |
| +// 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'; |
|
Cutch
2016/08/04 15:35:52
no space between the case value and the colon (:)
cbernaschina
2016/08/04 19:45:08
Done.
|
| + 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'); |
| +} |
| + |
| +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; |
| + |
| + SampleProfileLoadingProgress 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) { |
| + return _last..reuse(); |
| + } |
| + return _last = new SampleProfileLoadingProgress(isolate, t, clear); |
| + } |
| +} |
| + |
| +class ClassSampleProfileRepository |
| + implements M.ClassSampleProfileRepository { |
| + SampleProfileLoadingProgress 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); |
| + } |
| +} |