diff options
author | Timur Mustafin/Platform Lab /SRR/Engineer/Samsung Electronics <t.mustafin@partner.samsung.com> | 2022-09-06 19:44:24 +0300 |
---|---|---|
committer | GitHub Enterprise <noreply-CODE@samsung.com> | 2022-09-06 19:44:24 +0300 |
commit | 698b8764a2fbd9d0168e4791f3cc8468984f1973 (patch) | |
tree | c1f66f0d4cfdfb608719c061cb21aada85973ee1 | |
parent | 83b98332edef313709a8ec8d87ff4966b6c54929 (diff) | |
download | heaptrack-698b8764a2fbd9d0168e4791f3cc8468984f1973.tar.gz heaptrack-698b8764a2fbd9d0168e4791f3cc8468984f1973.tar.bz2 heaptrack-698b8764a2fbd9d0168e4791f3cc8468984f1973.zip |
Fix Aarch64 work (#100)
* interpret: class name resolve warn only
Unresolved nodes ejection corrupts tree structure, it leads to problems on reading the tree in buildObjectTree.
* Fix Linux build
Changes to make heaptrack build on linux
Define USE_KCHART to build all GUI tabs
Add Linux instruction
* gui: Refactoing and comments
* profiler: fix pointer storage in int type
* Use OnFunctionLeave as OnTailCall callback
Fixes flamegraph picture on architectures with TailCall optimization
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | LINUX_GUI_BUILD.md | 39 | ||||
-rw-r--r-- | profiler/profiler/src/profiler.cpp | 13 | ||||
-rw-r--r-- | profiler/profiler/src/stackentry.h | 4 | ||||
-rw-r--r-- | src/analyze/accumulatedtracedata.h | 6 | ||||
-rw-r--r-- | src/analyze/gui/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/analyze/gui/parser.cpp | 22 | ||||
-rw-r--r-- | src/interpret/heaptrack_interpret.cpp | 1 |
8 files changed, 70 insertions, 22 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index c57c2f2..850259a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,9 @@ if(HEAPTRACK_BUILD_GUI) find_package(KF5 COMPONENTS CoreAddons I18n ItemModels ThreadWeaver ConfigWidgets KIO) find_package(KChart "2.6.0") set_package_properties(KChart PROPERTIES TYPE RECOMMENDED PURPOSE "Required for the heaptrack_gui executable. Get it from the kdiagram module.") + if(KChart_FOUND) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_CHART=1") + endif() endif() endif() diff --git a/LINUX_GUI_BUILD.md b/LINUX_GUI_BUILD.md new file mode 100644 index 0000000..0fe813b --- /dev/null +++ b/LINUX_GUI_BUILD.md @@ -0,0 +1,39 @@ +# Building Heaptrack GUI on Linux + +## Prerequisites + +Operating system: Ubuntu 18.04 can be used to build Heaptrack GUI. + +The following packages are needed: + +```bash +apt-get update && apt-get -y install cmake libsparsehash-dev \ + build-essential libunwind8-dev libunwind8 libboost-dev \ + libboost-iostreams-dev libboost-program-options-dev \ + zlib1g zlib1g-dev libdwarf-dev qt5-default extra-cmake-modules \ + libkf5coreaddons-dev libkf5i18n-dev libkf5itemmodels-dev \ + libkf5threadweaver-dev libkf5configwidgets-dev libkf5kiocore5 \ + libkf5kiowidgets5 kio-dev cpio rpm2cpio clang libkchart2 \ + libkchart-dev gettext +``` + +## Building the GUI application + +### How to build + +After installing all libraries required it’s possible to build the GUI application itself. It can be done using *cmake* utility from project root directory: + +```bash +cd <heaptrack sources> +mkdir build-x64; cd build-x64 +cmake ../ +make +``` + +### Open collected and interpreted heaptrack file in builded Heaptrack GUI + +Heaptrack GUI file is placed in ./bin/ directory after build: + +```bash +./bin/heaptrack_gui --managed <path to heaptrack.interpreted file heaptrack.interpreted.gz file> +``` diff --git a/profiler/profiler/src/profiler.cpp b/profiler/profiler/src/profiler.cpp index 29607cc..774e2db 100644 --- a/profiler/profiler/src/profiler.cpp +++ b/profiler/profiler/src/profiler.cpp @@ -1,3 +1,4 @@ +#include <cinttypes> #include "profiler.h" #include "pal_excerpts.h" #include "classfactory.h" @@ -103,7 +104,7 @@ static WCHAR *wszModuleNames = nullptr; extern __thread StackEntry* g_shadowStack; __thread StackEntry* g_freeStackEntryListItems = nullptr; -StackEntry::StackEntry(unsigned int funcId, +StackEntry::StackEntry(uintptr_t funcId, const char* className, const char* methodName, bool isType, @@ -342,7 +343,7 @@ HRESULT STDMETHODCALLTYPE Profiler::Initialize(IUnknown *pICorProfilerInfoUnk) { COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO | COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_MONITOR_CLASS_LOADS | COR_PRF_ENABLE_OBJECT_ALLOCATED | COR_PRF_MONITOR_OBJECT_ALLOCATED | COR_PRF_MONITOR_GC); - info->SetEnterLeaveFunctionHooks3WithInfo(OnFunctionEnter, OnFunctionLeave, NULL); + info->SetEnterLeaveFunctionHooks3WithInfo(OnFunctionEnter, OnFunctionLeave, OnFunctionLeave); info->Release(); info = NULL; } @@ -427,7 +428,7 @@ HRESULT STDMETHODCALLTYPE Profiler::ClassLoadFinished(ClassID classId, HRESULT hrStatus) { if (hrStatus != S_OK) { - fprintf(stderr, "[W] Failed to load class %x, HRESULT=%x\n", classId, hrStatus); + fprintf(stderr, "[W] Failed to load class %" PRIxPTR ", HRESULT=%x\n", classId, hrStatus); return S_OK; } @@ -442,7 +443,7 @@ HRESULT STDMETHODCALLTYPE hr = GetClassNameFromClassId(info, classId, wszClassName); if (hr != S_OK) { - fprintf(stderr, "[W] Failed to retrieve class name for class %x, HRESULT=%x\n", classId, hr); + fprintf(stderr, "[W] Failed to retrieve class name for class %" PRIxPTR ", HRESULT=%x\n", classId, hr); goto Cleanup; } @@ -651,7 +652,7 @@ HRESULT STDMETHODCALLTYPE // We still want the best estimate, even though something went wrong. if (hr != S_OK) { - fprintf(stderr, "[W] Unknown type for object %x, HRESULT=%x\n", objectRefIds[i], hr); + fprintf(stderr, "[W] Unknown type for object %" PRIxPTR ", HRESULT=%x\n", objectRefIds[i], hr); continue; } @@ -686,7 +687,7 @@ HRESULT STDMETHODCALLTYPE // We still want the best estimate, even though something went wrong. if (hr != S_OK) { - fprintf(stderr, "[W] Unknown type for object %x, HRESULT=%x\n", rootRefIds[i], hr); + fprintf(stderr, "[W] Unknown type for object %" PRIxPTR ", HRESULT=%x\n", rootRefIds[i], hr); continue; } diff --git a/profiler/profiler/src/stackentry.h b/profiler/profiler/src/stackentry.h index 53cf27f..77813c0 100644 --- a/profiler/profiler/src/stackentry.h +++ b/profiler/profiler/src/stackentry.h @@ -6,9 +6,9 @@ static constexpr size_t MAX_NAME_LENGTH = 512; class StackEntry { public: - StackEntry(unsigned int funcId, const char* className, const char* methodName, bool isType, StackEntry *next); + StackEntry(uintptr_t funcId, const char* className, const char* methodName, bool isType, StackEntry *next); - unsigned int m_funcId; + uintptr_t m_funcId; char m_className[MAX_NAME_LENGTH + 1]; char m_methodName[MAX_NAME_LENGTH + 1]; bool m_isType; diff --git a/src/analyze/accumulatedtracedata.h b/src/analyze/accumulatedtracedata.h index 4002d95..cd5597e 100644 --- a/src/analyze/accumulatedtracedata.h +++ b/src/analyze/accumulatedtracedata.h @@ -91,7 +91,7 @@ struct ObjectTreeNode { uint64_t gcNum; uint64_t numChildren; - uint64_t objectPtr; + uint64_t objectPtr; // Object pointer as it was on target ClassIndex classIndex; AllocationIndex allocIndex; }; @@ -364,6 +364,10 @@ struct AccumulatedTraceData std::vector<IpIndex> opNewIpIndices; std::vector<AllocationInfo> allocationInfos; std::vector<ClassIndex> classIndices; + + /* objectTreeNodes is in fact a flat collection of ObjectTreeNodes. The graph structure + is provided by ObjectTreeNode::numChildren which indicates how many childrens has current node. + Childrens of current node follow in a row with intervals for thier own descendants. */ std::vector<ObjectTreeNode> objectTreeNodes; AddressRangesMap addressRangeInfos; diff --git a/src/analyze/gui/CMakeLists.txt b/src/analyze/gui/CMakeLists.txt index e734554..bf59fbe 100644 --- a/src/analyze/gui/CMakeLists.txt +++ b/src/analyze/gui/CMakeLists.txt @@ -2,6 +2,7 @@ set(CMAKE_AUTOMOC 1) ki18n_wrap_ui(UIFILES mainwindow.ui + aboutdialog.ui ) unset(BIN_INSTALL_DIR) @@ -31,6 +32,8 @@ set(SRCFILES topproxy.cpp callercalleemodel.cpp util.cpp + aboutdata.cpp + aboutdialog.cpp ) set(LIBRARIES @@ -60,7 +63,6 @@ endif() add_definitions(-Wall -DQT_NO_URL_CAST_FROM_STRING - -DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII -DQT_NO_CAST_FROM_BYTEARRAY -DQT_USE_QSTRINGBUILDER ) diff --git a/src/analyze/gui/parser.cpp b/src/analyze/gui/parser.cpp index 940ba9a..a495d62 100644 --- a/src/analyze/gui/parser.cpp +++ b/src/analyze/gui/parser.cpp @@ -358,13 +358,13 @@ struct ObjectNode { } std::vector<ObjectNode*> m_children; - size_t index; + size_t index; // Index to access vector data.objectTreeNodes bool visited; static std::unordered_map<uint64_t, std::unique_ptr<ObjectNode>> nodes; }; -std::unordered_map<uint64_t, std::unique_ptr<ObjectNode>> ObjectNode::nodes; +std::unordered_map<uint64_t, std::unique_ptr<ObjectNode>> ObjectNode::nodes; // Key is ObjectTreeNode.objectPtr, object pointer as it was on target struct TypeTree { TypeTree() @@ -397,7 +397,7 @@ struct TypeTree { auto TT = std::unique_ptr<TypeTree>(new TypeTree()); TT->m_classIndex = data.objectTreeNodes[node->index].classIndex; TT->m_gcNum = data.objectTreeNodes[node->index].gcNum; - TT->m_uniqueObjects[node->index] = 1; + TT->m_uniqueObjects.insert(node->index); return TT; } @@ -438,7 +438,7 @@ struct TypeTree { for (auto &grandparent: other->m_parents) m_parents.push_back(std::move(grandparent)); for (auto& uo: other->m_uniqueObjects) { - m_uniqueObjects[uo.first]++; + m_uniqueObjects.insert(uo); } } @@ -499,15 +499,14 @@ struct TypeTree { size_t addRefSize(ParserData& data, size_t objectIndex, size_t leafSize) { int result = 0; for (auto& uo: m_uniqueObjects) { - size_t uoIndex = uo.first; - auto& uoChildren = ObjectNode::nodes[data.objectTreeNodes[uoIndex].objectPtr]->m_children; + auto& uoChildren = ObjectNode::nodes[data.objectTreeNodes[uo].objectPtr]->m_children; for (auto &uoChild: uoChildren) { if (uoChild->index == objectIndex) { if (m_parents.size() == 0) { result += 1; } for (auto& parent: m_parents) - result += parent->addRefSize(data, uoIndex, leafSize); + result += parent->addRefSize(data, uo, leafSize); } } } @@ -517,7 +516,7 @@ struct TypeTree { ClassIndex m_classIndex; std::vector<std::unique_ptr<TypeTree>> m_parents; - std::unordered_map<size_t, uint64_t> m_uniqueObjects; + std::unordered_set<size_t> m_uniqueObjects; // Indexes in data.objectTreeNodes uint64_t m_referencedSize; int m_gcNum; }; @@ -783,7 +782,7 @@ ObjectRowData objectRowDataFromTypeTree(ParserData& data, TypeTree* tree) { rowData.allocations = tree->m_uniqueObjects.size(); rowData.referenced = tree->m_referencedSize; for (auto &uo: tree->m_uniqueObjects) { - rowData.allocated += data.allocationInfos[data.objectTreeNodes[uo.first].allocIndex.index].size; + rowData.allocated += data.allocationInfos[data.objectTreeNodes[uo].allocIndex.index].size; } for (auto& parent: tree->m_parents) rowData.children.push_back(objectRowDataFromTypeTree(data, parent.get())); @@ -824,6 +823,7 @@ ObjectTreeData buildObjectTree(ParserData& data) auto nodePtr = node.get(); ObjectNode::nodes.insert(std::pair<uint64_t, std::unique_ptr<ObjectNode>>( 0, std::move(node))); + Q_ASSERT(data.objectTreeNodes[nodePtr->index].objectPtr == 0 && "Incorrect root node"); TypeTree root; root.m_gcNum = data.objectTreeNodes[nodePtr->index].gcNum; root.m_parents = std::move(TypeTree::createBottomUp(data, nodePtr)); @@ -832,8 +832,8 @@ ObjectTreeData buildObjectTree(ParserData& data) for (auto& parent: root.m_parents) { for (auto &uo: parent->m_uniqueObjects) { for (auto &grandparent: parent->m_parents) { - size_t leafSize = data.allocationInfos[data.objectTreeNodes[uo.first].allocIndex.index].size; - size_t chains = grandparent->addRefSize(data, uo.first, leafSize); + size_t leafSize = data.allocationInfos[data.objectTreeNodes[uo].allocIndex.index].size; + size_t chains = grandparent->addRefSize(data, uo, leafSize); parent->m_referencedSize += chains * leafSize; } } diff --git a/src/interpret/heaptrack_interpret.cpp b/src/interpret/heaptrack_interpret.cpp index 9b69853..5a9b539 100644 --- a/src/interpret/heaptrack_interpret.cpp +++ b/src/interpret/heaptrack_interpret.cpp @@ -813,7 +813,6 @@ int main(int /*argc*/, char** /*argv*/) const auto classId = data.addClass(classPointer); if (classId == 0 && classPointer != 0) { cerr << "[W] Unknown class id (" << classPointer << ") here: " << reader.line() << endl; - continue; } const auto objectId = ptrToIndex.peekPointer(objectPointer); |