starting mode escape hatch
This commit is contained in:
507
profiling/__profiles__/settings_menu_mode_profile.lua
Normal file
507
profiling/__profiles__/settings_menu_mode_profile.lua
Normal file
@@ -0,0 +1,507 @@
|
||||
-- Profiling test comparing retained mode flag vs. default behavior in complex UI
|
||||
-- This simulates creating a settings menu multiple times per frame to stress test
|
||||
-- the performance difference between explicit mode="retained" and implicit retained mode
|
||||
|
||||
package.path = package.path .. ";../../?.lua;../../modules/?.lua"
|
||||
|
||||
local FlexLove = require("FlexLove")
|
||||
local Color = require("modules.Color")
|
||||
|
||||
-- Mock resolution sets (simplified)
|
||||
local resolution_sets = {
|
||||
["16:9"] = {
|
||||
{ 1920, 1080 },
|
||||
{ 1600, 900 },
|
||||
{ 1280, 720 },
|
||||
},
|
||||
["16:10"] = {
|
||||
{ 1920, 1200 },
|
||||
{ 1680, 1050 },
|
||||
{ 1280, 800 },
|
||||
},
|
||||
}
|
||||
|
||||
-- Mock Settings object
|
||||
local Settings = {
|
||||
values = {
|
||||
resolution = { width = 1920, height = 1080 },
|
||||
fullscreen = false,
|
||||
vsync = true,
|
||||
msaa = 4,
|
||||
resizable = true,
|
||||
borderless = false,
|
||||
masterVolume = 0.8,
|
||||
musicVolume = 0.7,
|
||||
sfxVolume = 0.9,
|
||||
crtEffectStrength = 0.3,
|
||||
},
|
||||
get = function(self, key)
|
||||
return self.values[key]
|
||||
end,
|
||||
set = function(self, key, value)
|
||||
self.values[key] = value
|
||||
end,
|
||||
reset_to_defaults = function(self) end,
|
||||
apply = function(self) end,
|
||||
}
|
||||
|
||||
-- Helper function to round numbers
|
||||
local function round(num, decimals)
|
||||
local mult = 10 ^ (decimals or 0)
|
||||
return math.floor(num * mult + 0.5) / mult
|
||||
end
|
||||
|
||||
-- Simplified SettingsMenu implementation
|
||||
local function create_settings_menu_with_mode_flag(use_mode_flag)
|
||||
local GuiZIndexing = { MainMenuOverlay = 100 }
|
||||
|
||||
-- Backdrop
|
||||
local backdrop_props = {
|
||||
z = GuiZIndexing.MainMenuOverlay - 1,
|
||||
width = "100%",
|
||||
height = "100%",
|
||||
backdropBlur = { radius = 10 },
|
||||
backgroundColor = Color.new(1, 1, 1, 0.1),
|
||||
}
|
||||
if use_mode_flag then
|
||||
backdrop_props.mode = "retained"
|
||||
end
|
||||
local backdrop = FlexLove.new(backdrop_props)
|
||||
|
||||
-- Main window
|
||||
local window_props = {
|
||||
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 use_mode_flag then
|
||||
window_props.mode = "retained"
|
||||
end
|
||||
local window = FlexLove.new(window_props)
|
||||
|
||||
-- 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 = 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 button_container = FlexLove.new({
|
||||
parent = row4,
|
||||
width = "60%",
|
||||
height = "100%",
|
||||
positioning = "flex",
|
||||
flexDirection = "horizontal",
|
||||
gap = 5,
|
||||
})
|
||||
|
||||
local msaa_values = { 0, 1, 2, 4, 8, 16 }
|
||||
for _, msaa_val in ipairs(msaa_values) do
|
||||
local is_selected = Settings:get("msaa") == msaa_val
|
||||
FlexLove.new({
|
||||
parent = button_container,
|
||||
themeComponent = is_selected and "buttonv1" or "buttonv2",
|
||||
text = tostring(msaa_val),
|
||||
textAlign = "center",
|
||||
width = "8vw",
|
||||
height = "100%",
|
||||
textSize = "sm",
|
||||
disabled = is_selected,
|
||||
opacity = is_selected and 0.7 or 1.0,
|
||||
})
|
||||
end
|
||||
|
||||
-- Audio Settings Section
|
||||
FlexLove.new({
|
||||
parent = content,
|
||||
text = "Audio Settings",
|
||||
textAlign = "start",
|
||||
textSize = "xl",
|
||||
width = "100%",
|
||||
textColor = 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 slider_container = 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 slider_track = FlexLove.new({
|
||||
parent = slider_container,
|
||||
width = "80%",
|
||||
height = "75%",
|
||||
positioning = "flex",
|
||||
flexDirection = "horizontal",
|
||||
themeComponent = "framev3",
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = slider_track,
|
||||
width = (normalized * 100) .. "%",
|
||||
height = "100%",
|
||||
themeComponent = "buttonv1",
|
||||
themeStateLock = true,
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = slider_container,
|
||||
text = string.format("%d", value * 100),
|
||||
textAlign = "center",
|
||||
textSize = "md",
|
||||
width = "15%",
|
||||
})
|
||||
|
||||
-- Meta controls (bottom buttons)
|
||||
local meta_container = FlexLove.new({
|
||||
parent = window,
|
||||
positioning = "absolute",
|
||||
width = "100%",
|
||||
height = "10%",
|
||||
y = "90%",
|
||||
x = "0%",
|
||||
})
|
||||
|
||||
local button_bar = FlexLove.new({
|
||||
parent = meta_container,
|
||||
width = "100%",
|
||||
positioning = "flex",
|
||||
flexDirection = "horizontal",
|
||||
justifyContent = "center",
|
||||
alignItems = "center",
|
||||
gap = 10,
|
||||
})
|
||||
|
||||
FlexLove.new({
|
||||
parent = button_bar,
|
||||
themeComponent = "buttonv2",
|
||||
text = "Reset",
|
||||
textAlign = "center",
|
||||
width = "15vw",
|
||||
height = "6vh",
|
||||
textSize = "lg",
|
||||
})
|
||||
|
||||
return { backdrop = backdrop, window = window }
|
||||
end
|
||||
|
||||
-- Profile configuration
|
||||
local PROFILE_NAME = "Settings Menu Mode Comparison"
|
||||
local ITERATIONS_PER_TEST = 100 -- Create the menu 100 times to measure difference
|
||||
|
||||
print("=" .. string.rep("=", 78))
|
||||
print(string.format(" %s", PROFILE_NAME))
|
||||
print("=" .. string.rep("=", 78))
|
||||
print()
|
||||
print("This profile compares performance when creating a complex settings menu")
|
||||
print("with explicit mode='retained' flags vs. implicit retained mode (global).")
|
||||
print()
|
||||
print(string.format("Test configuration:"))
|
||||
print(string.format(" - Iterations: %d menu creations per test", ITERATIONS_PER_TEST))
|
||||
print(string.format(" - Elements per menu: ~45 (backdrop, window, buttons, sliders, etc.)"))
|
||||
print(string.format(" - Total elements created: ~%d per test", ITERATIONS_PER_TEST * 45))
|
||||
print()
|
||||
|
||||
-- Warm up
|
||||
print("Warming up...")
|
||||
FlexLove.init({ immediateMode = false, theme = "space" })
|
||||
for i = 1, 10 do
|
||||
create_settings_menu_with_mode_flag(false)
|
||||
end
|
||||
collectgarbage("collect")
|
||||
|
||||
-- Test 1: Without explicit mode flags (implicit retained via global setting)
|
||||
print("Running Test 1: Without explicit mode='retained' flags...")
|
||||
FlexLove.init({ immediateMode = false, theme = "space" })
|
||||
collectgarbage("collect")
|
||||
local mem_before_implicit = collectgarbage("count")
|
||||
local time_before_implicit = os.clock()
|
||||
|
||||
for i = 1, ITERATIONS_PER_TEST do
|
||||
local menu = create_settings_menu_with_mode_flag(false)
|
||||
end
|
||||
|
||||
local time_after_implicit = os.clock()
|
||||
collectgarbage("collect")
|
||||
local mem_after_implicit = collectgarbage("count")
|
||||
|
||||
local time_implicit = time_after_implicit - time_before_implicit
|
||||
local mem_implicit = mem_after_implicit - mem_before_implicit
|
||||
|
||||
print(string.format(" Time: %.4f seconds", time_implicit))
|
||||
print(string.format(" Memory: %.2f KB", mem_implicit))
|
||||
print(string.format(" Avg time per menu: %.4f ms", (time_implicit / ITERATIONS_PER_TEST) * 1000))
|
||||
print()
|
||||
|
||||
-- Test 2: With explicit mode="retained" flags
|
||||
print("Running Test 2: With explicit mode='retained' flags...")
|
||||
FlexLove.init({ immediateMode = false, theme = "space" })
|
||||
collectgarbage("collect")
|
||||
local mem_before_explicit = collectgarbage("count")
|
||||
local time_before_explicit = os.clock()
|
||||
|
||||
for i = 1, ITERATIONS_PER_TEST do
|
||||
local menu = create_settings_menu_with_mode_flag(true)
|
||||
end
|
||||
|
||||
local time_after_explicit = os.clock()
|
||||
collectgarbage("collect")
|
||||
local mem_after_explicit = collectgarbage("count")
|
||||
|
||||
local time_explicit = time_after_explicit - time_before_explicit
|
||||
local mem_explicit = mem_after_explicit - mem_before_explicit
|
||||
|
||||
print(string.format(" Time: %.4f seconds", time_explicit))
|
||||
print(string.format(" Memory: %.2f KB", mem_explicit))
|
||||
print(string.format(" Avg time per menu: %.4f ms", (time_explicit / ITERATIONS_PER_TEST) * 1000))
|
||||
print()
|
||||
|
||||
-- Calculate differences
|
||||
print("=" .. string.rep("=", 78))
|
||||
print("RESULTS COMPARISON")
|
||||
print("=" .. string.rep("=", 78))
|
||||
print()
|
||||
|
||||
local time_diff = time_explicit - time_implicit
|
||||
local time_percent = (time_diff / time_implicit) * 100
|
||||
local mem_diff = mem_explicit - mem_implicit
|
||||
|
||||
print(string.format("Time Difference:"))
|
||||
print(string.format(" Without mode flag: %.4f seconds", time_implicit))
|
||||
print(string.format(" With mode flag: %.4f seconds", time_explicit))
|
||||
print(string.format(" Difference: %.4f seconds (%+.2f%%)", time_diff, time_percent))
|
||||
print()
|
||||
|
||||
print(string.format("Memory Difference:"))
|
||||
print(string.format(" Without mode flag: %.2f KB", mem_implicit))
|
||||
print(string.format(" With mode flag: %.2f KB", mem_explicit))
|
||||
print(string.format(" Difference: %+.2f KB", mem_diff))
|
||||
print()
|
||||
|
||||
-- Interpretation
|
||||
print("INTERPRETATION:")
|
||||
print()
|
||||
if math.abs(time_percent) < 5 then
|
||||
print(" ✓ Performance is essentially identical (< 5% difference)")
|
||||
print(" The explicit mode flag has negligible impact on performance.")
|
||||
elseif time_percent > 0 then
|
||||
print(string.format(" ⚠ Explicit mode flag is %.2f%% SLOWER", time_percent))
|
||||
print(" This indicates overhead from mode checking/resolution.")
|
||||
else
|
||||
print(string.format(" ✓ Explicit mode flag is %.2f%% FASTER", -time_percent))
|
||||
print(" This indicates potential optimization benefits.")
|
||||
end
|
||||
print()
|
||||
|
||||
if math.abs(mem_diff) < 50 then
|
||||
print(" ✓ Memory usage is essentially identical (< 50 KB difference)")
|
||||
elseif mem_diff > 0 then
|
||||
print(string.format(" ⚠ Explicit mode flag uses %.2f KB MORE memory", mem_diff))
|
||||
else
|
||||
print(string.format(" ✓ Explicit mode flag uses %.2f KB LESS memory", -mem_diff))
|
||||
end
|
||||
print()
|
||||
|
||||
print("RECOMMENDATION:")
|
||||
print()
|
||||
if math.abs(time_percent) < 5 and math.abs(mem_diff) < 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("=", 78))
|
||||
print("Profile complete!")
|
||||
print("=" .. string.rep("=", 78))
|
||||
Reference in New Issue
Block a user