table.sort function gives "Failed to perform mandatory yield" near end of time slice
planned
Nikki Lacrima
Builder's Brewery [Main] Mesh Academy Blender Classroom, Builders Brewery (77, 62, 26)
LUAU 2026-01-30.21516666911
If the scan range is decreased to 10 giving fewer sensor results the script works, when number of sensor results increases the error occurs..
The objective is to sort a table of uuid's by the corresponding object names.
function LLEvents.touch_start(total_number)
ll.Say(0, "touch_start")
ll.Sensor("", NULL_KEY, PASSIVE+AGENT , 30.0, PI)
end
function LLEvents.sensor( events )
ll.Say(0, "sensor")
local lSensorResults = {}
for _, evt in events do
table.insert(lSensorResults, evt:getKey() )
end
-- now sort and print
table.sort(lSensorResults, function(a,b) return string.lower( ll.Key2Name(a)) < string.lower( ll.Key2Name(b)) end )
for i, kn in ipairs(lSensorResults) do
ll.Say(0,`{ll.Key2Name(kn)} {kn}`)
end
end
Log In
H
Harold Linden
Thanks for sending this in!
Yep, unfortunately this is the case with a lot of standard library functions that accept a function parameter... They don't allow yielding in the middle of an operation, which the simulator needs to be able to do to go work on other scripts.
I think we may end up going with some notion of a critical section around those functions that has a constant time limit, so they won't behave differently around the end of a script's allotted time slice. A better error message might be good too :)
H
Harold Linden
marked this post as
planned
H
Harold Linden
marked this post as
tracked
SuzannaLinn Resident
table.sort()
cannot yield, meaning the function is designed to execute in one go without pausing. If it exceeds the script's allotted running time, the scheduler forces it to stop, resulting in a 'Failed to perform mandatory yield' error.For instance, sorting a long table:
local t = {}
for i = 1, 500 do
table.insert(t, math.random(1000))
end
table.sort(t, function(a,b)
return a > b
end)
-- > Failed to perform mandatory yield
Or repeated sorts with a short table, until a
table.sort()
happens to run near the end of the scheduled time:local t = {}
for i = 1, 100 do
table.insert(t, math.random(1000))
end
for i = 1, 99 do
table.sort(t, function(a,b)
return a > b
end)
print(i)
end
-- > 1
-- > 2
-- > 3
-- > 4
-- > 5
-- > Failed to perform mandatory yield
We can try to move ll functions that call the simulator and are slow out of the sorting function to minimize the error chances:
function LLEvents.touch_start(total_number)
ll.Say(0, "touch_start")
ll.Sensor("", NULL_KEY, PASSIVE+AGENT , 30.0, PI)
end
function LLEvents.sensor( events )
ll.Say(0, "sensor")
local lSensorResults = {}
for _, evt in events do
table.insert(lSensorResults, { id = evt:getKey(), name = evt:getName() })
end
-- now sort and print
table.sort(lSensorResults, function(a,b) return string.lower(a.name) < string.lower(b.name) end)
for i, kn in ipairs(lSensorResults) do
ll.Say(0,`{kn.id} {kn.name}`)
end
end
Nikki Lacrima
SuzannaLinn Resident
Thanks for info on timing and yielding.
I used two tables, one array with the keys and one dictionary table of key = name pairs. Should be basically same memory footprint and speed. The choise depends on how we plan to further process the data.