mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
![Ryan Macnak](/assets/img/avatar_default.png)
Bug: https://github.com/dart-lang/sdk/issues/35009 Change-Id: I6b509e1eb8e76e07f60a086c67358d65d2a1fae4 Reviewed-on: https://dart-review.googlesource.com/c/82460 Reviewed-by: Vyacheslav Egorov <vegorov@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Siva Annamalai <asiva@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
207 lines
5.7 KiB
C++
207 lines
5.7 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 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, ...) PRINTF_ATTRIBUTE(2, 3);
|
|
|
|
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_
|