Optimize polling async functions (40% performance win)

This commit is contained in:
Alex Orlenko 2023-06-04 20:53:12 +01:00
parent 0f5c68dcf8
commit d5483988d2
No known key found for this signature in database
GPG Key ID: 4C150C250863B96D
1 changed files with 31 additions and 21 deletions

View File

@ -2773,31 +2773,33 @@ impl Lua {
unsafe extern "C" fn poll_future(state: *mut ffi::lua_State) -> c_int { unsafe extern "C" fn poll_future(state: *mut ffi::lua_State) -> c_int {
let upvalue = get_userdata::<AsyncPollUpvalue>(state, ffi::lua_upvalueindex(1)); let upvalue = get_userdata::<AsyncPollUpvalue>(state, ffi::lua_upvalueindex(1));
let extra = (*upvalue).extra.get(); let extra = (*upvalue).extra.get();
callback_error_ext(state, extra, |nargs| { callback_error_ext(state, extra, |_| {
if nargs < ffi::LUA_MINSTACK {
check_stack(state, ffi::LUA_MINSTACK - nargs)?;
}
let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref()); let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
let _guard = StateGuard::new(&lua.0, state); let _guard = StateGuard::new(&lua.0, state);
let fut = &mut (*upvalue).data; let fut = &mut (*upvalue).data;
let mut ctx = Context::from_waker(lua.waker()); let mut ctx = Context::from_waker(lua.waker());
match fut.as_mut().poll(&mut ctx) { match fut.as_mut().poll(&mut ctx) {
Poll::Pending => { Poll::Pending => Ok(0),
check_stack(state, 1)?;
ffi::lua_pushboolean(state, 0);
Ok(1)
}
Poll::Ready(results) => { Poll::Ready(results) => {
let results = results?; let mut results = results?;
let nresults = results.len() as Integer; let nresults = results.len();
let results = lua.create_sequence_from(results)?; lua.push_value(Value::Integer(nresults as _))?;
check_stack(state, 3)?; match nresults {
ffi::lua_pushboolean(state, 1); 0 => Ok(1),
lua.push_value(Value::Table(results))?; 1 | 2 => {
lua.push_value(Value::Integer(nresults))?; // Fast path for 1 or 2 results without creating a table
Ok(3) for r in results.drain_all() {
lua.push_value(r)?;
}
MultiValue::return_to_pool(results, lua);
Ok(nresults as c_int + 1)
}
_ => {
lua.push_value(Value::Table(lua.create_sequence_from(results)?))?;
Ok(2)
}
}
} }
} }
}) })
@ -2850,9 +2852,17 @@ impl Lua {
local poll = get_poll(...) local poll = get_poll(...)
local pending, yield, unpack = pending, yield, unpack local pending, yield, unpack = pending, yield, unpack
while true do while true do
local ready, res, nres = poll() local nres, res, res2 = poll()
if ready then if nres ~= nil then
return unpack(res, nres) if nres == 0 then
return
elseif nres == 1 then
return res
elseif nres == 2 then
return res, res2
else
return unpack(res, nres)
end
end end
yield(pending) yield(pending)
end end