Skip to content

Commit 2757042

Browse files
committed
added initial memory tracking
1 parent 0fd7405 commit 2757042

8 files changed

Lines changed: 100 additions & 23 deletions

File tree

example_usage/example1.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,28 @@
11
import random
2+
import resource
23
from time import sleep
34

45
from logic.profiling_meta import ProfilingMeta
56

67

78

9+
from resource import *
10+
import time
11+
12+
# a non CPU-bound task
13+
time.sleep(3)
814

915
class Example(metaclass=ProfilingMeta):
1016

1117
@staticmethod
1218
def ex1_func():
19+
a = [1] * (10 ** 6)
20+
b = [1] * (10 ** 6)
1321
print("1")
1422
sleep(2)
1523
Example.ex2_func()
1624
sleep(3)
1725
print("2")
18-
1926
@staticmethod
2027
def ex2_func():
2128
print("1")
@@ -24,6 +31,8 @@ def ex2_func():
2431

2532
@staticmethod
2633
def ex3_func():
34+
a = [1] * (10 ** 7)
35+
b = [1] * (10 ** 7)
2736
print("1")
2837
sleep(random.randint(0,5))
2938
print("2")

logic/profiling_decorators.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

2+
import functools
23
import os
4+
import resource
35
import socket
46
from datetime import datetime
57
import uuid
@@ -9,6 +11,7 @@ class ProfilingDecorators:
911
PORT = int(os.environ.get('PORT', "65433") )
1012

1113
def time_profile(func):
14+
@functools.wraps(func)
1215
def wrapper(*args, **kwargs):
1316
start = datetime.now()
1417
val = func(*args, **kwargs)
@@ -18,4 +21,15 @@ def wrapper(*args, **kwargs):
1821
s.sendall(bytes('time;'+str(uuid.uuid1()) +';'+str(func.__name__) +';'+ str(start) + ';'+str(end), 'utf-8'))
1922
return val
2023
return wrapper
24+
def memory_profile(func):
25+
@functools.wraps(func)
26+
def wrapper(*args, **kwargs):
27+
start = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
28+
val = func(*args, **kwargs)
29+
end = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
30+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
31+
s.connect((ProfilingDecorators.HOST, ProfilingDecorators.PORT))
32+
s.sendall(bytes('memory;'+str(uuid.uuid1()) +';'+str(func.__name__) +';'+ str(start) + ';'+str(end), 'utf-8'))
33+
return val
34+
return wrapper
2135

logic/profiling_meta.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from logic.profiling_decorators import ProfilingDecorators
22

3-
43
class ProfilingMeta(type):
54
def __new__(cls, name, bases, class_dict):
65
for key, value in class_dict.items():
76
if callable(value):
8-
class_dict[key] = ProfilingDecorators.time_profile(value)
7+
class_dict[key] = ProfilingDecorators.time_profile(ProfilingDecorators.memory_profile(value))
98
return super().__new__(cls, name, bases, class_dict)

logic/stamps/memory_stamp.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from dataclasses import dataclass
2+
3+
from logic.stamps.base_stamp import BaseStamp
4+
5+
6+
@dataclass
7+
class MemoryStamp(BaseStamp):
8+
"""
9+
object that holds a time stap and additional info about the function
10+
"""
11+
start_memory:float
12+
end_memory:float
13+
14+
@staticmethod
15+
def init_from_bytes(split_desc_string):
16+
"""
17+
init date time from a string
18+
"""
19+
if len(split_desc_string) > 0:
20+
21+
id = split_desc_string[0]
22+
name = split_desc_string[1]
23+
start_memory = float(split_desc_string[2])
24+
end_memory = float(split_desc_string[3])
25+
26+
return MemoryStamp(id=id,name=name,start_memory=start_memory,end_memory=end_memory)
27+
28+
def __lt__(self, other):
29+
return self.end_memory - self.start_memory < other.end_memory - other.start_memory

profiler_server.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import socket
33
from controller import Model
4+
from logic.stamps.memory_stamp import MemoryStamp
45

56
from logic.stamps.time_stamp import TimeStamp
67

@@ -32,7 +33,7 @@ def init_stamp_from_bytes(data):
3233
match split_desc_string[0]:
3334
case 'time':
3435
Model.add_time_stamp(split_desc_string[1],TimeStamp.init_from_bytes(split_desc_string[1:]))
35-
case 'mem':
36+
case 'memory':
3637
# TODO FIX
37-
Model.add_memmory_stamp(split_desc_string[1],TimeStamp.init_from_bytes(split_desc_string[1:]))
38+
Model.add_memmory_stamp(split_desc_string[1],MemoryStamp.init_from_bytes(split_desc_string[1:]))
3839

view/base_view.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22

33

44
@dataclass
5-
class Baseview():
5+
class Baseview:
66
width:int = 500
77
height:int = 500
88
color:str = '#FFFFFF'
99
canvas_scaler:int=40
1010
rectange_height:int = 60
11-
rectange_spacing:int = 5
11+
rectange_width:int = 20
12+
rectange_spacing:int = 5
13+
def draw_rect(self,x1,x2,y1,y2):
14+
self.canvas.create_rectangle((x1,x2,y1,y2),fill='red')
15+
def destroy(self):
16+
self.frame.destroy()

view/memory_view.py

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from tkinter import *
2+
from controller import Model
23

34
from view.base_view import Baseview
45

@@ -9,23 +10,46 @@ def __init__(self,root) -> None:
910
self.root=root
1011
self.frame=Frame(self.root,width=self.width,height=self.height)
1112
label = Label(self.frame,text="Memory profiling")
12-
label.pack()
13+
copy = Model.MEMORY_STAMPS.copy()
1314

15+
mlist = list(copy.values())
16+
if len(copy) > 0:
17+
self.canvas=Canvas(self.frame,bg=self.color,width=self.width,height=self.height,scrollregion=(0,0,max(self.rectange_width*len(copy),self.width),max(max(mlist).end_memory - max(mlist).start_memory,self.height*self.canvas_scaler)))
18+
else :
19+
self.canvas=Canvas(self.frame,bg=self.color,width=self.width,height=self.height,scrollregion=(0,0,self.width*self.canvas_scaler,self.height*self.canvas_scaler))
1420
def draw(self):
1521
self.frame.pack(expand=True, fill=BOTH)
16-
canvas=Canvas(self.frame,bg=self.color,width=self.width,height=self.height,scrollregion=(0,0,self.width*self.canvas_scaler,self.height*self.canvas_scaler))
22+
1723
hbar=Scrollbar(self.frame,orient=HORIZONTAL)
1824
hbar.pack(side=BOTTOM,fill=X)
19-
hbar.config(command=canvas.xview)
25+
hbar.config(command=self.canvas.xview)
2026
vbar=Scrollbar(self.frame,orient=VERTICAL)
2127
vbar.pack(side=RIGHT,fill=Y)
22-
vbar.config(command=canvas.yview)
23-
canvas.config(width=self.width,height=self.height)
24-
canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
25-
canvas.pack(side=LEFT,expand=True,fill=BOTH)
28+
vbar.config(command=self.canvas.yview)
29+
self.canvas.config(width=self.width,height=self.height)
30+
self.canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set)
31+
self.canvas.pack(side=LEFT,expand=True,fill=BOTH)
32+
self.update()
2633

27-
def draw_rect(self,x1,x2,y1,y2):
28-
self.canvas.create_rectangle((x1,x2,y1,y2))
29-
30-
def destroy(self):
31-
self.frame.destroy()
34+
def update(self):
35+
copy = Model.MEMORY_STAMPS.copy()
36+
if len(copy) <=0:
37+
return
38+
mlist = list(copy.values())
39+
mlist_sorted= sorted(mlist)
40+
max_mlist=max(mlist)
41+
for index,i in enumerate(mlist_sorted):
42+
memory_stamp = i
43+
memory_leaked = memory_stamp.end_memory - memory_stamp.start_memory
44+
if memory_leaked == 0 :
45+
continue
46+
self.scaler = 1/10
47+
x = index * (self.rectange_width + self.rectange_spacing)
48+
y = (max_mlist.end_memory - max_mlist.start_memory) *self.scaler
49+
width = x + self.rectange_width + 50
50+
height = memory_leaked *self.scaler# it is in kb
51+
self.draw_rect( x ,y ,width ,height)
52+
53+
self.canvas.create_text((x + width )/2 ,(y +height)/2 -self.rectange_height/3 , text=memory_stamp.name , fill="white")
54+
self.canvas.create_text((x + width )/2 ,(y +height)/2 , text='memory_leaked: '+str(memory_leaked), fill="white")
55+
self.canvas.create_text((x + width )/2 ,(y +height)/2 +self.rectange_height/3, text=memory_stamp.id, fill="white")

view/time_view.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,3 @@ def update(self):
4848
self.canvas.create_text((x + width )/2 ,(y +height)/2 -self.rectange_height/3 , text=time_stamp.name , fill="white")
4949
self.canvas.create_text((x + width )/2 ,(y +height)/2 , text=str(time.seconds)+' seconds', fill="white")
5050
self.canvas.create_text((x + width )/2 ,(y +height)/2 +self.rectange_height/3, text=time_stamp.id, fill="white")
51-
def draw_rect(self,x1,x2,y1,y2):
52-
self.canvas.create_rectangle((x1,x2,y1,y2),fill='red')
53-
def destroy(self):
54-
self.frame.destroy()

0 commit comments

Comments
 (0)