summaryrefslogtreecommitdiff
path: root/src/lua.rs
diff options
context:
space:
mode:
authorAlex Orlenko <zxteam@protonmail.com>2023-06-04 20:53:12 +0100
committerAlex Orlenko <zxteam@protonmail.com>2023-06-04 20:53:12 +0100
commitd5483988d2c81f9850f0854cc58783b64d727855 (patch)
tree012c4ddc92f46c01b6db1004b2a5d7fcff9c50c2 /src/lua.rs
parent0f5c68dcf8f46f881150e8c9f648dab7f034625e (diff)
downloadmlua-d5483988d2c81f9850f0854cc58783b64d727855.zip
Optimize polling async functions (40% performance win)
Diffstat (limited to 'src/lua.rs')
-rw-r--r--src/lua.rs52
1 files changed, 31 insertions, 21 deletions
diff --git a/src/lua.rs b/src/lua.rs
index 06bc5a3..6f7fbbc 100644
--- a/src/lua.rs
+++ b/src/lua.rs
@@ -2773,31 +2773,33 @@ impl Lua {
unsafe extern "C" fn poll_future(state: *mut ffi::lua_State) -> c_int {
let upvalue = get_userdata::<AsyncPollUpvalue>(state, ffi::lua_upvalueindex(1));
let extra = (*upvalue).extra.get();
- callback_error_ext(state, extra, |nargs| {
- if nargs < ffi::LUA_MINSTACK {
- check_stack(state, ffi::LUA_MINSTACK - nargs)?;
- }
-
+ callback_error_ext(state, extra, |_| {
let lua: &Lua = mem::transmute((*extra).inner.assume_init_ref());
let _guard = StateGuard::new(&lua.0, state);
let fut = &mut (*upvalue).data;
let mut ctx = Context::from_waker(lua.waker());
match fut.as_mut().poll(&mut ctx) {
- Poll::Pending => {
- check_stack(state, 1)?;
- ffi::lua_pushboolean(state, 0);
- Ok(1)
- }
+ Poll::Pending => Ok(0),
Poll::Ready(results) => {
- let results = results?;
- let nresults = results.len() as Integer;
- let results = lua.create_sequence_from(results)?;
- check_stack(state, 3)?;
- ffi::lua_pushboolean(state, 1);
- lua.push_value(Value::Table(results))?;
- lua.push_value(Value::Integer(nresults))?;
- Ok(3)
+ let mut results = results?;
+ let nresults = results.len();
+ lua.push_value(Value::Integer(nresults as _))?;
+ match nresults {
+ 0 => Ok(1),
+ 1 | 2 => {
+ // Fast path for 1 or 2 results without creating a table
+ 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 pending, yield, unpack = pending, yield, unpack
while true do
- local ready, res, nres = poll()
- if ready then
- return unpack(res, nres)
+ local nres, res, res2 = poll()
+ if nres ~= nil then
+ 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
yield(pending)
end