Skip to content

Commit

Permalink
feat: retained size; initialize before connection
Browse files Browse the repository at this point in the history
  • Loading branch information
comeillfoo committed May 17, 2023
1 parent 6a8071b commit 7f09108
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 31 deletions.
2 changes: 1 addition & 1 deletion clr-profiler
54 changes: 27 additions & 27 deletions frames.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,59 +147,59 @@ def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)

UPDATE_TIMEOUT = 2000
VALUES_LIMIT = 11
self.VALUES_LIMIT = 11
PLOT_SIZE = (5, 2.5)

# threads number
threads = tk.Frame(self)
self.threads = [0] * VALUES_LIMIT
self.threads = [0] * self.VALUES_LIMIT
self.thread = tk.IntVar(threads, 0)
threads.after(UPDATE_TIMEOUT,
lambda: refresh(threads, self.threads, self.thread, 'Число потоков: {:.0f}', VALUES_LIMIT, UPDATE_TIMEOUT,
lambda: refresh(threads, self.threads, self.thread, 'Число потоков: {:.0f}', self.VALUES_LIMIT, UPDATE_TIMEOUT,
color='g', figsize=PLOT_SIZE))
threads.grid(row=0, column=0)

# exceptions number
exceptions = tk.Frame(self)
self.exceptions = [0] * VALUES_LIMIT
self.exceptions = [0] * self.VALUES_LIMIT
self.exception = tk.IntVar(exceptions, 0)
exceptions.after(UPDATE_TIMEOUT,
lambda: refresh(exceptions, self.exceptions, self.exception, 'Выброшено исключений: {:.0f}', VALUES_LIMIT, UPDATE_TIMEOUT,
lambda: refresh(exceptions, self.exceptions, self.exception, 'Выброшено исключений: {:.0f}', self.VALUES_LIMIT, UPDATE_TIMEOUT,
color='r', figsize=PLOT_SIZE))
exceptions.grid(row=0, column=1)

# cpu usage
cpu = tk.Frame(self)
self.cpus = [0.0] * VALUES_LIMIT
self.cpus = [0.0] * self.VALUES_LIMIT
self.cpu = tk.StringVar(cpu, '0.0')
cpu.after(UPDATE_TIMEOUT,
lambda: refresh(cpu, self.cpus, self.cpu, 'CPU, {:.2f}%', VALUES_LIMIT, UPDATE_TIMEOUT,
lambda: refresh(cpu, self.cpus, self.cpu, 'CPU, {:.2f}%', self.VALUES_LIMIT, UPDATE_TIMEOUT,
color='b', figsize=PLOT_SIZE))
cpu.grid(row=1, column=0)

# memory usage
memory = tk.Frame(self)
self.memories = [0.0] * VALUES_LIMIT
self.memories = [0.0] * self.VALUES_LIMIT
self.memory = tk.StringVar(memory, '0.0')
memory.after(UPDATE_TIMEOUT,
lambda: refresh(memory, self.memories, self.memory, 'Mem, {:.2f}Кб', VALUES_LIMIT, UPDATE_TIMEOUT,
lambda: refresh(memory, self.memories, self.memory, 'Mem, {:.2f}Кб', self.VALUES_LIMIT, UPDATE_TIMEOUT,
color='#A0522D', figsize=PLOT_SIZE))
memory.grid(row=1, column=1)

# io usage
io_read = tk.Frame(self)
self.reads = [0.0] * VALUES_LIMIT
self.reads = [0.0] * self.VALUES_LIMIT
self.read_kbytes = tk.StringVar(io_read, '0.0')
io_read.after(UPDATE_TIMEOUT,
lambda: refresh(io_read, self.reads, self.read_kbytes, 'Прочитано, {}Кб', VALUES_LIMIT, UPDATE_TIMEOUT, difference=True,
lambda: refresh(io_read, self.reads, self.read_kbytes, 'Прочитано, {}Кб', self.VALUES_LIMIT, UPDATE_TIMEOUT, difference=True,
color='#20B2AA', figsize=PLOT_SIZE))
io_read.grid(row=2, column=0)

io_write = tk.Frame(self)
self.writes = [0.0] * VALUES_LIMIT
self.writes = [0.0] * self.VALUES_LIMIT
self.write_kbytes = tk.StringVar(io_write, '0.0')
io_write.after(UPDATE_TIMEOUT,
lambda: refresh(io_write, self.writes, self.write_kbytes, 'Записано, {}Кб', VALUES_LIMIT, UPDATE_TIMEOUT, difference=True,
lambda: refresh(io_write, self.writes, self.write_kbytes, 'Записано, {}Кб', self.VALUES_LIMIT, UPDATE_TIMEOUT, difference=True,
color='#DB7093', figsize=PLOT_SIZE))
io_write.grid(row=2, column=1)

Expand Down Expand Up @@ -299,9 +299,9 @@ def sort_column(tv: ttk.Treeview, column: str, reverse: bool = False, unboxer =
sort_column(tv, _column, not reverse, unboxer))


columns = ('class', 'total') #, 'gen0', 'gen1', 'gen2', 'loh', 'poh')
headings = ('Класс', 'Память, Кб') #, 'Gen 0, Кб', 'Gen 1, Кб', 'Gen 2, Кб', 'LOH, Кб', 'POH, Кб')
unboxers = (str, float)
columns = ('class', 'total', 'retained') #, 'gen0', 'gen1', 'gen2', 'loh', 'poh')
headings = ('Класс', 'Занимаемая память, Кб', 'Утекаемая память, Кб') #, 'Gen 0, Кб', 'Gen 1, Кб', 'Gen 2, Кб', 'LOH, Кб', 'POH, Кб')
unboxers = (str, float, float)
self.stats = ttk.Treeview(self, columns=columns, show='headings')
for (column, heading, unboxer) in zip(columns, headings, unboxers):
self.stats.heading(column, text=heading, command=lambda _column=column: \
Expand All @@ -317,62 +317,62 @@ def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)

UPDATE_TIMEOUT = 2000
VALUES_LIMIT = 21
self.VALUES_LIMIT = 21
PLOT_SIZE = (10, 2)

# gen 0
gen0_header = tk.Label(self, text='GC Generation 0 (Поколение 0)', anchor='w')
gen0_header.pack(fill=tk.BOTH, expand=1, padx=10)
gen0 = tk.Frame(self)
self.usage_gen0 = [0.0] * VALUES_LIMIT
self.usage_gen0 = [0.0] * self.VALUES_LIMIT
self.current_gen0 = tk.StringVar(gen0, '0.0')
gen0.after(UPDATE_TIMEOUT,
lambda: refresh(
gen0, self.usage_gen0, self.current_gen0, 'Gen 0: {:.2f}Кб',VALUES_LIMIT, UPDATE_TIMEOUT,
gen0, self.usage_gen0, self.current_gen0, 'Gen 0: {:.2f}Кб',self.VALUES_LIMIT, UPDATE_TIMEOUT,
color='#f6f64d', figsize=PLOT_SIZE))
gen0.pack(fill=tk.BOTH, expand=1)

# gen 1
gen1_header = tk.Label(self, text='GC Generation 1 (Поколение 1)', anchor='w')
gen1_header.pack(fill=tk.BOTH, expand=1, padx=10)
gen1 = tk.Frame(self)
self.usage_gen1 = [0.0] * VALUES_LIMIT
self.usage_gen1 = [0.0] * self.VALUES_LIMIT
self.current_gen1 = tk.StringVar(gen1, '0.0')
gen1.after(UPDATE_TIMEOUT,
lambda: refresh(gen1, self.usage_gen1, self.current_gen1, 'Gen 1: {:.2f}Кб', VALUES_LIMIT, UPDATE_TIMEOUT,
lambda: refresh(gen1, self.usage_gen1, self.current_gen1, 'Gen 1: {:.2f}Кб', self.VALUES_LIMIT, UPDATE_TIMEOUT,
color='#ffcc25', figsize=PLOT_SIZE))
gen1.pack(fill=tk.BOTH, expand=1)

# gen 2
gen2_header = tk.Label(self, text='GC Generation 2 (Поколение 2)', anchor='w')
gen2_header.pack(fill=tk.BOTH, expand=1, padx=10)
gen2 = tk.Frame(self)
self.usage_gen2 = [0.0] * VALUES_LIMIT
self.usage_gen2 = [0.0] * self.VALUES_LIMIT
self.current_gen2 = tk.StringVar(gen2, '0.0')
gen2.after(UPDATE_TIMEOUT,
lambda: refresh(gen2, self.usage_gen2, self.current_gen2, 'Gen 2: {:.2f}Кб', VALUES_LIMIT, UPDATE_TIMEOUT,
lambda: refresh(gen2, self.usage_gen2, self.current_gen2, 'Gen 2: {:.2f}Кб', self.VALUES_LIMIT, UPDATE_TIMEOUT,
color='#ff9f17', figsize=PLOT_SIZE))
gen2.pack(fill=tk.BOTH, expand=1)

# gc large-object heap
loh_header = tk.Label(self, text='Large-object heap (Куча больших объектов)', anchor='w')
loh_header.pack(fill=tk.BOTH, expand=1, padx=10)
loh = tk.Frame(self)
self.usage_loh = [0.0] * VALUES_LIMIT
self.usage_loh = [0.0] * self.VALUES_LIMIT
self.current_loh = tk.StringVar(loh, '0.0')
loh.after(UPDATE_TIMEOUT,
lambda: refresh(loh, self.usage_loh, self.current_loh, 'LOH: {:.2f}Кб', VALUES_LIMIT, UPDATE_TIMEOUT,
lambda: refresh(loh, self.usage_loh, self.current_loh, 'LOH: {:.2f}Кб', self.VALUES_LIMIT, UPDATE_TIMEOUT,
color='#ff7026', figsize=PLOT_SIZE))
loh.pack(fill=tk.BOTH, expand=1)

# gc pinned-object heap
poh_header = tk.Label(self, text='Pinned-object heap (Куча закрепленных объектов)', anchor='w')
poh_header.pack(fill=tk.BOTH, expand=1, padx=10)
poh = tk.Frame(self)
self.usage_poh = [0.0] * VALUES_LIMIT
self.usage_poh = [0.0] * self.VALUES_LIMIT
self.current_poh = tk.StringVar(poh, '0.0')
loh.after(UPDATE_TIMEOUT,
lambda: refresh(poh, self.usage_poh, self.current_poh, 'POH: {:.2f}Кб', VALUES_LIMIT, UPDATE_TIMEOUT,
lambda: refresh(poh, self.usage_poh, self.current_poh, 'POH: {:.2f}Кб', self.VALUES_LIMIT, UPDATE_TIMEOUT,
color='#f63838', figsize=PLOT_SIZE))
poh.pack(fill=tk.BOTH, expand=1)

Expand Down
9 changes: 8 additions & 1 deletion utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,11 @@ def unix2str(timestamp: float) -> str:

SessionQueues = namedtuple('SessionQueues', ['pending', 'start', 'finish', 'logs', 'threads', 'stats', 'allocations', 'objects'])

ManagedObject = namedtuple('ManagedObject', ['class_name', 'size', 'generation'])
class ManagedObject:
def __init__(self, class_name, size, generation, is_retained):
self.class_name = class_name
self.size = size
self.generation = generation
self.is_retained = is_retained

# ManagedObject = namedtuple('ManagedObject', ['class_name', 'size', 'generation', 'is_retained'])
57 changes: 55 additions & 2 deletions visualclrapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,55 @@ def start_session(self, event):
self.init_tabs(data)

def init_tabs(self, data):
# common
self.common.pid.set(f"PID: {data['pid']}")
self.common.path.set(f"PATH: {data['path']}")
self.common.sdks.set(f"SDKs: {list_sdks(data['path'])}")
self.common.rts.set(f"Runtimes: {list_runtimes(data['path'])}")
self.common.cmd.set(f"CMD: {data['cmd']}")

# metrics
reset_list = [0.0] * self.metrics.VALUES_LIMIT
self.metrics.threads = reset_list.copy()
self.metrics.thread.set(0)
self.metrics.exceptions = reset_list.copy()
self.metrics.exception.set(0)
self.metrics.cpus = reset_list.copy()
self.metrics.cpu.set('0.0')
self.metrics.memories = reset_list.copy()
self.metrics.memory.set('0.0')
self.metrics.reads = reset_list.copy()
self.metrics.read_kbytes.set('0.0')
self.metrics.writes = reset_list.copy()
self.metrics.write_kbytes.set('0.0')
self.metrics.classes.set(0)
self.metrics.objects_disposed.set(0)
self.metrics.classes_loaded.set(0)
self.metrics.classes_unloaded.set(0)
# TODO: update labels
# logs
self.traces.logs.delete('1.0', tk.END)
self.objects.stats.delete(*self.objects.stats.get_children(''))
# threads
self.threads.listv.set([])

# gc
reset_list = [0.0] * self.gc.VALUES_LIMIT
self.gc.usage_gen0 = reset_list.copy()
self.gc.current_gen0.set('0.0')
self.gc.usage_gen1 = reset_list.copy()
self.gc.current_gen1.set('0.0')
self.gc.usage_gen2 = reset_list.copy()
self.gc.current_gen2.set('0.0')
self.gc.usage_loh = reset_list.copy()
self.gc.current_loh.set('0.0')
self.gc.usage_poh = reset_list.copy()
self.gc.current_poh.set('0.0')

# self fields
self.threads_data = {}
self.objects_data = {}

def append_log(self, event):
while not self.queues.logs.empty():
log = self.queues.logs.get()
Expand Down Expand Up @@ -211,7 +254,7 @@ def allocate_object(self, event):
classes = set(map(lambda child: objects.set(child, 'class'), objects.get_children('')))
if request.class_name not in classes:
objects.insert('', tk.END, \
values=(request.class_name, round(request.size / 1024, 2)))
values=(request.class_name, round(request.size / 1024, 2), 0.0))
else:
updated_children = filter(lambda child: objects.set(child, 'class') == request.class_name,
objects.get_children(''))
Expand All @@ -223,7 +266,8 @@ def allocate_object(self, event):
self.objects_data[id] = ManagedObject(
request.class_name,
request.size,
GcGenerations.from_value(g)
GcGenerations.from_value(g),
False
)
# update gc gen
self._update_generation(self.objects_data[id].generation, +request.size)
Expand All @@ -240,12 +284,21 @@ def update_objects(self, event):
# update gc gens
object_data.generation = GcGenerations.from_value(object.generation.value)
self._update_generation(object_data.generation, +object_data.size)
# survived collection
object_data.is_retained = True
updated_children = filter(lambda child: objects.set(child, 'class') == object_data.class_name, objects.get_children(''))
for child in updated_children:
prev = float(objects.set(child, 'retained')) * 1024
objects.set(child, 'retained', round((prev + object_data.size) / 1024, 2))
else:
# disposed
updated_children = filter(lambda child: objects.set(child, 'class') == object_data.class_name, objects.get_children(''))
for child in updated_children:
prev = float(objects.set(child, 'total')) * 1024
objects.set(child, 'total', round((prev - object_data.size) / 1024, 2))
if object_data.is_retained:
prev = float(objects.set(child, 'retained')) * 1024
objects.set(child, 'retained', round((prev - object_data.size) / 1024, 2))

_fold_variable(self.metrics.objects_disposed, 1)
self.metrics.objects_disposed_v.set(
Expand Down

0 comments on commit 7f09108

Please sign in to comment.