716 lines
22 KiB
Lua
716 lines
22 KiB
Lua
-- Settings Menu Mode Comparison Profile
|
|
-- Compares performance between explicit mode="retained" flags vs implicit retained mode
|
|
|
|
local FlexLove = require("FlexLove")
|
|
|
|
local profile = {
|
|
name = "Settings Menu Mode Comparison",
|
|
description = "Tests whether explicit mode='retained' has performance overhead",
|
|
testPhase = "warmup", -- warmup, implicit, explicit, complete
|
|
frameCount = 0,
|
|
framesPerPhase = 300, -- 5 seconds at 60 FPS
|
|
results = {
|
|
implicit = { startMem = 0, endMem = 0, avgFrameTime = 0, frameTimes = {} },
|
|
explicit = { startMem = 0, endMem = 0, avgFrameTime = 0, frameTimes = {} },
|
|
},
|
|
currentFrameStart = nil,
|
|
}
|
|
|
|
-- Mock Settings object
|
|
local Settings = {
|
|
values = {
|
|
resolution = { width = 1920, height = 1080 },
|
|
fullscreen = false,
|
|
vsync = true,
|
|
msaa = 4,
|
|
masterVolume = 0.8,
|
|
},
|
|
get = function(self, key)
|
|
return self.values[key]
|
|
end,
|
|
}
|
|
|
|
-- Simplified SettingsMenu implementation
|
|
local function createSettingsMenu(useExplicitMode)
|
|
local GuiZIndexing = { MainMenuOverlay = 100 }
|
|
|
|
-- Backdrop
|
|
local backdropProps = {
|
|
z = GuiZIndexing.MainMenuOverlay - 1,
|
|
width = "100%",
|
|
height = "100%",
|
|
backdropBlur = { radius = 10 },
|
|
backgroundColor = FlexLove.Color.new(1, 1, 1, 0.1),
|
|
}
|
|
if useExplicitMode then
|
|
backdropProps.mode = "retained"
|
|
end
|
|
local backdrop = FlexLove.new(backdropProps)
|
|
|
|
-- Main window
|
|
local windowProps = {
|
|
z = GuiZIndexing.MainMenuOverlay,
|
|
x = "5%",
|
|
y = "5%",
|
|
width = "90%",
|
|
height = "90%",
|
|
themeComponent = "framev3",
|
|
positioning = "flex",
|
|
flexDirection = "vertical",
|
|
justifySelf = "center",
|
|
justifyContent = "flex-start",
|
|
alignItems = "center",
|
|
scaleCorners = 3,
|
|
padding = { horizontal = "5%", vertical = "3%" },
|
|
gap = 10,
|
|
}
|
|
if useExplicitMode then
|
|
windowProps.mode = "retained"
|
|
end
|
|
local window = FlexLove.new(windowProps)
|
|
|
|
-- Close button
|
|
FlexLove.new({
|
|
parent = window,
|
|
x = "2%",
|
|
y = "2%",
|
|
alignSelf = "flex-start",
|
|
themeComponent = "buttonv2",
|
|
width = "4vw",
|
|
height = "4vw",
|
|
text = "X",
|
|
textSize = "2xl",
|
|
textAlign = "center",
|
|
})
|
|
|
|
-- Title
|
|
FlexLove.new({
|
|
parent = window,
|
|
text = "Settings",
|
|
textAlign = "center",
|
|
textSize = "3xl",
|
|
width = "100%",
|
|
margin = { top = "-4%", bottom = "4%" },
|
|
})
|
|
|
|
-- Content container
|
|
local content = FlexLove.new({
|
|
parent = window,
|
|
width = "100%",
|
|
height = "100%",
|
|
positioning = "flex",
|
|
flexDirection = "vertical",
|
|
padding = { top = "4%" },
|
|
})
|
|
|
|
-- Display Settings Section
|
|
FlexLove.new({
|
|
parent = content,
|
|
text = "Display Settings",
|
|
textAlign = "start",
|
|
textSize = "xl",
|
|
width = "100%",
|
|
textColor = FlexLove.Color.new(0.8, 0.9, 1, 1),
|
|
})
|
|
|
|
-- Resolution control
|
|
local row1 = FlexLove.new({
|
|
parent = content,
|
|
width = "100%",
|
|
height = "5vh",
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
justifyContent = "space-between",
|
|
alignItems = "center",
|
|
gap = 10,
|
|
})
|
|
|
|
FlexLove.new({
|
|
parent = row1,
|
|
text = "Resolution",
|
|
textAlign = "start",
|
|
textSize = "md",
|
|
width = "30%",
|
|
})
|
|
|
|
local resolution = Settings:get("resolution")
|
|
FlexLove.new({
|
|
parent = row1,
|
|
text = resolution.width .. " x " .. resolution.height,
|
|
themeComponent = "buttonv2",
|
|
width = "30%",
|
|
textAlign = "center",
|
|
textSize = "lg",
|
|
})
|
|
|
|
-- Fullscreen toggle
|
|
local row2 = FlexLove.new({
|
|
parent = content,
|
|
width = "100%",
|
|
height = "5vh",
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
justifyContent = "space-between",
|
|
alignItems = "center",
|
|
gap = 10,
|
|
})
|
|
|
|
FlexLove.new({
|
|
parent = row2,
|
|
text = "Fullscreen",
|
|
textAlign = "start",
|
|
textSize = "md",
|
|
width = "60%",
|
|
})
|
|
|
|
local fullscreen = Settings:get("fullscreen")
|
|
FlexLove.new({
|
|
parent = row2,
|
|
text = fullscreen and "ON" or "OFF",
|
|
themeComponent = fullscreen and "buttonv1" or "buttonv2",
|
|
textAlign = "center",
|
|
width = "15vw",
|
|
height = "4vh",
|
|
textSize = "md",
|
|
})
|
|
|
|
-- VSync toggle
|
|
local row3 = FlexLove.new({
|
|
parent = content,
|
|
width = "100%",
|
|
height = "5vh",
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
justifyContent = "space-between",
|
|
alignItems = "center",
|
|
gap = 10,
|
|
})
|
|
|
|
FlexLove.new({
|
|
parent = row3,
|
|
text = "VSync",
|
|
textAlign = "start",
|
|
textSize = "md",
|
|
width = "60%",
|
|
})
|
|
|
|
local vsync = Settings:get("vsync")
|
|
FlexLove.new({
|
|
parent = row3,
|
|
text = vsync and "ON" or "OFF",
|
|
themeComponent = vsync and "buttonv1" or "buttonv2",
|
|
textAlign = "center",
|
|
width = "15vw",
|
|
height = "4vh",
|
|
textSize = "md",
|
|
})
|
|
|
|
-- MSAA control
|
|
local row4 = FlexLove.new({
|
|
parent = content,
|
|
width = "100%",
|
|
height = "5vh",
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
justifyContent = "space-between",
|
|
alignItems = "center",
|
|
gap = 10,
|
|
})
|
|
|
|
FlexLove.new({
|
|
parent = row4,
|
|
text = "MSAA",
|
|
textAlign = "start",
|
|
textSize = "md",
|
|
width = "30%",
|
|
})
|
|
|
|
local buttonContainer = FlexLove.new({
|
|
parent = row4,
|
|
width = "60%",
|
|
height = "100%",
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
gap = 5,
|
|
})
|
|
|
|
local msaaValues = { 0, 1, 2, 4, 8, 16 }
|
|
for _, msaaVal in ipairs(msaaValues) do
|
|
local isSelected = Settings:get("msaa") == msaaVal
|
|
FlexLove.new({
|
|
parent = buttonContainer,
|
|
themeComponent = isSelected and "buttonv1" or "buttonv2",
|
|
text = tostring(msaaVal),
|
|
textAlign = "center",
|
|
width = "8vw",
|
|
height = "100%",
|
|
textSize = "sm",
|
|
disabled = isSelected,
|
|
opacity = isSelected and 0.7 or 1.0,
|
|
})
|
|
end
|
|
|
|
-- Audio Settings Section
|
|
FlexLove.new({
|
|
parent = content,
|
|
text = "Audio Settings",
|
|
textAlign = "start",
|
|
textSize = "xl",
|
|
width = "100%",
|
|
textColor = FlexLove.Color.new(0.8, 0.9, 1, 1),
|
|
})
|
|
|
|
-- Master volume slider
|
|
local row5 = FlexLove.new({
|
|
parent = content,
|
|
width = "100%",
|
|
height = "5vh",
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
justifyContent = "space-between",
|
|
alignItems = "center",
|
|
gap = 10,
|
|
})
|
|
|
|
FlexLove.new({
|
|
parent = row5,
|
|
text = "Master Volume",
|
|
textAlign = "start",
|
|
textSize = "md",
|
|
width = "30%",
|
|
})
|
|
|
|
local sliderContainer = FlexLove.new({
|
|
parent = row5,
|
|
width = "50%",
|
|
height = "100%",
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
alignItems = "center",
|
|
gap = 5,
|
|
})
|
|
|
|
local value = Settings:get("masterVolume")
|
|
local normalized = value
|
|
|
|
local sliderTrack = FlexLove.new({
|
|
parent = sliderContainer,
|
|
width = "80%",
|
|
height = "75%",
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
themeComponent = "framev3",
|
|
})
|
|
|
|
FlexLove.new({
|
|
parent = sliderTrack,
|
|
width = (normalized * 100) .. "%",
|
|
height = "100%",
|
|
themeComponent = "buttonv1",
|
|
themeStateLock = true,
|
|
})
|
|
|
|
FlexLove.new({
|
|
parent = sliderContainer,
|
|
text = string.format("%d", value * 100),
|
|
textAlign = "center",
|
|
textSize = "md",
|
|
width = "15%",
|
|
})
|
|
|
|
-- Meta controls (bottom buttons)
|
|
local metaContainer = FlexLove.new({
|
|
parent = window,
|
|
positioning = "absolute",
|
|
width = "100%",
|
|
height = "10%",
|
|
y = "90%",
|
|
x = "0%",
|
|
})
|
|
|
|
local buttonBar = FlexLove.new({
|
|
parent = metaContainer,
|
|
width = "100%",
|
|
positioning = "flex",
|
|
flexDirection = "horizontal",
|
|
justifyContent = "center",
|
|
alignItems = "center",
|
|
gap = 10,
|
|
})
|
|
|
|
FlexLove.new({
|
|
parent = buttonBar,
|
|
themeComponent = "buttonv2",
|
|
text = "Reset",
|
|
textAlign = "center",
|
|
width = "15vw",
|
|
height = "6vh",
|
|
textSize = "lg",
|
|
})
|
|
|
|
return { backdrop = backdrop, window = window }
|
|
end
|
|
|
|
function profile.init()
|
|
print("\n=== Settings Menu Mode Comparison Profile ===\n")
|
|
print("Testing whether explicit mode='retained' has performance overhead")
|
|
print("compared to implicit retained mode (global setting).\n")
|
|
|
|
FlexLove.init({
|
|
width = love.graphics.getWidth(),
|
|
height = love.graphics.getHeight(),
|
|
immediateMode = false, -- Global retained mode
|
|
theme = "space",
|
|
})
|
|
|
|
profile.testPhase = "warmup"
|
|
profile.frameCount = 0
|
|
|
|
print("Phase 1: Warmup (30 frames)...")
|
|
end
|
|
|
|
function profile.update(dt)
|
|
if profile.testPhase == "complete" then
|
|
return
|
|
end
|
|
|
|
-- Track frame time
|
|
local frameStart = love.timer.getTime()
|
|
|
|
if profile.testPhase == "warmup" then
|
|
-- Warmup phase - create menu a few times
|
|
createSettingsMenu(false)
|
|
profile.frameCount = profile.frameCount + 1
|
|
|
|
if profile.frameCount >= 30 then
|
|
print(" Warmup complete.\n")
|
|
print("Phase 2: Testing WITHOUT explicit mode flags (" .. profile.framesPerPhase .. " frames)...")
|
|
profile.testPhase = "implicit"
|
|
profile.frameCount = 0
|
|
collectgarbage("collect")
|
|
collectgarbage("collect")
|
|
profile.results.implicit.startMem = collectgarbage("count")
|
|
end
|
|
|
|
elseif profile.testPhase == "implicit" then
|
|
-- Test implicit mode (no explicit mode flags)
|
|
createSettingsMenu(false)
|
|
|
|
local frameTime = (love.timer.getTime() - frameStart) * 1000
|
|
table.insert(profile.results.implicit.frameTimes, frameTime)
|
|
|
|
profile.frameCount = profile.frameCount + 1
|
|
|
|
if profile.frameCount >= profile.framesPerPhase then
|
|
collectgarbage("collect")
|
|
collectgarbage("collect")
|
|
profile.results.implicit.endMem = collectgarbage("count")
|
|
|
|
-- Calculate average
|
|
local sum = 0
|
|
for _, ft in ipairs(profile.results.implicit.frameTimes) do
|
|
sum = sum + ft
|
|
end
|
|
profile.results.implicit.avgFrameTime = sum / #profile.results.implicit.frameTimes
|
|
|
|
print(" Complete. Avg frame time: " .. string.format("%.4f", profile.results.implicit.avgFrameTime) .. "ms\n")
|
|
print("Phase 3: Testing WITH explicit mode='retained' flags (" .. profile.framesPerPhase .. " frames)...")
|
|
|
|
profile.testPhase = "explicit"
|
|
profile.frameCount = 0
|
|
collectgarbage("collect")
|
|
collectgarbage("collect")
|
|
profile.results.explicit.startMem = collectgarbage("count")
|
|
end
|
|
|
|
elseif profile.testPhase == "explicit" then
|
|
-- Test explicit mode (with mode="retained" flags)
|
|
createSettingsMenu(true)
|
|
|
|
local frameTime = (love.timer.getTime() - frameStart) * 1000
|
|
table.insert(profile.results.explicit.frameTimes, frameTime)
|
|
|
|
profile.frameCount = profile.frameCount + 1
|
|
|
|
if profile.frameCount >= profile.framesPerPhase then
|
|
collectgarbage("collect")
|
|
collectgarbage("collect")
|
|
profile.results.explicit.endMem = collectgarbage("count")
|
|
|
|
-- Calculate average
|
|
local sum = 0
|
|
for _, ft in ipairs(profile.results.explicit.frameTimes) do
|
|
sum = sum + ft
|
|
end
|
|
profile.results.explicit.avgFrameTime = sum / #profile.results.explicit.frameTimes
|
|
|
|
print(" Complete. Avg frame time: " .. string.format("%.4f", profile.results.explicit.avgFrameTime) .. "ms\n")
|
|
|
|
profile.testPhase = "complete"
|
|
profile.generateReport()
|
|
end
|
|
end
|
|
end
|
|
|
|
function profile.draw()
|
|
-- Draw the current menu
|
|
if profile.testPhase ~= "complete" then
|
|
FlexLove.draw()
|
|
end
|
|
|
|
-- Draw status overlay
|
|
love.graphics.setColor(0, 0, 0, 0.85)
|
|
love.graphics.rectangle("fill", 10, 10, 400, 120)
|
|
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
love.graphics.print("Settings Menu Mode Comparison", 20, 20)
|
|
|
|
if profile.testPhase == "warmup" then
|
|
love.graphics.print("Phase: Warmup (" .. profile.frameCount .. "/30)", 20, 45)
|
|
elseif profile.testPhase == "implicit" then
|
|
love.graphics.print("Phase: Without mode flags", 20, 45)
|
|
love.graphics.print("Progress: " .. profile.frameCount .. "/" .. profile.framesPerPhase, 20, 65)
|
|
elseif profile.testPhase == "explicit" then
|
|
love.graphics.print("Phase: With mode='retained' flags", 20, 45)
|
|
love.graphics.print("Progress: " .. profile.frameCount .. "/" .. profile.framesPerPhase, 20, 65)
|
|
elseif profile.testPhase == "complete" then
|
|
love.graphics.print("Phase: COMPLETE", 20, 45)
|
|
love.graphics.print("Report saved! Press S to save again, ESC to exit.", 20, 65)
|
|
end
|
|
|
|
love.graphics.print("Memory: " .. string.format("%.2f", collectgarbage("count") / 1024) .. " MB", 20, 85)
|
|
love.graphics.print("Press ESC to return to menu", 20, 105)
|
|
end
|
|
|
|
function profile.generateReport()
|
|
print("\n" .. string.rep("=", 80))
|
|
print("RESULTS COMPARISON")
|
|
print(string.rep("=", 80) .. "\n")
|
|
|
|
local timeDiff = profile.results.explicit.avgFrameTime - profile.results.implicit.avgFrameTime
|
|
local timePercent = (timeDiff / profile.results.implicit.avgFrameTime) * 100
|
|
local memDiff = (profile.results.explicit.endMem - profile.results.explicit.startMem) -
|
|
(profile.results.implicit.endMem - profile.results.implicit.startMem)
|
|
|
|
print("Time Comparison:")
|
|
print(string.format(" Without mode flag: %.4f ms", profile.results.implicit.avgFrameTime))
|
|
print(string.format(" With mode flag: %.4f ms", profile.results.explicit.avgFrameTime))
|
|
print(string.format(" Difference: %.4f ms (%+.2f%%)", timeDiff, timePercent))
|
|
print()
|
|
|
|
print("Memory Comparison:")
|
|
print(string.format(" Without mode flag: %.2f KB", profile.results.implicit.endMem - profile.results.implicit.startMem))
|
|
print(string.format(" With mode flag: %.2f KB", profile.results.explicit.endMem - profile.results.explicit.startMem))
|
|
print(string.format(" Difference: %+.2f KB", memDiff))
|
|
print()
|
|
|
|
print("INTERPRETATION:")
|
|
print()
|
|
if math.abs(timePercent) < 5 then
|
|
print(" ✓ Performance is essentially identical (< 5% difference)")
|
|
print(" The explicit mode flag has negligible impact on performance.")
|
|
elseif timePercent > 0 then
|
|
print(string.format(" ⚠ Explicit mode flag is %.2f%% SLOWER", timePercent))
|
|
print(" This indicates overhead from mode checking/resolution.")
|
|
else
|
|
print(string.format(" ✓ Explicit mode flag is %.2f%% FASTER", -timePercent))
|
|
print(" This indicates potential optimization benefits.")
|
|
end
|
|
print()
|
|
|
|
if math.abs(memDiff) < 50 then
|
|
print(" ✓ Memory usage is essentially identical (< 50 KB difference)")
|
|
elseif memDiff > 0 then
|
|
print(string.format(" ⚠ Explicit mode flag uses %.2f KB MORE memory", memDiff))
|
|
else
|
|
print(string.format(" ✓ Explicit mode flag uses %.2f KB LESS memory", -memDiff))
|
|
end
|
|
print()
|
|
|
|
print("RECOMMENDATION:")
|
|
print()
|
|
if math.abs(timePercent) < 5 and math.abs(memDiff) < 50 then
|
|
print(" The explicit mode='retained' flag provides clarity and explicitness")
|
|
print(" without any meaningful performance cost. It's recommended for:")
|
|
print(" - Code readability (makes intent explicit)")
|
|
print(" - Future-proofing (if global mode changes)")
|
|
print(" - Mixed-mode UIs (where some elements are immediate)")
|
|
else
|
|
print(" Consider the trade-offs based on your specific use case.")
|
|
end
|
|
print()
|
|
print(string.rep("=", 80))
|
|
print("Profile complete! Press S to save report.")
|
|
print(string.rep("=", 80) .. "\n")
|
|
|
|
-- Save report automatically
|
|
profile.saveReportToFile()
|
|
end
|
|
|
|
function profile.saveReportToFile()
|
|
local timestamp = os.date("%Y-%m-%d_%H-%M-%S")
|
|
local filename = string.format("reports/settings_menu_mode_profile/%s.md", timestamp)
|
|
|
|
-- Get the actual project directory
|
|
local sourceDir = love.filesystem.getSource()
|
|
local filepath
|
|
|
|
if sourceDir:match("%.love$") then
|
|
-- Running from .love file, use save directory
|
|
love.filesystem.createDirectory("reports/settings_menu_mode_profile")
|
|
-- Use love.filesystem for sandboxed writes
|
|
local content = profile.formatReportMarkdown()
|
|
local success = love.filesystem.write(filename, content)
|
|
if success then
|
|
print("\n✓ Report saved to: " .. love.filesystem.getSaveDirectory() .. "/" .. filename)
|
|
else
|
|
print("\n✗ Failed to save report")
|
|
end
|
|
else
|
|
-- Running from source, use io module
|
|
filepath = sourceDir .. "/" .. filename
|
|
os.execute('mkdir -p "' .. sourceDir .. '/reports/settings_menu_mode_profile"')
|
|
|
|
local file, err = io.open(filepath, "w")
|
|
if file then
|
|
file:write(profile.formatReportMarkdown())
|
|
file:close()
|
|
print("\n✓ Report saved to: " .. filepath)
|
|
|
|
-- Also save as latest.md
|
|
local latestPath = sourceDir .. "/reports/settings_menu_mode_profile/latest.md"
|
|
local latestFile = io.open(latestPath, "w")
|
|
if latestFile then
|
|
latestFile:write(profile.formatReportMarkdown())
|
|
latestFile:close()
|
|
end
|
|
else
|
|
print("\n✗ Failed to save report: " .. tostring(err))
|
|
end
|
|
end
|
|
end
|
|
|
|
function profile.formatReportMarkdown()
|
|
local lines = {}
|
|
|
|
table.insert(lines, "# Settings Menu Mode Comparison Report")
|
|
table.insert(lines, "")
|
|
table.insert(lines, "**Generated:** " .. os.date("%Y-%m-%d %H:%M:%S"))
|
|
table.insert(lines, "")
|
|
table.insert(lines, "This profile compares performance when creating a complex settings menu")
|
|
table.insert(lines, "with explicit `mode='retained'` flags vs. implicit retained mode (global setting).")
|
|
table.insert(lines, "")
|
|
table.insert(lines, "---")
|
|
table.insert(lines, "")
|
|
|
|
table.insert(lines, "## Test Configuration")
|
|
table.insert(lines, "")
|
|
table.insert(lines, "- **Frames per test:** " .. profile.framesPerPhase)
|
|
table.insert(lines, "- **Elements per menu:** ~45 (backdrop, window, buttons, sliders, etc.)")
|
|
table.insert(lines, "- **Global mode:** `immediateMode = false` (retained)")
|
|
table.insert(lines, "")
|
|
|
|
table.insert(lines, "## Results")
|
|
table.insert(lines, "")
|
|
|
|
local timeDiff = profile.results.explicit.avgFrameTime - profile.results.implicit.avgFrameTime
|
|
local timePercent = (timeDiff / profile.results.implicit.avgFrameTime) * 100
|
|
local memDiff = (profile.results.explicit.endMem - profile.results.explicit.startMem) -
|
|
(profile.results.implicit.endMem - profile.results.implicit.startMem)
|
|
|
|
table.insert(lines, "### Frame Time Comparison")
|
|
table.insert(lines, "")
|
|
table.insert(lines, "| Metric | Without `mode` flag | With `mode='retained'` flag | Difference |")
|
|
table.insert(lines, "|--------|--------------------:|----------------------------:|-----------:|")
|
|
table.insert(lines, string.format("| Average Frame Time | %.4f ms | %.4f ms | %+.4f ms (%+.2f%%) |",
|
|
profile.results.implicit.avgFrameTime,
|
|
profile.results.explicit.avgFrameTime,
|
|
timeDiff,
|
|
timePercent))
|
|
table.insert(lines, "")
|
|
|
|
table.insert(lines, "### Memory Comparison")
|
|
table.insert(lines, "")
|
|
table.insert(lines, "| Metric | Without `mode` flag | With `mode='retained'` flag | Difference |")
|
|
table.insert(lines, "|--------|--------------------:|----------------------------:|-----------:|")
|
|
table.insert(lines, string.format("| Memory Used | %.2f KB | %.2f KB | %+.2f KB |",
|
|
profile.results.implicit.endMem - profile.results.implicit.startMem,
|
|
profile.results.explicit.endMem - profile.results.explicit.startMem,
|
|
memDiff))
|
|
table.insert(lines, "")
|
|
|
|
table.insert(lines, "## Interpretation")
|
|
table.insert(lines, "")
|
|
|
|
if math.abs(timePercent) < 5 then
|
|
table.insert(lines, "✓ **Performance is essentially identical** (< 5% difference)")
|
|
table.insert(lines, "")
|
|
table.insert(lines, "The explicit `mode='retained'` flag has negligible impact on performance.")
|
|
elseif timePercent > 0 then
|
|
table.insert(lines, string.format("⚠ **Explicit mode flag is %.2f%% SLOWER**", timePercent))
|
|
table.insert(lines, "")
|
|
table.insert(lines, "This indicates overhead from mode checking/resolution.")
|
|
else
|
|
table.insert(lines, string.format("✓ **Explicit mode flag is %.2f%% FASTER**", -timePercent))
|
|
table.insert(lines, "")
|
|
table.insert(lines, "This indicates potential optimization benefits.")
|
|
end
|
|
table.insert(lines, "")
|
|
|
|
if math.abs(memDiff) < 50 then
|
|
table.insert(lines, "✓ **Memory usage is essentially identical** (< 50 KB difference)")
|
|
elseif memDiff > 0 then
|
|
table.insert(lines, string.format("⚠ **Explicit mode flag uses %.2f KB MORE memory**", memDiff))
|
|
else
|
|
table.insert(lines, string.format("✓ **Explicit mode flag uses %.2f KB LESS memory**", -memDiff))
|
|
end
|
|
table.insert(lines, "")
|
|
|
|
table.insert(lines, "## Recommendation")
|
|
table.insert(lines, "")
|
|
|
|
if math.abs(timePercent) < 5 and math.abs(memDiff) < 50 then
|
|
table.insert(lines, "The explicit `mode='retained'` flag provides clarity and explicitness")
|
|
table.insert(lines, "without any meaningful performance cost. It's recommended for:")
|
|
table.insert(lines, "")
|
|
table.insert(lines, "- **Code readability** - Makes intent explicit")
|
|
table.insert(lines, "- **Future-proofing** - If global mode changes")
|
|
table.insert(lines, "- **Mixed-mode UIs** - Where some elements are immediate")
|
|
else
|
|
table.insert(lines, "Consider the trade-offs based on your specific use case.")
|
|
end
|
|
table.insert(lines, "")
|
|
|
|
table.insert(lines, "---")
|
|
table.insert(lines, "")
|
|
table.insert(lines, "*Report generated by FlexLöve Performance Profiler*")
|
|
|
|
return table.concat(lines, "\n")
|
|
end
|
|
|
|
function profile.keypressed(key, profiler)
|
|
if key == "s" and profile.testPhase == "complete" then
|
|
profile.saveReportToFile()
|
|
end
|
|
end
|
|
|
|
function profile.resize(w, h)
|
|
FlexLove.resize(w, h)
|
|
end
|
|
|
|
function profile.reset()
|
|
profile.testPhase = "warmup"
|
|
profile.frameCount = 0
|
|
profile.results = {
|
|
implicit = { startMem = 0, endMem = 0, avgFrameTime = 0, frameTimes = {} },
|
|
explicit = { startMem = 0, endMem = 0, avgFrameTime = 0, frameTimes = {} },
|
|
}
|
|
print("\nProfile reset. Starting over...\n")
|
|
end
|
|
|
|
function profile.cleanup()
|
|
print("\nCleaning up settings menu mode profile...\n")
|
|
end
|
|
|
|
return profile
|