mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 20:07:35 +00:00
ProfileViewer: Convert the JSON samples into a more efficient format
Only do the conversion from JSON once. This makes it much faster to do time range filtering with the timeline widget. :^)
This commit is contained in:
parent
d4a570d576
commit
063fef312e
3 changed files with 48 additions and 36 deletions
|
@ -11,14 +11,30 @@ Profile::Profile(const JsonArray& json)
|
||||||
m_last_timestamp = m_json.at(m_json.size() - 1).as_object().get("timestamp").to_number<u64>();
|
m_last_timestamp = m_json.at(m_json.size() - 1).as_object().get("timestamp").to_number<u64>();
|
||||||
|
|
||||||
m_model = ProfileModel::create(*this);
|
m_model = ProfileModel::create(*this);
|
||||||
rebuild_tree();
|
|
||||||
|
|
||||||
m_sample_data.ensure_capacity(m_json.size());
|
m_samples.ensure_capacity(m_json.size());
|
||||||
m_json.for_each([&](const JsonValue& sample) {
|
for (auto& sample_value : m_json.values()) {
|
||||||
u64 timestamp = sample.as_object().get("timestamp").to_number<u64>() - m_first_timestamp;
|
auto& sample_object = sample_value.as_object();
|
||||||
bool in_kernel = sample.as_object().get("frames").as_array().at(1).as_object().get("address").to_number<u32>() < (8 * MB);
|
|
||||||
m_sample_data.append({ timestamp, in_kernel });
|
Sample sample;
|
||||||
});
|
sample.timestamp = sample_object.get("timestamp").to_number<u64>();
|
||||||
|
sample.in_kernel = sample_object.get("frames").as_array().at(1).as_object().get("address").to_number<u32>() < (8 * MB);
|
||||||
|
|
||||||
|
auto frames_value = sample_object.get("frames");
|
||||||
|
auto& frames_array = frames_value.as_array();
|
||||||
|
for (int i = frames_array.size() - 1; i >= 0; --i) {
|
||||||
|
auto& frame_value = frames_array.at(i);
|
||||||
|
auto& frame_object = frame_value.as_object();
|
||||||
|
Frame frame;
|
||||||
|
frame.symbol = frame_object.get("symbol").as_string_or({});
|
||||||
|
frame.address = frame_object.get("address").as_u32();
|
||||||
|
frame.offset = frame_object.get("offset").as_u32();
|
||||||
|
sample.frames.append(move(frame));
|
||||||
|
};
|
||||||
|
m_samples.append(move(sample));
|
||||||
|
}
|
||||||
|
|
||||||
|
rebuild_tree();
|
||||||
}
|
}
|
||||||
|
|
||||||
Profile::~Profile()
|
Profile::~Profile()
|
||||||
|
@ -46,35 +62,32 @@ void Profile::rebuild_tree()
|
||||||
return new_root;
|
return new_root;
|
||||||
};
|
};
|
||||||
|
|
||||||
m_json.for_each([&](const JsonValue& sample) {
|
for (auto& sample : m_samples) {
|
||||||
if (has_timestamp_filter_range()) {
|
if (has_timestamp_filter_range()) {
|
||||||
auto timestamp = sample.as_object().get("timestamp").to_number<u64>();
|
auto timestamp = sample.timestamp;
|
||||||
if (timestamp < m_timestamp_filter_range_start || timestamp > m_timestamp_filter_range_end)
|
if (timestamp < m_timestamp_filter_range_start || timestamp > m_timestamp_filter_range_end)
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto frames_value = sample.as_object().get("frames");
|
|
||||||
auto& frames = frames_value.as_array();
|
|
||||||
ProfileNode* node = nullptr;
|
ProfileNode* node = nullptr;
|
||||||
for (int i = frames.size() - 1; i >= 0; --i) {
|
for (int i = 0; i < sample.frames.size(); ++i) {
|
||||||
auto& frame = frames.at(i);
|
auto& frame = sample.frames.at(i);
|
||||||
|
|
||||||
auto symbol = frame.as_object().get("symbol").as_string_or({});
|
auto& symbol = frame.symbol;
|
||||||
auto address = frame.as_object().get("address").as_u32();
|
auto& address = frame.address;
|
||||||
auto offset = frame.as_object().get("offset").as_u32();
|
auto& offset = frame.offset;
|
||||||
auto timestamp = frame.as_object().get("timestamp").to_number<u64>();
|
|
||||||
|
|
||||||
if (symbol.is_empty())
|
if (symbol.is_empty())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!node)
|
if (!node)
|
||||||
node = &find_or_create_root(symbol, address, offset, timestamp);
|
node = &find_or_create_root(symbol, address, offset, sample.timestamp);
|
||||||
else
|
else
|
||||||
node = &node->find_or_create_child(symbol, address, offset, timestamp);
|
node = &node->find_or_create_child(symbol, address, offset, sample.timestamp);
|
||||||
|
|
||||||
node->increment_sample_count();
|
node->increment_sample_count();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
for (auto& root : roots) {
|
for (auto& root : roots) {
|
||||||
root.sort_children();
|
root.sort_children();
|
||||||
|
|
|
@ -82,20 +82,19 @@ public:
|
||||||
|
|
||||||
const Vector<NonnullRefPtr<ProfileNode>>& roots() const { return m_roots; }
|
const Vector<NonnullRefPtr<ProfileNode>>& roots() const { return m_roots; }
|
||||||
|
|
||||||
template<typename Callback>
|
struct Frame {
|
||||||
void for_each_sample(Callback callback)
|
String symbol;
|
||||||
{
|
u32 address { 0 };
|
||||||
m_json.for_each([&](auto& value) {
|
u32 offset { 0 };
|
||||||
callback(value.as_object());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SampleData {
|
|
||||||
u64 timestamp { 0 };
|
|
||||||
bool in_kernel { false };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Vector<SampleData>& sample_data() const { return m_sample_data; }
|
struct Sample {
|
||||||
|
u64 timestamp { 0 };
|
||||||
|
bool in_kernel { false };
|
||||||
|
Vector<Frame> frames;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Vector<Sample>& samples() const { return m_samples; }
|
||||||
|
|
||||||
u64 length_in_ms() const { return m_last_timestamp - m_first_timestamp; }
|
u64 length_in_ms() const { return m_last_timestamp - m_first_timestamp; }
|
||||||
u64 first_timestamp() const { return m_first_timestamp; }
|
u64 first_timestamp() const { return m_first_timestamp; }
|
||||||
|
@ -116,7 +115,7 @@ private:
|
||||||
u64 m_first_timestamp { 0 };
|
u64 m_first_timestamp { 0 };
|
||||||
u64 m_last_timestamp { 0 };
|
u64 m_last_timestamp { 0 };
|
||||||
|
|
||||||
Vector<SampleData> m_sample_data;
|
Vector<Sample> m_samples;
|
||||||
|
|
||||||
bool m_has_timestamp_filter_range { false };
|
bool m_has_timestamp_filter_range { false };
|
||||||
u64 m_timestamp_filter_range_start { 0 };
|
u64 m_timestamp_filter_range_start { 0 };
|
||||||
|
|
|
@ -28,8 +28,8 @@ void ProfileTimelineWidget::paint_event(GPaintEvent& event)
|
||||||
|
|
||||||
float column_width = (float)frame_inner_rect().width() / (float)m_profile.length_in_ms();
|
float column_width = (float)frame_inner_rect().width() / (float)m_profile.length_in_ms();
|
||||||
|
|
||||||
for (auto& sample : m_profile.sample_data()) {
|
for (auto& sample : m_profile.samples()) {
|
||||||
u64 t = sample.timestamp;
|
u64 t = sample.timestamp - m_profile.first_timestamp();
|
||||||
int x = (int)((float)t * column_width);
|
int x = (int)((float)t * column_width);
|
||||||
int cw = max(1, (int)column_width);
|
int cw = max(1, (int)column_width);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue