168 lines
5.8 KiB
Lua
168 lines
5.8 KiB
Lua
#!/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))
|