blob: a4700843fb8199fe3b4348b82517c97aa648ff00 [file] [log] [blame]
// 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 RUNTIME_VM_TIMELINE_ANALYSIS_H_
#define RUNTIME_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 // RUNTIME_VM_TIMELINE_ANALYSIS_H_