memory tooling, state handling changes
This commit is contained in:
167
scripts/analyze-memory-baseline.lua
Normal file
167
scripts/analyze-memory-baseline.lua
Normal file
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env lua
|
||||
-- Memory Baseline Analysis
|
||||
-- Analyzes base memory usage and per-element costs
|
||||
|
||||
-- Add libs directory to package path
|
||||
package.path = package.path .. ";./?.lua;./?/init.lua"
|
||||
|
||||
-- Mock LÖVE
|
||||
_G.love = {
|
||||
graphics = {
|
||||
newCanvas = function() return {} end,
|
||||
newImage = function() return {} end,
|
||||
setCanvas = function() end,
|
||||
clear = function() end,
|
||||
setColor = function() end,
|
||||
draw = function() end,
|
||||
rectangle = function() end,
|
||||
print = function() end,
|
||||
getDimensions = function() return 800, 600 end,
|
||||
getColor = function() return 1, 1, 1, 1 end,
|
||||
setBlendMode = function() end,
|
||||
setScissor = function() end,
|
||||
getScissor = function() return nil end,
|
||||
push = function() end,
|
||||
pop = function() end,
|
||||
translate = function() end,
|
||||
rotate = function() end,
|
||||
scale = function() end,
|
||||
newFont = function() return {} end,
|
||||
setFont = function() end,
|
||||
getFont = function() return { getHeight = function() return 12 end } end,
|
||||
},
|
||||
window = { getMode = function() return 800, 600 end },
|
||||
timer = { getTime = function() return os.clock() end },
|
||||
image = { newImageData = function() return {} end },
|
||||
mouse = { getPosition = function() return 0, 0 end },
|
||||
}
|
||||
|
||||
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")
|
||||
|
||||
print("=== Memory Baseline Analysis ===")
|
||||
print("")
|
||||
|
||||
-- Baseline: Just FlexLove loaded
|
||||
collectgarbage("collect")
|
||||
collectgarbage("collect")
|
||||
local baseline = collectgarbage("count") / 1024
|
||||
print(string.format("1. FlexLove loaded (no init): %.2f MB", baseline))
|
||||
|
||||
-- Initialize FlexLove
|
||||
FlexLove.init({ immediateMode = true })
|
||||
collectgarbage("collect")
|
||||
collectgarbage("collect")
|
||||
local afterInit = collectgarbage("count") / 1024
|
||||
print(string.format("2. After init(): %.2f MB (+%.2f MB)", afterInit, afterInit - baseline))
|
||||
|
||||
-- Create 1 simple element
|
||||
FlexLove.beginFrame()
|
||||
FlexLove.new({ id = "test1", width = 100, height = 100 })
|
||||
FlexLove.endFrame()
|
||||
collectgarbage("collect")
|
||||
collectgarbage("collect")
|
||||
local after1Element = collectgarbage("count") / 1024
|
||||
print(string.format("3. After 1 element: %.2f MB (+%.2f KB)", after1Element, (after1Element - afterInit) * 1024))
|
||||
|
||||
-- Create 10 more elements (total 11)
|
||||
FlexLove.beginFrame()
|
||||
for i = 1, 10 do
|
||||
FlexLove.new({ id = "elem" .. i, width = 100, height = 100 })
|
||||
end
|
||||
FlexLove.endFrame()
|
||||
collectgarbage("collect")
|
||||
collectgarbage("collect")
|
||||
local after10Elements = collectgarbage("count") / 1024
|
||||
print(string.format("4. After 10 more elements: %.2f MB (+%.2f KB)", after10Elements, (after10Elements - after1Element) * 1024))
|
||||
print(string.format(" Per element: ~%.2f KB", (after10Elements - after1Element) * 1024 / 10))
|
||||
|
||||
-- Create 100 more elements
|
||||
FlexLove.beginFrame()
|
||||
for i = 1, 100 do
|
||||
FlexLove.new({ id = "bulk" .. i, width = 100, height = 100 })
|
||||
end
|
||||
FlexLove.endFrame()
|
||||
collectgarbage("collect")
|
||||
collectgarbage("collect")
|
||||
local after100Elements = collectgarbage("count") / 1024
|
||||
print(string.format("5. After 100 more elements: %.2f MB (+%.2f KB)", after100Elements, (after100Elements - after10Elements) * 1024))
|
||||
print(string.format(" Per element: ~%.2f KB", (after100Elements - after10Elements) * 1024 / 100))
|
||||
|
||||
print("")
|
||||
print("=== Memory Breakdown ===")
|
||||
|
||||
-- Initialize scanner
|
||||
MemoryScanner.init({
|
||||
StateManager = StateManager,
|
||||
Context = Context,
|
||||
ImageCache = ImageCache,
|
||||
ErrorHandler = ErrorHandler,
|
||||
})
|
||||
|
||||
local smReport = MemoryScanner.scanStateManager()
|
||||
print(string.format("StateManager: %d states, %.2f KB total", smReport.stateCount, smReport.stateStoreSize / 1024))
|
||||
if smReport.stateCount > 0 then
|
||||
print(string.format(" Per state: ~%.2f KB", smReport.stateStoreSize / smReport.stateCount / 1024))
|
||||
end
|
||||
print(string.format(" Metadata: %.2f KB", smReport.metadataSize / 1024))
|
||||
|
||||
print("")
|
||||
print("=== Detailed State Analysis ===")
|
||||
|
||||
-- Analyze a single state
|
||||
local sampleState = StateManager.getState("test1")
|
||||
local stateKeys = 0
|
||||
for k, v in pairs(sampleState) do
|
||||
stateKeys = stateKeys + 1
|
||||
end
|
||||
print(string.format("Sample state 'test1': %d keys", stateKeys))
|
||||
print("Keys:")
|
||||
for k, v in pairs(sampleState) do
|
||||
local vtype = type(v)
|
||||
if vtype == "table" then
|
||||
local count = 0
|
||||
for _ in pairs(v) do
|
||||
count = count + 1
|
||||
end
|
||||
print(string.format(" %s: table (%d items)", k, count))
|
||||
else
|
||||
print(string.format(" %s: %s = %s", k, vtype, tostring(v)))
|
||||
end
|
||||
end
|
||||
|
||||
print("")
|
||||
print("=== Optimization Targets ===")
|
||||
print("")
|
||||
|
||||
-- Calculate potential savings
|
||||
local stateOverhead = smReport.stateStoreSize / smReport.stateCount
|
||||
print(string.format("1. StateManager per-state overhead: %.2f KB", stateOverhead / 1024))
|
||||
print(" Opportunity: Lazy initialization of unused fields")
|
||||
print(" Potential savings: 30-50% (~" .. string.format("%.2f", stateOverhead * 0.4 / 1024) .. " KB per state)")
|
||||
print("")
|
||||
|
||||
print("2. Element instance size: ~" .. string.format("%.2f", (after10Elements - after1Element) * 1024 / 10) .. " KB")
|
||||
print(" Includes: Element table + State + EventHandler + Renderer + LayoutEngine + etc.")
|
||||
print(" Opportunity: Lazy module initialization, shared instances")
|
||||
print(" Potential savings: 20-30%")
|
||||
print("")
|
||||
|
||||
print("3. Module instances per element:")
|
||||
print(" - EventHandler (always created)")
|
||||
print(" - Renderer (always created)")
|
||||
print(" - LayoutEngine (always created)")
|
||||
print(" - ThemeManager (always created)")
|
||||
print(" - ScrollManager (conditional)")
|
||||
print(" - TextEditor (conditional)")
|
||||
print(" Opportunity: Share non-stateful modules, lazy init conditional ones")
|
||||
print("")
|
||||
|
||||
local totalMemory = after100Elements
|
||||
print(string.format("Total memory with 111 elements: %.2f MB", totalMemory))
|
||||
print(string.format("Potential savings with optimizations: %.2f - %.2f MB (30-50%%)",
|
||||
totalMemory * 0.3, totalMemory * 0.5))
|
||||
Reference in New Issue
Block a user