| Index: runtime/vm/timeline_analysis.cc
|
| diff --git a/runtime/vm/timeline_analysis.cc b/runtime/vm/timeline_analysis.cc
|
| index 2aaf6b06cf0cbceb698f4e6bc9be95ffab843856..1ca8442a2d8ba32f7898839b04ce0774bb2e027c 100644
|
| --- a/runtime/vm/timeline_analysis.cc
|
| +++ b/runtime/vm/timeline_analysis.cc
|
| @@ -10,7 +10,8 @@
|
|
|
| namespace dart {
|
|
|
| -DEFINE_FLAG(bool, trace_timeline_analysis, false, "Trace timeline analysis");
|
| +DECLARE_FLAG(bool, trace_timeline_analysis);
|
| +DECLARE_FLAG(bool, timing);
|
|
|
| TimelineAnalysisThread::TimelineAnalysisThread(ThreadId id)
|
| : id_(id) {
|
| @@ -161,6 +162,10 @@ void TimelineAnalysis::DiscoverThreads() {
|
| // Skip empty blocks.
|
| continue;
|
| }
|
| + if (block->isolate() != isolate_) {
|
| + // Skip blocks for other isolates.
|
| + continue;
|
| + }
|
| if (!block->CheckBlock()) {
|
| if (FLAG_trace_timeline_analysis) {
|
| THR_Print("DiscoverThreads block %" Pd " "
|
| @@ -226,6 +231,20 @@ void TimelineLabelPauseInfo::OnPop(int64_t exclusive_micros) {
|
| }
|
|
|
|
|
| +void TimelineLabelPauseInfo::Aggregate(
|
| + const TimelineLabelPauseInfo* thread_pause_info) {
|
| + ASSERT(thread_pause_info != NULL);
|
| + inclusive_micros_ += thread_pause_info->inclusive_micros_;
|
| + exclusive_micros_ += thread_pause_info->exclusive_micros_;
|
| + if (max_inclusive_micros_ < thread_pause_info->max_inclusive_micros_) {
|
| + max_inclusive_micros_ = thread_pause_info->max_inclusive_micros_;
|
| + }
|
| + if (max_exclusive_micros_ < thread_pause_info->max_exclusive_micros_) {
|
| + max_exclusive_micros_ = thread_pause_info->max_exclusive_micros_;
|
| + }
|
| +}
|
| +
|
| +
|
| TimelinePauses::TimelinePauses(Zone* zone,
|
| Isolate* isolate,
|
| TimelineEventRecorder* recorder)
|
| @@ -386,7 +405,7 @@ void TimelinePauses::Push(TimelineEvent* event) {
|
| }
|
|
|
|
|
| -bool TimelinePauses::IsLabelOnStack(const char* label) {
|
| +bool TimelinePauses::IsLabelOnStack(const char* label) const {
|
| ASSERT(label != NULL);
|
| for (intptr_t i = 0; i < stack_.length(); i++) {
|
| const StackItem& slot = stack_.At(i);
|
| @@ -422,4 +441,95 @@ TimelineLabelPauseInfo* TimelinePauses::GetOrAddLabelPauseInfo(
|
| return pause_info;
|
| }
|
|
|
| +
|
| +TimelinePauseTrace::TimelinePauseTrace() {
|
| +}
|
| +
|
| +
|
| +TimelinePauseTrace::~TimelinePauseTrace() {
|
| +}
|
| +
|
| +
|
| +void TimelinePauseTrace::Print() {
|
| + Thread* thread = Thread::Current();
|
| + ASSERT(thread != NULL);
|
| + Isolate* isolate = thread->isolate();
|
| + ASSERT(isolate != NULL);
|
| + Zone* zone = thread->zone();
|
| + ASSERT(zone != NULL);
|
| + TimelineEventRecorder* recorder = Timeline::recorder();
|
| + ASSERT(recorder != NULL);
|
| + TimelinePauses pauses(zone, isolate, recorder);
|
| + pauses.Setup();
|
| +
|
| + THR_Print("Timing for isolate %s (from %" Pd " threads)\n",
|
| + isolate->name(),
|
| + pauses.NumThreads());
|
| + THR_Print("\n");
|
| + for (intptr_t t_idx = 0; t_idx < pauses.NumThreads(); t_idx++) {
|
| + TimelineAnalysisThread* tat = pauses.At(t_idx);
|
| + ASSERT(tat != NULL);
|
| + pauses.CalculatePauseTimesForThread(tat->id());
|
| + THR_Print("Thread %" Pd " (%" Px "):\n",
|
| + t_idx,
|
| + OSThread::ThreadIdToIntPtr(tat->id()));
|
| + for (intptr_t j = 0; j < pauses.NumPauseInfos(); j++) {
|
| + const TimelineLabelPauseInfo* pause_info = pauses.PauseInfoAt(j);
|
| + ASSERT(pause_info != NULL);
|
| + Aggregate(pause_info);
|
| + PrintPauseInfo(pause_info);
|
| + }
|
| + THR_Print("\n");
|
| + }
|
| + THR_Print("Totals:\n");
|
| + for (intptr_t i = 0; i < isolate_labels_.length(); i++) {
|
| + TimelineLabelPauseInfo* pause_info = isolate_labels_.At(i);
|
| + ASSERT(pause_info != NULL);
|
| + PrintPauseInfo(pause_info);
|
| + }
|
| + THR_Print("\n");
|
| +}
|
| +
|
| +
|
| +TimelineLabelPauseInfo* TimelinePauseTrace::GetOrAddLabelPauseInfo(
|
| + const char* name) {
|
| + ASSERT(name != NULL);
|
| + // Linear lookup because we expect N (# of labels in an isolate) to be small.
|
| + for (intptr_t i = 0; i < isolate_labels_.length(); i++) {
|
| + TimelineLabelPauseInfo* label = isolate_labels_.At(i);
|
| + if (strcmp(label->name(), name) == 0) {
|
| + return label;
|
| + }
|
| + }
|
| + // New label.
|
| + TimelineLabelPauseInfo* pause_info = new TimelineLabelPauseInfo(name);
|
| + isolate_labels_.Add(pause_info);
|
| + return pause_info;
|
| +}
|
| +
|
| +
|
| +void TimelinePauseTrace::Aggregate(
|
| + const TimelineLabelPauseInfo* thread_pause_info) {
|
| + ASSERT(thread_pause_info != NULL);
|
| + TimelineLabelPauseInfo* isolate_pause_info =
|
| + GetOrAddLabelPauseInfo(thread_pause_info->name());
|
| + ASSERT(isolate_pause_info != NULL);
|
| + isolate_pause_info->Aggregate(thread_pause_info);
|
| +}
|
| +
|
| +
|
| +void TimelinePauseTrace::PrintPauseInfo(
|
| + const TimelineLabelPauseInfo* pause_info) {
|
| + ASSERT(pause_info != NULL);
|
| + THR_Print("%s : ", pause_info->name());
|
| + THR_Print("%.3f ms total on stack; ",
|
| + MicrosecondsToMilliseconds(pause_info->inclusive_micros()));
|
| + THR_Print("%.3f ms total executing; ",
|
| + MicrosecondsToMilliseconds(pause_info->exclusive_micros()));
|
| + THR_Print("%.3f ms max on stack; ",
|
| + MicrosecondsToMilliseconds(pause_info->max_inclusive_micros()));
|
| + THR_Print("%.3f ms max executing.\n",
|
| + MicrosecondsToMilliseconds(pause_info->max_exclusive_micros()));
|
| +}
|
| +
|
| } // namespace dart
|
|
|