2020-06-03 18:40:05 -04:00
|
|
|
# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
|
|
|
|
#
|
|
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
|
2016-11-23 20:31:53 -05:00
|
|
|
import sys
|
|
|
|
import json
|
|
|
|
|
|
|
|
# Map start block to current allocation info.
|
|
|
|
current_heap = {}
|
|
|
|
allocation_history = []
|
|
|
|
root = {}
|
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
|
2016-11-23 20:31:53 -05:00
|
|
|
def change_root(trace, size):
|
|
|
|
level = root
|
|
|
|
for frame in reversed(trace):
|
|
|
|
file_location = frame[1]
|
|
|
|
if file_location not in level:
|
2021-03-15 09:57:36 -04:00
|
|
|
level[file_location] = {
|
|
|
|
"blocks": 0,
|
|
|
|
"file": file_location,
|
|
|
|
"function": frame[2],
|
|
|
|
"subcalls": {},
|
|
|
|
}
|
2016-11-23 20:31:53 -05:00
|
|
|
level[file_location]["blocks"] += size
|
|
|
|
level = level[file_location]["subcalls"]
|
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
|
2016-11-23 20:31:53 -05:00
|
|
|
total_actions = 0
|
|
|
|
with open(sys.argv[1], "r") as f:
|
|
|
|
for line in f:
|
|
|
|
if not line.strip():
|
|
|
|
break
|
|
|
|
for line in f:
|
|
|
|
action = None
|
|
|
|
if line.startswith("Breakpoint 2"):
|
|
|
|
break
|
2021-03-15 09:57:36 -04:00
|
|
|
next(f) # throw away breakpoint code line
|
|
|
|
next(f) # first frame
|
2016-11-23 20:31:53 -05:00
|
|
|
block = 0
|
|
|
|
size = 0
|
|
|
|
trace = []
|
|
|
|
for line in f:
|
2021-03-15 09:57:36 -04:00
|
|
|
# print(line.strip())
|
2016-11-23 20:31:53 -05:00
|
|
|
if line[0] == "#":
|
|
|
|
frame = line.strip().split()
|
|
|
|
if frame[1].startswith("0x"):
|
|
|
|
trace.append((frame[1], frame[-1], frame[3]))
|
|
|
|
else:
|
|
|
|
trace.append(("0x0", frame[-1], frame[1]))
|
|
|
|
elif line[0] == "$":
|
|
|
|
block = int(line.strip().split()[-1][2:], 16)
|
|
|
|
size = int(next(f).strip().split()[-1][2:], 16)
|
|
|
|
if not line.strip():
|
|
|
|
break
|
|
|
|
|
|
|
|
action = "unknown"
|
|
|
|
if block not in current_heap:
|
2021-03-15 09:57:36 -04:00
|
|
|
current_heap[block] = {
|
|
|
|
"start_block": block,
|
|
|
|
"size": size,
|
|
|
|
"start_trace": trace,
|
|
|
|
"start_time": total_actions,
|
|
|
|
}
|
2016-11-23 20:31:53 -05:00
|
|
|
action = "alloc"
|
|
|
|
change_root(trace, size)
|
|
|
|
else:
|
|
|
|
alloc = current_heap[block]
|
|
|
|
alloc["end_trace"] = trace
|
|
|
|
alloc["end_time"] = total_actions
|
|
|
|
change_root(alloc["start_trace"], -1 * alloc["size"])
|
|
|
|
if size > 0:
|
|
|
|
action = "realloc"
|
2021-03-15 09:57:36 -04:00
|
|
|
current_heap[block] = {
|
|
|
|
"start_block": block,
|
|
|
|
"size": size,
|
|
|
|
"start_trace": trace,
|
|
|
|
"start_time": total_actions,
|
|
|
|
}
|
2016-11-23 20:31:53 -05:00
|
|
|
change_root(trace, size)
|
|
|
|
else:
|
|
|
|
action = "free"
|
|
|
|
if trace[0][2] == "gc_sweep":
|
|
|
|
action = "sweep"
|
|
|
|
del current_heap[block]
|
|
|
|
alloc["end_cause"] = action
|
|
|
|
allocation_history.append(alloc)
|
|
|
|
print(total_actions, action, block, size)
|
|
|
|
total_actions += 1
|
|
|
|
|
|
|
|
print()
|
|
|
|
|
|
|
|
for alloc in current_heap.values():
|
|
|
|
alloc["end_trace"] = ""
|
|
|
|
alloc["end_time"] = total_actions
|
|
|
|
allocation_history.append(alloc)
|
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
|
2016-11-23 20:31:53 -05:00
|
|
|
def print_frame(frame, indent=0):
|
|
|
|
for key in sorted(frame):
|
2021-03-15 09:57:36 -04:00
|
|
|
if (
|
|
|
|
not frame[key]["blocks"]
|
|
|
|
or key.startswith("../py/malloc.c")
|
|
|
|
or key.startswith("../py/gc.c")
|
|
|
|
):
|
2016-11-23 20:31:53 -05:00
|
|
|
continue
|
|
|
|
print(" " * (indent - 1), key, frame[key]["function"], frame[key]["blocks"], "blocks")
|
|
|
|
print_frame(frame[key]["subcalls"], indent + 2)
|
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
|
2016-11-23 20:31:53 -05:00
|
|
|
print_frame(root)
|
|
|
|
total_blocks = 0
|
|
|
|
for key in sorted(root):
|
|
|
|
total_blocks += root[key]["blocks"]
|
|
|
|
print(total_blocks, "total blocks")
|
|
|
|
|
|
|
|
with open("allocation_history.json", "w") as f:
|
|
|
|
json.dump(allocation_history, f)
|