From ae8a38e8153cb60c7cf632baa755c0f020ac7fc7 Mon Sep 17 00:00:00 2001 From: Ivan Yurchenko Date: Sun, 20 Nov 2022 08:16:48 +0200 Subject: [PATCH 1/3] ui: Add link to type object in object view --- pyheap-ui/src/pyheap_ui/__main__.py | 1 + pyheap-ui/src/pyheap_ui/templates/objects.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pyheap-ui/src/pyheap_ui/__main__.py b/pyheap-ui/src/pyheap_ui/__main__.py index 0dc825f..6da6244 100644 --- a/pyheap-ui/src/pyheap_ui/__main__.py +++ b/pyheap-ui/src/pyheap_ui/__main__.py @@ -118,6 +118,7 @@ def objects(address: int) -> str: tab_object_active=True, address=address, obj=obj, + type_address=obj.type, type=heap.types[obj.type], objects=heap.objects, types=heap.types, diff --git a/pyheap-ui/src/pyheap_ui/templates/objects.html b/pyheap-ui/src/pyheap_ui/templates/objects.html index 027dc3e..a93e7dd 100644 --- a/pyheap-ui/src/pyheap_ui/templates/objects.html +++ b/pyheap-ui/src/pyheap_ui/templates/objects.html @@ -66,7 +66,7 @@

Address: {{ address }}

-

Type: {{ type }}

+

Type: {{ render_object_link(type_address) }} {{ type }}

Size: {{ obj.size | big_number | safe }} B

Retained heap: {{ retained_heap.get_for_object(address) | big_number | safe }} B

String representation: From 243e965388de495cedc4d3ce29207dc9a8ee7352 Mon Sep 17 00:00:00 2001 From: Ivan Yurchenko Date: Sun, 20 Nov 2022 12:35:09 +0200 Subject: [PATCH 2/3] dumper,ui: add more well-known types --- integration_tests/test_dumper.py | 16 ++++++- pyheap-ui/src/pyheap_ui/__main__.py | 21 ++++++--- pyheap-ui/src/pyheap_ui/heap_reader.py | 7 ++- .../src/pyheap_ui/templates/objects.html | 6 +-- pyheap/src/dumper_inferior.py | 46 +++++++++++++------ 5 files changed, 69 insertions(+), 27 deletions(-) diff --git a/integration_tests/test_dumper.py b/integration_tests/test_dumper.py index 9e68ecf..b8bc1be 100644 --- a/integration_tests/test_dumper.py +++ b/integration_tests/test_dumper.py @@ -429,7 +429,21 @@ def _check_header(heap: Heap, dump_str_repr: bool) -> None: assert (datetime.now(timezone.utc) - x).total_seconds() < 5 * 60 assert heap.header.flags.with_str_repr is dump_str_repr - for type_name in ["dict", "set", "list", "tuple"]: + for type_name in [ + "dict", + "set", + "list", + "tuple", + "str", + "bytes", + "bytearray", + "int", + "bool", + "float", + "object", + "type", + "NoneType", + ]: dict_type_addr = heap.header.well_known_types[type_name] assert heap.types[dict_type_addr] == type_name if dump_str_repr: diff --git a/pyheap-ui/src/pyheap_ui/__main__.py b/pyheap-ui/src/pyheap_ui/__main__.py index 6da6244..929f851 100644 --- a/pyheap-ui/src/pyheap_ui/__main__.py +++ b/pyheap-ui/src/pyheap_ui/__main__.py @@ -15,16 +15,17 @@ # import argparse import dataclasses +import functools import logging import mmap import os import time import math -from typing import Optional, Any +from typing import Optional, Any, Dict from flask import Flask, render_template, abort, request from flask.json.provider import DefaultJSONProvider -from .heap_types import Heap, JsonObject +from .heap_types import Heap, JsonObject, Address from .heap_reader import HeapReader from .heap import ( provide_retained_heap_with_caching, @@ -109,10 +110,6 @@ def objects(address: int) -> str: obj = heap.objects[address] - well_known_type = next( - (k for k, v in heap.header.well_known_types.items() if v == obj.type), None - ) - return render_template( "objects.html", tab_object_active=True, @@ -123,7 +120,7 @@ def objects(address: int) -> str: objects=heap.objects, types=heap.types, retained_heap=retained_heap, - well_known_type=well_known_type, + well_known_container_type=well_known_container_types().get(obj.type), ) @@ -160,6 +157,16 @@ def big_number(size: int) -> str: return " ".join(chunks) +@functools.lru_cache +def well_known_container_types() -> Dict[Address, str]: + return { + heap.header.well_known_types["dict"]: "dict", + heap.header.well_known_types["list"]: "list", + heap.header.well_known_types["set"]: "set", + heap.header.well_known_types["tuple"]: "tuple", + } + + if __name__ == "__main__": parser = argparse.ArgumentParser(description="Heap viewer UI.", allow_abbrev=False) parser.add_argument("--file", "-f", type=str, required=True, help="heap file name") diff --git a/pyheap-ui/src/pyheap_ui/heap_reader.py b/pyheap-ui/src/pyheap_ui/heap_reader.py index 4ee61fa..2d8c3b2 100644 --- a/pyheap-ui/src/pyheap_ui/heap_reader.py +++ b/pyheap-ui/src/pyheap_ui/heap_reader.py @@ -189,7 +189,12 @@ def _read_heap_object(self, address: Address) -> HeapObject: type_ = self._read(Address) size_ = self._read(UnsignedInt) - is_well_known_container_type = type_ in self._header.well_known_types.values() + is_well_known_container_type = type_ in { + self._header.well_known_types["dict"], + self._header.well_known_types["list"], + self._header.well_known_types["set"], + self._header.well_known_types["tuple"], + } content: ObjectContent = None extra_referents: Set[Address] = set() diff --git a/pyheap-ui/src/pyheap_ui/templates/objects.html b/pyheap-ui/src/pyheap_ui/templates/objects.html index a93e7dd..1f79dae 100644 --- a/pyheap-ui/src/pyheap_ui/templates/objects.html +++ b/pyheap-ui/src/pyheap_ui/templates/objects.html @@ -137,7 +137,7 @@

- {% if well_known_type is not none %} + {% if well_known_container_type is not none %}

@@ -166,6 +166,28 @@

{% endif %} + {% if is_type_type %} +
+

+ +

+
+
+
    + {% for addr in type_instances %} +
  • {{ render_element(addr) }} + {% endfor %} +
+
+
+
+ {% endif %} +