Serenity Operating System
at hosted 168 lines 5.5 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#pragma once 28 29#include <AK/JsonArray.h> 30#include <AK/JsonObject.h> 31#include <AK/JsonValue.h> 32#include <AK/NonnullRefPtrVector.h> 33#include <AK/OwnPtr.h> 34#include <LibGUI/Forward.h> 35 36class ProfileModel; 37 38class ProfileNode : public RefCounted<ProfileNode> { 39public: 40 static NonnullRefPtr<ProfileNode> create(const String& symbol, u32 address, u32 offset, u64 timestamp) 41 { 42 return adopt(*new ProfileNode(symbol, address, offset, timestamp)); 43 } 44 45 const String& symbol() const { return m_symbol; } 46 u32 address() const { return m_address; } 47 u32 offset() const { return m_offset; } 48 u64 timestamp() const { return m_timestamp; } 49 50 u32 event_count() const { return m_event_count; } 51 u32 self_count() const { return m_self_count; } 52 53 int child_count() const { return m_children.size(); } 54 const Vector<NonnullRefPtr<ProfileNode>>& children() const { return m_children; } 55 56 void add_child(ProfileNode& child) 57 { 58 if (child.m_parent == this) 59 return; 60 ASSERT(!child.m_parent); 61 child.m_parent = this; 62 m_children.append(child); 63 } 64 65 ProfileNode& find_or_create_child(const String& symbol, u32 address, u32 offset, u64 timestamp) 66 { 67 for (size_t i = 0; i < m_children.size(); ++i) { 68 auto& child = m_children[i]; 69 if (child->symbol() == symbol) { 70 return child; 71 } 72 } 73 auto new_child = ProfileNode::create(symbol, address, offset, timestamp); 74 add_child(new_child); 75 return new_child; 76 }; 77 78 ProfileNode* parent() { return m_parent; } 79 const ProfileNode* parent() const { return m_parent; } 80 81 void increment_event_count() { ++m_event_count; } 82 void increment_self_count() { ++m_self_count; } 83 84 void sort_children(); 85 86private: 87 explicit ProfileNode(const String& symbol, u32 address, u32 offset, u64 timestamp) 88 : m_symbol(symbol) 89 , m_address(address) 90 , m_offset(offset) 91 , m_timestamp(timestamp) 92 { 93 } 94 95 ProfileNode* m_parent { nullptr }; 96 String m_symbol; 97 u32 m_address { 0 }; 98 u32 m_offset { 0 }; 99 u32 m_event_count { 0 }; 100 u32 m_self_count { 0 }; 101 u64 m_timestamp { 0 }; 102 Vector<NonnullRefPtr<ProfileNode>> m_children; 103}; 104 105class Profile { 106public: 107 static OwnPtr<Profile> load_from_perfcore_file(const StringView& path); 108 ~Profile(); 109 110 GUI::Model& model(); 111 112 const Vector<NonnullRefPtr<ProfileNode>>& roots() const { return m_roots; } 113 114 struct Frame { 115 String symbol; 116 u32 address { 0 }; 117 u32 offset { 0 }; 118 }; 119 120 struct Event { 121 u64 timestamp { 0 }; 122 String type; 123 FlatPtr ptr { 0 }; 124 size_t size { 0 }; 125 bool in_kernel { false }; 126 Vector<Frame> frames; 127 }; 128 129 u32 filtered_event_count() const { return m_filtered_event_count; } 130 131 const Vector<Event>& events() const { return m_events; } 132 133 u64 length_in_ms() const { return m_last_timestamp - m_first_timestamp; } 134 u64 first_timestamp() const { return m_first_timestamp; } 135 u64 last_timestamp() const { return m_last_timestamp; } 136 u32 deepest_stack_depth() const { return m_deepest_stack_depth; } 137 138 void set_timestamp_filter_range(u64 start, u64 end); 139 void clear_timestamp_filter_range(); 140 bool has_timestamp_filter_range() const { return m_has_timestamp_filter_range; } 141 142 bool is_inverted() const { return m_inverted; } 143 void set_inverted(bool); 144 145 bool show_percentages() const { return m_show_percentages; } 146 void set_show_percentages(bool); 147 148private: 149 explicit Profile(Vector<Event>); 150 151 void rebuild_tree(); 152 153 RefPtr<ProfileModel> m_model; 154 Vector<NonnullRefPtr<ProfileNode>> m_roots; 155 u32 m_filtered_event_count { 0 }; 156 u64 m_first_timestamp { 0 }; 157 u64 m_last_timestamp { 0 }; 158 159 Vector<Event> m_events; 160 161 bool m_has_timestamp_filter_range { false }; 162 u64 m_timestamp_filter_range_start { 0 }; 163 u64 m_timestamp_filter_range_end { 0 }; 164 165 u32 m_deepest_stack_depth { 0 }; 166 bool m_inverted { false }; 167 bool m_show_percentages { false }; 168};