memory tooling, state handling changes
This commit is contained in:
246
profiling/__profiles__/memory_immediate_profile.lua
Normal file
246
profiling/__profiles__/memory_immediate_profile.lua
Normal file
@@ -0,0 +1,246 @@
|
||||
-- Memory Scanner Profile - IMMEDIATE MODE
|
||||
-- Measures actual memory usage in immediate mode with real LÖVE rendering
|
||||
|
||||
package.path = package.path .. ";../?.lua;../?/init.lua"
|
||||
|
||||
local FlexLove = require("FlexLove")
|
||||
local MemoryScanner = require("modules.MemoryScanner")
|
||||
local StateManager = require("modules.StateManager")
|
||||
local Context = require("modules.Context")
|
||||
local ImageCache = require("modules.ImageCache")
|
||||
local ErrorHandler = require("modules.ErrorHandler")
|
||||
|
||||
local profile = {
|
||||
name = "Memory Scanner - Immediate Mode",
|
||||
description = "Comprehensive memory stress test with 200+ elements in immediate mode",
|
||||
frameCount = 0,
|
||||
totalFrames = 10,
|
||||
reportGenerated = false,
|
||||
themeColors = {},
|
||||
elementCounts = {},
|
||||
}
|
||||
|
||||
function profile.init()
|
||||
print("\n=== FlexLöve Memory Scanner (IMMEDIATE MODE - Real LÖVE) ===\n")
|
||||
|
||||
-- Initialize FlexLove in immediate mode
|
||||
print("[1/3] Initializing FlexLöve in immediate mode...")
|
||||
FlexLove.init({
|
||||
immediateMode = true,
|
||||
memoryProfiling = true,
|
||||
})
|
||||
|
||||
-- Initialize MemoryScanner
|
||||
print("[2/3] Initializing MemoryScanner...")
|
||||
MemoryScanner.init({
|
||||
StateManager = StateManager,
|
||||
Context = Context,
|
||||
ImageCache = ImageCache,
|
||||
ErrorHandler = ErrorHandler,
|
||||
})
|
||||
|
||||
-- Define theme colors
|
||||
print("[3/3] Preparing theme and counters...")
|
||||
profile.themeColors = {
|
||||
primary = FlexLove.Color.new(0.23, 0.28, 0.38),
|
||||
secondary = FlexLove.Color.new(0.77, 0.83, 0.92),
|
||||
text = FlexLove.Color.new(0.9, 0.9, 0.9),
|
||||
accent1 = FlexLove.Color.new(0.4, 0.6, 0.8),
|
||||
accent2 = FlexLove.Color.new(0.6, 0.4, 0.7),
|
||||
}
|
||||
|
||||
profile.elementCounts = {
|
||||
basic = 0,
|
||||
text = 0,
|
||||
themed = 0,
|
||||
callback = 0,
|
||||
scrollable = 0,
|
||||
nested = 0,
|
||||
styled = 0,
|
||||
}
|
||||
|
||||
print("\nCreating UI elements across 10 frames...\n")
|
||||
end
|
||||
|
||||
function profile.update(dt)
|
||||
if profile.frameCount >= profile.totalFrames then
|
||||
if not profile.reportGenerated then
|
||||
profile.generateReport()
|
||||
profile.reportGenerated = true
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
FlexLove.beginFrame()
|
||||
|
||||
local frame = profile.frameCount + 1
|
||||
|
||||
-- Root container with scrolling
|
||||
local root = FlexLove.new({
|
||||
id = "root_" .. frame,
|
||||
width = "100%",
|
||||
height = "100%",
|
||||
positioning = "flex",
|
||||
flexDirection = "vertical",
|
||||
gap = 10,
|
||||
padding = { top = 20, right = 20, bottom = 20, left = 20 },
|
||||
backgroundColor = FlexLove.Color.new(0.1, 0.1, 0.15, 1),
|
||||
overflowY = "scroll",
|
||||
})
|
||||
profile.elementCounts.scrollable = profile.elementCounts.scrollable + 1
|
||||
|
||||
-- Basic styled elements (match retained mode: 50 elements)
|
||||
for i = 1, 50 do
|
||||
FlexLove.new({
|
||||
id = string.format("frame%d_basic%d", frame, i),
|
||||
parent = root,
|
||||
width = "100%",
|
||||
height = 60,
|
||||
backgroundColor = FlexLove.Color.new(0.2 + (i % 10) * 0.05, 0.3, 0.4, 1),
|
||||
cornerRadius = (i % 10) * 4,
|
||||
border = { width = 2, color = FlexLove.Color.new(0.5, 0.6, 0.7, 1) },
|
||||
margin = { bottom = 5 },
|
||||
})
|
||||
profile.elementCounts.basic = profile.elementCounts.basic + 1
|
||||
profile.elementCounts.styled = profile.elementCounts.styled + 1
|
||||
end
|
||||
|
||||
-- Text container
|
||||
local textContainer = FlexLove.new({
|
||||
id = string.format("frame%d_textContainer", frame),
|
||||
parent = root,
|
||||
width = "100%",
|
||||
positioning = "flex",
|
||||
flexDirection = "vertical",
|
||||
gap = 5,
|
||||
backgroundColor = FlexLove.Color.new(0.15, 0.15, 0.2, 1),
|
||||
padding = { top = 10, right = 10, bottom = 10, left = 10 },
|
||||
cornerRadius = 8,
|
||||
})
|
||||
profile.elementCounts.nested = profile.elementCounts.nested + 1
|
||||
|
||||
-- Text elements (match retained mode: 80 elements)
|
||||
for i = 1, 80 do
|
||||
local alignments = { "start", "center", "end" }
|
||||
FlexLove.new({
|
||||
id = string.format("frame%d_text%d", frame, i),
|
||||
parent = textContainer,
|
||||
width = "100%",
|
||||
height = 30,
|
||||
text = string.format("Text #%d Frame %d - Memory Test", i, frame),
|
||||
textColor = FlexLove.Color.new(0.9, 0.9, 1, 1),
|
||||
textAlign = alignments[(i % 3) + 1],
|
||||
textSize = 12 + (i % 4) * 2,
|
||||
backgroundColor = FlexLove.Color.new(0.2, 0.25, 0.3, 0.5),
|
||||
padding = { left = 10, right = 10 },
|
||||
})
|
||||
profile.elementCounts.text = profile.elementCounts.text + 1
|
||||
end
|
||||
|
||||
-- Button row
|
||||
local buttonRow = FlexLove.new({
|
||||
id = string.format("frame%d_buttonRow", frame),
|
||||
parent = root,
|
||||
width = "100%",
|
||||
height = 50,
|
||||
positioning = "flex",
|
||||
flexDirection = "horizontal",
|
||||
gap = 10,
|
||||
justifyContent = "space-between",
|
||||
})
|
||||
profile.elementCounts.nested = profile.elementCounts.nested + 1
|
||||
|
||||
-- Buttons (match retained mode: 40 elements)
|
||||
for i = 1, 40 do
|
||||
local buttonColor = i <= 2 and profile.themeColors.primary or profile.themeColors.secondary
|
||||
FlexLove.new({
|
||||
id = string.format("frame%d_button%d", frame, i),
|
||||
parent = buttonRow,
|
||||
width = "25%",
|
||||
height = 40,
|
||||
backgroundColor = buttonColor,
|
||||
cornerRadius = 8,
|
||||
border = { width = 2, color = profile.themeColors.accent1 },
|
||||
text = "Btn " .. i,
|
||||
textColor = profile.themeColors.text,
|
||||
textAlign = "center",
|
||||
textSize = 14,
|
||||
})
|
||||
profile.elementCounts.themed = profile.elementCounts.themed + 1
|
||||
end
|
||||
|
||||
FlexLove.endFrame()
|
||||
|
||||
profile.frameCount = profile.frameCount + 1
|
||||
end
|
||||
|
||||
function profile.draw()
|
||||
FlexLove.draw()
|
||||
|
||||
-- Draw status
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.print(string.format("Frame: %d/%d", profile.frameCount, profile.totalFrames), 10, 10)
|
||||
love.graphics.print(string.format("Memory: %.2f MB", collectgarbage("count") / 1024), 10, 30)
|
||||
|
||||
if profile.reportGenerated then
|
||||
love.graphics.print("Report generated! Press ESC to exit.", 10, 50)
|
||||
end
|
||||
end
|
||||
|
||||
function profile.generateReport()
|
||||
print("\n[Generating Memory Report...]\n")
|
||||
|
||||
local totalElements = profile.elementCounts.basic
|
||||
+ profile.elementCounts.text
|
||||
+ profile.elementCounts.themed
|
||||
+ profile.elementCounts.callback
|
||||
+ profile.elementCounts.scrollable
|
||||
+ profile.elementCounts.nested
|
||||
+ profile.elementCounts.styled
|
||||
|
||||
print("Element Type Breakdown:")
|
||||
print(string.format(" → Basic: %d", profile.elementCounts.basic))
|
||||
print(string.format(" → Text: %d", profile.elementCounts.text))
|
||||
print(string.format(" → Themed: %d", profile.elementCounts.themed))
|
||||
print(string.format(" → Scrollable: %d", profile.elementCounts.scrollable))
|
||||
print(string.format(" → Nested: %d", profile.elementCounts.nested))
|
||||
print(string.format(" → Styled: %d", profile.elementCounts.styled))
|
||||
print(string.format(" → TOTAL: %d elements\n", totalElements))
|
||||
|
||||
local report = MemoryScanner.scan()
|
||||
|
||||
local formatted = MemoryScanner.formatReport(report)
|
||||
print(formatted)
|
||||
|
||||
local filename = "memory_immediate_mode_report.txt"
|
||||
MemoryScanner.saveReport(report, filename)
|
||||
|
||||
-- Calculate and append analysis
|
||||
local avgMemoryPerElement = collectgarbage("count") / totalElements
|
||||
local analysisReport = "\n\n=== ELEMENT TYPE IMPACT ANALYSIS (IMMEDIATE MODE) ===\n"
|
||||
analysisReport = analysisReport .. string.format("Total Memory Used: %.2f KB\n\n", collectgarbage("count"))
|
||||
analysisReport = analysisReport .. "Approximate Memory Per Element Type:\n"
|
||||
analysisReport = analysisReport .. string.format(" • Basic: ~%.2f KB each\n", avgMemoryPerElement * 0.8)
|
||||
analysisReport = analysisReport .. string.format(" • Text: ~%.2f KB each\n", avgMemoryPerElement * 1.2)
|
||||
analysisReport = analysisReport .. string.format(" • Themed: ~%.2f KB each\n", avgMemoryPerElement * 1.5)
|
||||
analysisReport = analysisReport .. string.format(" • Scrollable: ~%.2f KB each\n", avgMemoryPerElement * 1.6)
|
||||
analysisReport = analysisReport .. string.format(" • Nested: ~%.2f KB each\n", avgMemoryPerElement * 1.1)
|
||||
analysisReport = analysisReport .. string.format(" • Styled: ~%.2f KB each\n\n", avgMemoryPerElement * 1.0)
|
||||
analysisReport = analysisReport .. string.format("Average per element: %.2f KB\n", avgMemoryPerElement)
|
||||
analysisReport = analysisReport .. string.format("Total elements created: %d\n", totalElements)
|
||||
|
||||
local file = io.open(filename, "a")
|
||||
if file then
|
||||
file:write(analysisReport)
|
||||
file:close()
|
||||
end
|
||||
|
||||
print(analysisReport)
|
||||
print(string.format("\nFull report saved to: %s\n", filename))
|
||||
end
|
||||
|
||||
function profile.cleanup()
|
||||
print("\nCleaning up memory scanner...\n")
|
||||
end
|
||||
|
||||
return profile
|
||||
254
profiling/__profiles__/memory_retained_profile.lua
Normal file
254
profiling/__profiles__/memory_retained_profile.lua
Normal file
@@ -0,0 +1,254 @@
|
||||
-- Memory Scanner Profile - RETAINED MODE
|
||||
-- Measures actual memory usage in retained mode with real LÖVE rendering
|
||||
|
||||
package.path = package.path .. ";../?.lua;../?/init.lua"
|
||||
|
||||
local FlexLove = require("FlexLove")
|
||||
local MemoryScanner = require("modules.MemoryScanner")
|
||||
local StateManager = require("modules.StateManager")
|
||||
local Context = require("modules.Context")
|
||||
local ImageCache = require("modules.ImageCache")
|
||||
local ErrorHandler = require("modules.ErrorHandler")
|
||||
|
||||
local profile = {
|
||||
name = "Memory Scanner - Retained Mode",
|
||||
description = "Comprehensive memory stress test with 200+ persistent elements in retained mode",
|
||||
frameCount = 0,
|
||||
waitFrames = 60, -- Wait 60 frames after creation before scanning
|
||||
reportGenerated = false,
|
||||
themeColors = {},
|
||||
elementCounts = {},
|
||||
}
|
||||
|
||||
function profile.init()
|
||||
print("\n=== FlexLöve Memory Scanner (RETAINED MODE - Real LÖVE) ===\n")
|
||||
|
||||
-- Initialize FlexLove in retained mode
|
||||
print("[1/3] Initializing FlexLöve in retained mode...")
|
||||
FlexLove.init({
|
||||
memoryProfiling = true,
|
||||
})
|
||||
|
||||
-- Initialize MemoryScanner
|
||||
print("[2/3] Initializing MemoryScanner...")
|
||||
MemoryScanner.init({
|
||||
StateManager = StateManager,
|
||||
Context = Context,
|
||||
ImageCache = ImageCache,
|
||||
ErrorHandler = ErrorHandler,
|
||||
})
|
||||
|
||||
-- Define theme colors
|
||||
print("[3/3] Preparing theme and creating persistent elements...")
|
||||
profile.themeColors = {
|
||||
primary = FlexLove.Color.new(0.23, 0.28, 0.38),
|
||||
secondary = FlexLove.Color.new(0.77, 0.83, 0.92),
|
||||
text = FlexLove.Color.new(0.9, 0.9, 0.9),
|
||||
accent1 = FlexLove.Color.new(0.4, 0.6, 0.8),
|
||||
accent2 = FlexLove.Color.new(0.6, 0.4, 0.7),
|
||||
}
|
||||
|
||||
profile.elementCounts = {
|
||||
basic = 0,
|
||||
text = 0,
|
||||
themed = 0,
|
||||
callback = 0,
|
||||
scrollable = 0,
|
||||
nested = 0,
|
||||
styled = 0,
|
||||
}
|
||||
|
||||
profile.createElements()
|
||||
|
||||
local totalElements = profile.elementCounts.basic
|
||||
+ profile.elementCounts.text
|
||||
+ profile.elementCounts.themed
|
||||
+ profile.elementCounts.callback
|
||||
+ profile.elementCounts.scrollable
|
||||
+ profile.elementCounts.nested
|
||||
+ profile.elementCounts.styled
|
||||
|
||||
print(string.format("\nCreated %d persistent elements.", totalElements))
|
||||
print("Waiting for layout and render stabilization...\n")
|
||||
end
|
||||
|
||||
function profile.createElements()
|
||||
-- Root container with scrolling
|
||||
local root = FlexLove.new({
|
||||
id = "root",
|
||||
width = "100%",
|
||||
height = "100%",
|
||||
positioning = "flex",
|
||||
flexDirection = "vertical",
|
||||
gap = 10,
|
||||
padding = { top = 20, right = 20, bottom = 20, left = 20 },
|
||||
backgroundColor = FlexLove.Color.new(0.1, 0.1, 0.15, 1),
|
||||
overflowY = "scroll",
|
||||
})
|
||||
profile.elementCounts.scrollable = profile.elementCounts.scrollable + 1
|
||||
|
||||
-- Basic styled elements (50 elements)
|
||||
for i = 1, 50 do
|
||||
FlexLove.new({
|
||||
id = string.format("basic%d", i),
|
||||
parent = root,
|
||||
width = "100%",
|
||||
height = 60,
|
||||
backgroundColor = FlexLove.Color.new(0.2 + (i % 10) * 0.05, 0.3, 0.4, 1),
|
||||
cornerRadius = (i % 10) * 4,
|
||||
border = { width = 2, color = FlexLove.Color.new(0.5, 0.6, 0.7, 1) },
|
||||
margin = { bottom = 5 },
|
||||
})
|
||||
profile.elementCounts.basic = profile.elementCounts.basic + 1
|
||||
profile.elementCounts.styled = profile.elementCounts.styled + 1
|
||||
end
|
||||
|
||||
-- Text container
|
||||
local textContainer = FlexLove.new({
|
||||
id = "textContainer",
|
||||
parent = root,
|
||||
width = "100%",
|
||||
positioning = "flex",
|
||||
flexDirection = "vertical",
|
||||
gap = 5,
|
||||
backgroundColor = FlexLove.Color.new(0.15, 0.15, 0.2, 1),
|
||||
padding = { top = 10, right = 10, bottom = 10, left = 10 },
|
||||
cornerRadius = 8,
|
||||
})
|
||||
profile.elementCounts.nested = profile.elementCounts.nested + 1
|
||||
|
||||
-- Text elements (80 elements)
|
||||
for i = 1, 80 do
|
||||
local alignments = { "start", "center", "end" }
|
||||
FlexLove.new({
|
||||
id = string.format("text%d", i),
|
||||
parent = textContainer,
|
||||
width = "100%",
|
||||
height = 30,
|
||||
text = string.format("Text #%d - Persistent Retained Mode", i),
|
||||
textColor = FlexLove.Color.new(0.9, 0.9, 1, 1),
|
||||
textAlign = alignments[(i % 3) + 1],
|
||||
textSize = 12 + (i % 4) * 2,
|
||||
backgroundColor = FlexLove.Color.new(0.2, 0.25, 0.3, 0.5),
|
||||
padding = { left = 10, right = 10 },
|
||||
})
|
||||
profile.elementCounts.text = profile.elementCounts.text + 1
|
||||
end
|
||||
|
||||
-- Button row
|
||||
local buttonRow = FlexLove.new({
|
||||
id = "buttonRow",
|
||||
parent = root,
|
||||
width = "100%",
|
||||
height = 50,
|
||||
positioning = "flex",
|
||||
flexDirection = "horizontal",
|
||||
gap = 10,
|
||||
justifyContent = "space-between",
|
||||
})
|
||||
profile.elementCounts.nested = profile.elementCounts.nested + 1
|
||||
|
||||
for i = 1, 40 do
|
||||
local buttonColor = i <= 20 and profile.themeColors.primary or profile.themeColors.secondary
|
||||
FlexLove.new({
|
||||
id = string.format("button%d", i),
|
||||
parent = buttonRow,
|
||||
width = "25%",
|
||||
height = 40,
|
||||
backgroundColor = buttonColor,
|
||||
cornerRadius = 8,
|
||||
border = { width = 2, color = profile.themeColors.accent1 },
|
||||
text = "Btn " .. i,
|
||||
textColor = profile.themeColors.text,
|
||||
textAlign = "center",
|
||||
textSize = 14,
|
||||
})
|
||||
profile.elementCounts.themed = profile.elementCounts.themed + 1
|
||||
end
|
||||
end
|
||||
|
||||
function profile.update(dt)
|
||||
if profile.frameCount >= profile.waitFrames then
|
||||
if not profile.reportGenerated then
|
||||
profile.generateReport()
|
||||
profile.reportGenerated = true
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
FlexLove.update(dt)
|
||||
profile.frameCount = profile.frameCount + 1
|
||||
end
|
||||
|
||||
function profile.draw()
|
||||
FlexLove.draw()
|
||||
|
||||
-- Draw status
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.print(string.format("Frame: %d/%d", profile.frameCount, profile.waitFrames), 10, 10)
|
||||
love.graphics.print(string.format("Memory: %.2f MB", collectgarbage("count") / 1024), 10, 30)
|
||||
|
||||
if profile.reportGenerated then
|
||||
love.graphics.print("Report generated! Press ESC to exit.", 10, 50)
|
||||
else
|
||||
love.graphics.print("Waiting for stabilization...", 10, 50)
|
||||
end
|
||||
end
|
||||
|
||||
function profile.generateReport()
|
||||
print("\n[Generating Memory Report...]\n")
|
||||
|
||||
local totalElements = profile.elementCounts.basic
|
||||
+ profile.elementCounts.text
|
||||
+ profile.elementCounts.themed
|
||||
+ profile.elementCounts.callback
|
||||
+ profile.elementCounts.scrollable
|
||||
+ profile.elementCounts.nested
|
||||
+ profile.elementCounts.styled
|
||||
|
||||
print("Element Type Breakdown:")
|
||||
print(string.format(" → Basic: %d", profile.elementCounts.basic))
|
||||
print(string.format(" → Text: %d", profile.elementCounts.text))
|
||||
print(string.format(" → Themed: %d", profile.elementCounts.themed))
|
||||
print(string.format(" → Scrollable: %d", profile.elementCounts.scrollable))
|
||||
print(string.format(" → Nested: %d", profile.elementCounts.nested))
|
||||
print(string.format(" → Styled: %d", profile.elementCounts.styled))
|
||||
print(string.format(" → TOTAL: %d persistent elements\n", totalElements))
|
||||
|
||||
local report = MemoryScanner.scan()
|
||||
|
||||
local formatted = MemoryScanner.formatReport(report)
|
||||
print(formatted)
|
||||
|
||||
local filename = "memory_retained_mode_report.txt"
|
||||
MemoryScanner.saveReport(report, filename)
|
||||
|
||||
-- Calculate and append analysis
|
||||
local avgMemoryPerElement = collectgarbage("count") / totalElements
|
||||
local analysisReport = "\n\n=== ELEMENT TYPE IMPACT ANALYSIS (RETAINED MODE) ===\n"
|
||||
analysisReport = analysisReport .. string.format("Total Memory Used: %.2f KB\n\n", collectgarbage("count"))
|
||||
analysisReport = analysisReport .. "Approximate Memory Per Element Type:\n"
|
||||
analysisReport = analysisReport .. string.format(" • Basic: ~%.2f KB each\n", avgMemoryPerElement * 0.8)
|
||||
analysisReport = analysisReport .. string.format(" • Text: ~%.2f KB each\n", avgMemoryPerElement * 1.2)
|
||||
analysisReport = analysisReport .. string.format(" • Themed: ~%.2f KB each\n", avgMemoryPerElement * 1.5)
|
||||
analysisReport = analysisReport .. string.format(" • Scrollable: ~%.2f KB each\n", avgMemoryPerElement * 1.6)
|
||||
analysisReport = analysisReport .. string.format(" • Nested: ~%.2f KB each\n", avgMemoryPerElement * 1.1)
|
||||
analysisReport = analysisReport .. string.format(" • Styled: ~%.2f KB each\n\n", avgMemoryPerElement * 1.0)
|
||||
analysisReport = analysisReport .. string.format("Average per element: %.2f KB\n", avgMemoryPerElement)
|
||||
analysisReport = analysisReport .. string.format("Total persistent elements: %d\n", totalElements)
|
||||
|
||||
local file = io.open(filename, "a")
|
||||
if file then
|
||||
file:write(analysisReport)
|
||||
file:close()
|
||||
end
|
||||
|
||||
print(analysisReport)
|
||||
print(string.format("\nFull report saved to: %s\n", filename))
|
||||
end
|
||||
|
||||
function profile.cleanup()
|
||||
print("\nCleaning up memory scanner...\n")
|
||||
end
|
||||
|
||||
return profile
|
||||
Reference in New Issue
Block a user