979b7868ca
- Add support for begin and end even kinds. - Update TimelineAnalysis to properly account for begin and end events as well as duration events. - Add unit test for analysis of timelines with begin and end events. R=rmacnak@google.com Review URL: https://codereview.chromium.org/1386263002 .
240 lines
5.8 KiB
C++
240 lines
5.8 KiB
C++
// Copyright (c) 2015, 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.
|
|
|
|
#ifndef VM_TIMELINE_ANALYSIS_H_
|
|
#define VM_TIMELINE_ANALYSIS_H_
|
|
|
|
#include "vm/growable_array.h"
|
|
#include "vm/timeline.h"
|
|
|
|
namespace dart {
|
|
|
|
class TimelineAnalysisThread : public ZoneAllocated {
|
|
public:
|
|
explicit TimelineAnalysisThread(ThreadId id);
|
|
~TimelineAnalysisThread();
|
|
|
|
ThreadId id() const {
|
|
return id_;
|
|
}
|
|
|
|
intptr_t NumBlocks() const {
|
|
return blocks_.length();
|
|
}
|
|
|
|
TimelineEventBlock* At(intptr_t i) const {
|
|
return blocks_.At(i);
|
|
}
|
|
|
|
private:
|
|
void AddBlock(TimelineEventBlock* block);
|
|
void Finalize();
|
|
|
|
const ThreadId id_;
|
|
ZoneGrowableArray<TimelineEventBlock*> blocks_;
|
|
|
|
friend class TimelineAnalysis;
|
|
};
|
|
|
|
|
|
class TimelineAnalysisThreadEventIterator : public ValueObject {
|
|
public:
|
|
explicit TimelineAnalysisThreadEventIterator(TimelineAnalysisThread* thread);
|
|
~TimelineAnalysisThreadEventIterator();
|
|
|
|
void Reset(TimelineAnalysisThread* thread);
|
|
|
|
bool HasNext() const;
|
|
|
|
TimelineEvent* Next();
|
|
|
|
private:
|
|
TimelineAnalysisThread* thread_;
|
|
TimelineEvent* current_;
|
|
intptr_t block_cursor_;
|
|
intptr_t event_cursor_;
|
|
};
|
|
|
|
|
|
// Base of all timeline analysis classes. Base functionality:
|
|
// - discovery of all thread ids in a recording.
|
|
// - collecting all ThreadEventBlocks by thread id.
|
|
class TimelineAnalysis : public ValueObject {
|
|
public:
|
|
TimelineAnalysis(Zone* zone,
|
|
Isolate* isolate,
|
|
TimelineEventRecorder* recorder);
|
|
~TimelineAnalysis();
|
|
|
|
void BuildThreads();
|
|
|
|
intptr_t NumThreads() const {
|
|
return threads_.length();
|
|
}
|
|
|
|
TimelineAnalysisThread* At(intptr_t i) const {
|
|
return threads_[i];
|
|
}
|
|
|
|
TimelineAnalysisThread* GetThread(ThreadId tid);
|
|
|
|
bool has_error() const {
|
|
return has_error_;
|
|
}
|
|
|
|
const char* error_msg() const {
|
|
return error_msg_;
|
|
}
|
|
|
|
protected:
|
|
TimelineAnalysisThread* GetOrAddThread(ThreadId tid);
|
|
|
|
void DiscoverThreads();
|
|
void FinalizeThreads();
|
|
|
|
void SetError(const char* format, ...);
|
|
|
|
Zone* zone_;
|
|
Isolate* isolate_;
|
|
TimelineEventRecorder* recorder_;
|
|
bool has_error_;
|
|
const char* error_msg_;
|
|
|
|
ZoneGrowableArray<TimelineAnalysisThread*> threads_;
|
|
};
|
|
|
|
|
|
class TimelineLabelPauseInfo : public ZoneAllocated {
|
|
public:
|
|
explicit TimelineLabelPauseInfo(const char* name);
|
|
|
|
const char* name() const {
|
|
return name_;
|
|
}
|
|
|
|
int64_t inclusive_micros() const {
|
|
return inclusive_micros_;
|
|
}
|
|
|
|
int64_t exclusive_micros() const {
|
|
return exclusive_micros_;
|
|
}
|
|
|
|
int64_t max_inclusive_micros() const {
|
|
return max_inclusive_micros_;
|
|
}
|
|
|
|
int64_t max_exclusive_micros() const {
|
|
return max_exclusive_micros_;
|
|
}
|
|
|
|
private:
|
|
// Adjusts |inclusive_micros_| and |exclusive_micros_| by |micros|.
|
|
// Also, may adjust, max_inclusive_micros_.
|
|
void OnPush(int64_t micros, bool already_on_stack);
|
|
|
|
// Adjusts |exclusive_micros_| by |exclusive_micros|.
|
|
// Also, may adjust |max_exclusive_micros_|.
|
|
void OnPop(int64_t exclusive_micros);
|
|
|
|
// Adjusts |inclusive_micros_| and |exclusive_micros_| by |micros|.
|
|
// Also, may adjust, |max_inclusive_micros_|.
|
|
void OnBeginPop(int64_t inclusive_micros,
|
|
int64_t exclusive_micros,
|
|
bool already_on_stack);
|
|
|
|
void UpdateInclusiveMicros(int64_t inclusive_micros, bool already_on_stack);
|
|
void UpdateExclusiveMicros(int64_t exclusive_micros);
|
|
|
|
// Adjust inclusive micros.
|
|
void add_inclusive_micros(int64_t delta_micros) {
|
|
inclusive_micros_ += delta_micros;
|
|
ASSERT(inclusive_micros_ >= 0);
|
|
}
|
|
|
|
// Adjust exclusive micros.
|
|
void add_exclusive_micros(int64_t delta_micros) {
|
|
exclusive_micros_ += delta_micros;
|
|
ASSERT(exclusive_micros_ >= 0);
|
|
}
|
|
|
|
void Aggregate(const TimelineLabelPauseInfo* thread_pause_info);
|
|
|
|
const char* name_;
|
|
int64_t inclusive_micros_;
|
|
int64_t exclusive_micros_;
|
|
int64_t max_inclusive_micros_;
|
|
int64_t max_exclusive_micros_;
|
|
|
|
friend class TimelinePauses;
|
|
friend class TimelinePauseTrace;
|
|
};
|
|
|
|
|
|
class TimelinePauses : public TimelineAnalysis {
|
|
public:
|
|
TimelinePauses(Zone* zone,
|
|
Isolate* isolate,
|
|
TimelineEventRecorder* recorder);
|
|
|
|
void Setup();
|
|
|
|
void CalculatePauseTimesForThread(ThreadId tid);
|
|
|
|
TimelineLabelPauseInfo* GetLabelPauseInfo(const char* name) const;
|
|
|
|
int64_t InclusiveTime(const char* name) const;
|
|
int64_t ExclusiveTime(const char* name) const;
|
|
int64_t MaxInclusiveTime(const char* name) const;
|
|
int64_t MaxExclusiveTime(const char* name) const;
|
|
|
|
intptr_t NumPauseInfos() const {
|
|
return labels_.length();
|
|
}
|
|
|
|
const TimelineLabelPauseInfo* PauseInfoAt(intptr_t i) const {
|
|
return labels_.At(i);
|
|
}
|
|
|
|
private:
|
|
struct StackItem {
|
|
TimelineEvent* event;
|
|
TimelineLabelPauseInfo* pause_info;
|
|
int64_t exclusive_micros;
|
|
};
|
|
|
|
void ProcessThread(TimelineAnalysisThread* thread);
|
|
bool CheckStack(TimelineEvent* event);
|
|
void PopFinishedDurations(int64_t start);
|
|
void PopBegin(const char* label, int64_t end);
|
|
void Push(TimelineEvent* event);
|
|
bool IsLabelOnStack(const char* label) const;
|
|
intptr_t StackDepth() const;
|
|
StackItem& GetStackTop();
|
|
TimelineLabelPauseInfo* GetOrAddLabelPauseInfo(const char* name);
|
|
|
|
ZoneGrowableArray<StackItem> stack_;
|
|
ZoneGrowableArray<TimelineLabelPauseInfo*> labels_;
|
|
};
|
|
|
|
|
|
class TimelinePauseTrace : public ValueObject {
|
|
public:
|
|
TimelinePauseTrace();
|
|
~TimelinePauseTrace();
|
|
|
|
void Print();
|
|
|
|
private:
|
|
TimelineLabelPauseInfo* GetOrAddLabelPauseInfo(const char* name);
|
|
void Aggregate(const TimelineLabelPauseInfo* thread_pause_info);
|
|
void PrintPauseInfo(const TimelineLabelPauseInfo* pause_info);
|
|
|
|
ZoneGrowableArray<TimelineLabelPauseInfo*> isolate_labels_;
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#endif // VM_TIMELINE_ANALYSIS_H_
|