Phased out async-stream in pursuit of compile performance

This commit is contained in:
2025-09-04 15:01:53 +02:00
parent 088cb6a247
commit e339350505
26 changed files with 359 additions and 342 deletions

View File

@@ -6,13 +6,15 @@ edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ahash = "0.8.12"
async-fn-stream = { version = "0.1.0", path = "../async-fn-stream" }
async-lock = "3.4.1"
async-once-cell = "0.5.4"
async-stream = "0.3.6"
derive_destructure = "1.0.0"
dyn-clone = "1.0.20"
futures = { version = "0.3.31", features = ["std"] }
futures = { version = "0.3.31", features = [
"std",
"async-await",
], default-features = false }
hashbrown = "0.16.0"
include_dir = { version = "0.7.4", optional = true }
itertools = "0.14.0"
@@ -29,10 +31,11 @@ ordered-float = "5.0.0"
pastey = "0.1.1"
some_executor = "0.6.1"
substack = "1.1.1"
tokio = { version = "1.47.1", optional = true }
tokio = { version = "1.47.1", optional = true, features = [] }
tokio-util = { version = "0.7.16", optional = true, features = ["compat"] }
trait-set = "0.3.0"
[features]
tokio = ["dep:tokio", "dep:tokio-util"]
default = ["tokio"]

View File

@@ -1,4 +1,5 @@
use std::any::{Any, TypeId, type_name};
use std::collections::HashMap;
use std::fmt;
use std::future::Future;
use std::num::NonZeroU32;
@@ -6,7 +7,6 @@ use std::ops::Deref;
use std::pin::Pin;
use std::rc::Rc;
use ahash::HashMap;
use dyn_clone::{DynClone, clone_box};
use futures::future::LocalBoxFuture;
use futures::{AsyncRead, AsyncWrite, FutureExt, StreamExt, stream};

View File

@@ -202,8 +202,12 @@ pub fn extension_init(
let record = SystemRecord { ctx, lazy_members: lazy_mems.into_inner() };
let systems = systems_weak.upgrade().expect("System constructed during shutdown");
systems.lock().await.insert(new_sys.id, record);
let response =
api::NewSystemResponse { lex_filter, const_root, line_types: vec![], prelude };
let line_types = join_all(
(cted.inst().dyn_parsers().iter())
.map(|p| async { i.i(p.line_head()).await.to_api() }),
)
.await;
let response = api::NewSystemResponse { lex_filter, const_root, line_types, prelude };
hand.handle(&new_sys, &response).await
},
api::HostExtReq::GetMember(get_tree @ api::GetMember(sys_id, tree_id)) => {

View File

@@ -1,6 +1,6 @@
use std::marker::PhantomData;
use async_stream::stream;
use async_fn_stream::stream;
use futures::future::{LocalBoxFuture, join_all};
use futures::{FutureExt, Stream, StreamExt};
use itertools::Itertools;
@@ -218,14 +218,15 @@ impl ConstCtx {
sys: self.ctx.sys_id(),
names: names.into_iter().map(|n| n.to_api()).collect_vec(),
};
stream! {
stream(async |mut cx| {
for name_opt in self.ctx.reqnot().request(resolve_names).await {
yield match name_opt {
cx.emit(match name_opt {
Err(e) => Err(OrcErrv::from_api(&e, self.ctx.i()).await),
Ok(name) => Ok(Sym::from_api(name, self.ctx.i()).await)
}
Ok(name) => Ok(Sym::from_api(name, self.ctx.i()).await),
})
.await
}
}
})
}
pub async fn names_n<const N: usize>(&self, names: [&Sym; N]) -> [OrcRes<Sym>; N] {
self.names(names).collect::<Vec<_>>().await.try_into().expect("Lengths must match")

View File

@@ -2,7 +2,7 @@ use crate::entrypoint::ExtensionData;
#[cfg(feature = "tokio")]
pub async fn tokio_main(data: ExtensionData) {
use std::io::Write;
use std::io::{ErrorKind, Write};
use std::mem;
use std::pin::{Pin, pin};
use std::rc::Rc;
@@ -14,8 +14,7 @@ pub async fn tokio_main(data: ExtensionData) {
use futures::stream::FuturesUnordered;
use orchid_api_traits::{Decode, Encode};
use orchid_base::msg::{recv_msg, send_msg};
use tokio::io;
use tokio::io::Stdout;
use tokio::io::{Stdout, stdin, stdout};
use tokio::task::{LocalSet, spawn_local};
use tokio_util::compat::{Compat, TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt};
@@ -24,7 +23,7 @@ pub async fn tokio_main(data: ExtensionData) {
let local_set = LocalSet::new();
local_set.spawn_local(async {
let host_header = api::HostHeader::decode(Pin::new(&mut tokio::io::stdin().compat())).await;
let host_header = api::HostHeader::decode(Pin::new(&mut stdin().compat())).await;
let init =
Rc::new(extension_init(data, host_header, Rc::new(|fut| mem::drop(spawn_local(fut)))));
let mut buf = Vec::new();
@@ -36,10 +35,10 @@ pub async fn tokio_main(data: ExtensionData) {
let mut io = FuturesUnordered::<LocalBoxFuture<()>>::new();
io.push(Box::pin(async {
loop {
match recv_msg(pin!(io::stdin().compat())).await {
match recv_msg(pin!(stdin().compat())).await {
Ok(msg) => init.send(&msg[..]).await,
Err(e) if e.kind() == io::ErrorKind::BrokenPipe => break,
Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => break,
Err(e) if e.kind() == ErrorKind::BrokenPipe => break,
Err(e) if e.kind() == ErrorKind::UnexpectedEof => break,
Err(e) => panic!("{e}"),
}
}
@@ -47,7 +46,7 @@ pub async fn tokio_main(data: ExtensionData) {
io.push(Box::pin(async {
while let Some(msg) = init.recv().await {
static STDOUT: OnceCell<Mutex<Compat<Stdout>>> = OnceCell::new();
let stdout_lk = STDOUT.get_or_init(async { Mutex::new(io::stdout().compat_write()) }).await;
let stdout_lk = STDOUT.get_or_init(async { Mutex::new(stdout().compat_write()) }).await;
let mut stdout_g = stdout_lk.lock().await;
send_msg(pin!(&mut *stdout_g), &msg[..]).await.expect("Parent pipe broken");
}

View File

@@ -1,7 +1,7 @@
use std::num::NonZero;
use std::rc::Rc;
use async_stream::stream;
use async_fn_stream::stream;
use dyn_clone::{DynClone, clone_box};
use futures::future::{LocalBoxFuture, join_all};
use futures::{FutureExt, StreamExt};
@@ -209,8 +209,14 @@ impl MemKind {
Self::Lazy(lazy) => api::MemberKind::Lazy(ctx.with_lazy(lazy)),
Self::Const(c) => api::MemberKind::Const(c.api_return(ctx.sys(), ctx.req()).await),
Self::Mod { members } => api::MemberKind::Module(api::Module {
members: Box::pin(stream! { for m in members { yield m.into_api(ctx).await } }.collect())
.await,
members: stream(async |mut cx| {
for m in members {
cx.emit(m.into_api(ctx).await).await
}
})
.collect()
.boxed_local()
.await,
}),
}
}