Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions release-notes/dashboard-renderkey-concat.build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- **Urban, Grid and Deck build their render key without a temporary list (`widgets/dashboard/themes/urban/layout.lua`, `widgets/dashboard/themes/grid/layout.lua`, `widgets/dashboard/themes/deck/layout.lua`)**:
- `L.renderKey` runs every 0.5 s in the host's state pass and joined its terms with `table.concat({ ... }, "|")`, although its comment said no table was allocated. The key is now one `..` expression with the same terms, order and separator, so the list is no longer built: a call allocates 200 bytes less in Urban and Grid and 216 bytes less in Deck. Measured on desktop Lua 5.3 with unchanged inputs and the suite logo's path in the key (a model picture's path is always in it), Urban allocates 119 bytes per call instead of 319; what is left is the key string itself. The key is byte-identical for every input, and the comment now says what the function still allocates.
31 changes: 16 additions & 15 deletions src/rfsuite/widgets/dashboard/themes/deck/layout.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2394,21 +2394,23 @@ end
-- word under the model picture is coloured at build time, so without the term the warn colour would never
-- clear. The picked pack is not a term: nothing drawn depends on it.
--
-- This runs every 0.5 s inside the host's STATE pass: one sensor read, no table allocation,
-- no probe of the card or the settings. What a build reads beyond this (the radio's battery
-- range, the image on the card) is read at build time and is not a term.
-- This runs every 0.5 s inside the host's STATE pass: one sensor read, no probe of the card or
-- the settings. The key is one `..` expression, so no list is built to be joined. What a call
-- still allocates is the key itself: Lua 5.3 makes a new string for every key over 40 bytes,
-- and the model picture's path (the suite logo's when there is no picture) puts it over. What a
-- build reads beyond this (the radio's battery range, the image on the card) is read at build
-- time and is not a term.
function L.renderKey(zone, state)
local derived = state and state.derived or nil
local bp = state and type(state.batteryPick) == "table" and state.batteryPick or nil
return table.concat({
"deck",
tostring(zone and zone.w or 0),
tostring(zone and zone.h or 0),
tostring(Common.cells(state or {})),
return "deck"
.. "|" .. tostring(zone and zone.w or 0)
.. "|" .. tostring(zone and zone.h or 0)
.. "|" .. tostring(Common.cells(state or {}))
-- The picture the host resolved -- which follows the craft name and the cell count as well
-- as the EdgeTX bitmap -- and whether a second antenna has been seen, which adds a bar.
tostring(derived and derived.model_image or ""),
L.diversity(state) and "div" or "",
.. "|" .. tostring(derived and derived.model_image or "")
.. "|" .. (L.diversity(state) and "div" or "")
-- The phase, and it is `themePhase` rather than `flightMode` on purpose.
--
-- A host that knows the two refinement phases puts the widget into `armed` on the arm edge
Expand All @@ -2425,11 +2427,10 @@ function L.renderKey(zone, state)
--
-- `flightMode` is the fallback for a host that publishes no `themePhase`: there the two
-- refinement phases do not exist either, so the term is what it always was.
tostring(state and (state.themePhase or state.flightMode) or ""),
tostring(txBatteryStep()),
tostring(bp and bp.pending or false),
tostring(state and state.lqSource or "")
}, "|")
.. "|" .. tostring(state and (state.themePhase or state.flightMode) or "")
.. "|" .. tostring(txBatteryStep())
.. "|" .. tostring(bp and bp.pending or false)
.. "|" .. tostring(state and state.lqSource or "")
end

if type(_G) == "table" then _G.__rfsuiteThemeDeckLayoutModule = L end
Expand Down
29 changes: 15 additions & 14 deletions src/rfsuite/widgets/dashboard/themes/grid/layout.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2104,21 +2104,23 @@ end
-- label's colour is a constant of the build, so without the term the warn colour would never
-- clear. The picked pack is not a term: nothing drawn depends on it.
--
-- This runs every 0.5 s inside the host's STATE pass: one sensor read, no table allocation,
-- no probe of the card or the settings. What a build reads beyond this (the radio's battery
-- range, the image on the card) is read at build time and is not a term.
-- This runs every 0.5 s inside the host's STATE pass: one sensor read, no probe of the card or
-- the settings. The key is one `..` expression, so no list is built to be joined. What a call
-- still allocates is the key itself: Lua 5.3 makes a new string for every key over 40 bytes,
-- and the model picture's path (the suite logo's when there is no picture) puts it over. What a
-- build reads beyond this (the radio's battery range, the image on the card) is read at build
-- time and is not a term.
function L.renderKey(zone, state)
local derived = state and state.derived or nil
local bp = state and type(state.batteryPick) == "table" and state.batteryPick or nil
return table.concat({
"grid",
tostring(zone and zone.w or 0),
tostring(zone and zone.h or 0),
tostring(Common.cells(state or {})),
return "grid"
.. "|" .. tostring(zone and zone.w or 0)
.. "|" .. tostring(zone and zone.h or 0)
.. "|" .. tostring(Common.cells(state or {}))
-- The picture the host resolved -- which follows the craft name and the cell count as well
-- as the EdgeTX bitmap -- and whether a second antenna has been seen, which adds a bar.
tostring(derived and derived.model_image or ""),
L.diversity(state) and "div" or "",
.. "|" .. tostring(derived and derived.model_image or "")
.. "|" .. (L.diversity(state) and "div" or "")
-- The phase, and it is `themePhase` rather than `flightMode` on purpose.
--
-- A host that knows the two refinement phases puts the widget into `armed` on the arm edge
Expand All @@ -2135,10 +2137,9 @@ function L.renderKey(zone, state)
--
-- `flightMode` is the fallback for a host that publishes no `themePhase`: there the two
-- refinement phases do not exist either, so the term is what it always was.
tostring(state and (state.themePhase or state.flightMode) or ""),
tostring(txBatteryStep()),
tostring(bp and bp.pending or false)
}, "|")
.. "|" .. tostring(state and (state.themePhase or state.flightMode) or "")
.. "|" .. tostring(txBatteryStep())
.. "|" .. tostring(bp and bp.pending or false)
end

if type(_G) == "table" then _G.__rfsuiteThemeGridLayoutModule = L end
Expand Down
29 changes: 15 additions & 14 deletions src/rfsuite/widgets/dashboard/themes/urban/layout.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1895,21 +1895,23 @@ end
-- label's colour is a constant of the build, so without the term the warn colour would never
-- clear. The picked pack is not a term: nothing drawn depends on it.
--
-- This runs every 0.5 s inside the host's STATE pass: one sensor read, no table allocation,
-- no probe of the card or the settings. What a build reads beyond this (the radio's battery
-- range, the image on the card) is read at build time and is not a term.
-- This runs every 0.5 s inside the host's STATE pass: one sensor read, no probe of the card or
-- the settings. The key is one `..` expression, so no list is built to be joined. What a call
-- still allocates is the key itself: Lua 5.3 makes a new string for every key over 40 bytes,
-- and the model picture's path (the suite logo's when there is no picture) puts it over. What a
-- build reads beyond this (the radio's battery range, the image on the card) is read at build
-- time and is not a term.
function L.renderKey(zone, state)
local derived = state and state.derived or nil
local bp = state and type(state.batteryPick) == "table" and state.batteryPick or nil
return table.concat({
"urban",
tostring(zone and zone.w or 0),
tostring(zone and zone.h or 0),
tostring(Common.cells(state or {})),
return "urban"
.. "|" .. tostring(zone and zone.w or 0)
.. "|" .. tostring(zone and zone.h or 0)
.. "|" .. tostring(Common.cells(state or {}))
-- The picture the host resolved -- which follows the craft name and the cell count as well
-- as the EdgeTX bitmap -- and whether a second antenna has been seen, which adds a bar.
tostring(derived and derived.model_image or ""),
L.diversity(state) and "div" or "",
.. "|" .. tostring(derived and derived.model_image or "")
.. "|" .. (L.diversity(state) and "div" or "")
-- The phase, and it is `themePhase` rather than `flightMode` on purpose.
--
-- A host that knows the two refinement phases puts the widget into `armed` on the arm edge

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These parentheses are load-bearing and correct: .. binds tighter than and/or, so .. L.diversity(state) and "div" or "" would have concatenated the boolean instead of the string. Every other term is an explicit tostring(...), so no number's rendering can change either way.

Expand All @@ -1926,10 +1928,9 @@ function L.renderKey(zone, state)
--
-- `flightMode` is the fallback for a host that publishes no `themePhase`: there the two
-- refinement phases do not exist either, so the term is what it always was.
tostring(state and (state.themePhase or state.flightMode) or ""),
tostring(txBatteryStep()),
tostring(bp and bp.pending or false)
}, "|")
.. "|" .. tostring(state and (state.themePhase or state.flightMode) or "")
.. "|" .. tostring(txBatteryStep())
.. "|" .. tostring(bp and bp.pending or false)
end

if type(_G) == "table" then _G.__rfsuiteThemeUrbanLayoutModule = L end
Expand Down
Loading