Performance & Debugging
When a macro feels slow or unreliable, the cause is usually one of three things:
- the detection area is too large
- the same expensive detection is repeated too often
- the macro continues without proving that the previous step succeeded
This guide focuses on the fastest ways to debug and optimize those problems.
Measure the Expensive Steps
In advanced macros, the most expensive operations are usually:
- full-screen image search
- full-screen OCR
- repeated waits for the same target
- large swipe loops without stable checkpoints
If a macro is slow, inspect the screen scans first, not the taps.
Shrink the Search Area First
If one page feels slow, reduce the search scope before tuning scores or delays.
local listArea = Region(0, 500, 1080, 2000)
listArea:find("collect-button.jpg")
This usually gives a larger performance improvement than minor parameter changes.
Use Fit Region After the First Match
If you need to interact repeatedly inside a matched object, use the first match to create a fitted region.
local result = Screen:find("dialog-frame.jpg")
if result then
local fitRegion = result:getRegion()
fitRegion:click("confirm-button.jpg")
fitRegion:wait("done-label.jpg", 5000)
end
This pattern is effective because:
Screen:find()pays the full-screen search cost oncegetRegion()gives you the exact matched bounds- later searches run only inside that fitted area
This is especially helpful for:
- popups
- fixed-size cards
- repeated list items
- dialog containers
- game panels or HUD components
If the object keeps the same size, fit region can cut processing cost dramatically.
Reuse Results When the Screen Has Not Changed
Do not call detection repeatedly if the UI is still in the same state.
Bad:
if Screen:exist("start.jpg") then
Screen:click("start.jpg")
end
Better:
local startExists = Screen:exist("start.jpg")
if startExists then
Screen:click("start.jpg")
end
Debug False Positives
If the macro clicks the wrong thing:
- increase match score slightly
- crop the template tighter
- reduce the search area
- stop using grayscale if color matters
- switch to text detection if the label is more stable than the image
Most false positives are caused by a template that is too generic, not by a bad threshold alone.
Debug False Negatives
If the macro cannot find a target that is clearly visible:
- lower match score slightly
- recapture the template at the real execution scale
- turn on dynamic scaling if multiple devices are involved
- test text detection instead of image detection
- verify the target is inside the actual search region
Use Highlights During Development
When available, highlights are useful to confirm what the macro is matching before it clicks.
That helps answer two questions quickly:
- did the macro find the right object?
- is the region or threshold too broad?
Use highlights while tuning, then disable them if they slow down the final production flow.
Tune Delays With Intent
Good delays absorb transitions. Bad delays hide logic problems.
Add delay only when:
- an animation blocks interaction
- a new screen is rendered but not yet stable
- the app performs a short transition that has no reliable marker
If a page has a reliable marker, always prefer wait() over raw sleep.
Build a Debug Version of Important Macros
For larger automations, keep two versions mentally:
- a debug flow with more waits, alerts, highlights, and logs
- a production flow with the same logic but less noise
That makes it easier to tune without losing a clean final version.
Optimization Checklist
Before trying advanced tuning, ask:
- Can I reduce the search area?
- Can I replace repeated scans with one stored result?
- Can I wait for one stable anchor instead of polling many targets?
- Can I split the macro into smaller verified steps?
- Can I remove unnecessary full-screen OCR?