-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Incremental compile OOM when rsx has a loop over a component #3903
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Further research: on expanding, within the loop, it seems that within the #[cfg(
debug_assertions
)] let __template_read = match __template_read.as_ref().map(|__template_read| __template_read.as_ref()) {
Some(Some(__template_read)) => &__template_read,
_ => __original_template(),
}; in debug mode, it is specifically the Specifically: Broken: #[cfg(
debug_assertions
)] let __template_read = match __template_read.as_ref().map(|__template_read| ()) {
Some(Some(__template_read)) => &__template_read,
_ => __original_template(),
};
let __template_read = __original_template(); Works: #[cfg(
debug_assertions
)] let __template_read = match __template_read.as_ref() {
Some(Some(__template_read)) => &__template_read,
_ => __original_template(),
};
let __template_read = __original_template(); I wonder if this is a rustc bug. Macro expansion - the relevant section is the template match within the 0..50's map() call#[component]
fn App() -> Element {
let initial_state =
use_server_future(move || async move { notify_update(None).await.unwrap() })?;
let mut state = use_signal(|| initial_state.unwrap());
use_future(move || async move {
loop {
let old_state = *state.read();
let new_state = notify_update(Some(old_state)).await.unwrap();
state.set(new_state);
}
});
let mut loaded = use_signal(|| "No");
use_effect(move || loaded.set("Yes"));
dioxus_core::Element::Ok({
#[cfg(debug_assertions)]
fn __original_template() -> &'static dioxus_core::internal::HotReloadedTemplate {
static __ORIGINAL_TEMPLATE: ::std::sync::OnceLock<dioxus_core::internal::HotReloadedTemplate> = ::std::sync::OnceLock::new();
if __ORIGINAL_TEMPLATE.get().is_none() { _ = __ORIGINAL_TEMPLATE.set(dioxus_core::internal::HotReloadedTemplate::new(None, vec![dioxus_core::internal::HotReloadDynamicNode::Dynamic(0usize), dioxus_core::internal::HotReloadDynamicNode::Dynamic(1usize)], vec![dioxus_core::internal::HotReloadDynamicAttribute::Dynamic(0usize)], vec![], __TEMPLATE_ROOTS)); }
__ORIGINAL_TEMPLATE.get().unwrap()
}
#[cfg(
debug_assertions
)] let __template_read = {
static __NORMALIZED_FILE: &'static str = {
const PATH: &str = dioxus_core::const_format::str_replace!(file ! (), "\\\\" , "/" );
dioxus_core::const_format::str_replace!(PATH , '\\' , "/" )
};
static __TEMPLATE: GlobalSignal<Option<dioxus_core::internal::HotReloadedTemplate>> = GlobalSignal::with_location(|| None::<dioxus_core::internal::HotReloadedTemplate>, __NORMALIZED_FILE, line!(), column!(), 0usize);
dioxus_core::Runtime::current().ok().map(|_| __TEMPLATE.read())
};
#[cfg(
debug_assertions
)] let __template_read = match __template_read.as_ref().map(|__template_read| __template_read.as_ref()) {
Some(Some(__template_read)) => &__template_read,
_ => __original_template(),
};
#[cfg(
debug_assertions
)] let mut __dynamic_literal_pool = dioxus_core::internal::DynamicLiteralPool::new(vec![format!("{0:}", loaded).to_string()]);
let __dynamic_nodes: [dioxus_core::DynamicNode; 2usize] = [dioxus_core::DynamicNode::Text(dioxus_core::VText::new(::std::format!("{loaded}"
))), {
let ___nodes = (0..50).into_iter().map(|_| {
dioxus_core::Element::Ok({
#[cfg(debug_assertions)]
fn __original_template() -> &'static dioxus_core::internal::HotReloadedTemplate {
static __ORIGINAL_TEMPLATE: ::std::sync::OnceLock<dioxus_core::internal::HotReloadedTemplate> = ::std::sync::OnceLock::new();
if __ORIGINAL_TEMPLATE.get().is_none() { _ = __ORIGINAL_TEMPLATE.set(dioxus_core::internal::HotReloadedTemplate::new(None, vec![], vec![], vec![], __TEMPLATE_ROOTS)); }
__ORIGINAL_TEMPLATE.get().unwrap()
}
#[cfg(
debug_assertions
)] let __template_read = {
static __NORMALIZED_FILE: &'static str = {
const PATH: &str = dioxus_core::const_format::str_replace!(file ! (), "\\\\" , "/" );
dioxus_core::const_format::str_replace!(PATH , '\\' , "/" )
};
static __TEMPLATE: GlobalSignal<Option<dioxus_core::internal::HotReloadedTemplate>> = GlobalSignal::with_location(|| None::<dioxus_core::internal::HotReloadedTemplate>, __NORMALIZED_FILE, line!(), column!(), 1usize);
dioxus_core::Runtime::current().ok().map(|_| __TEMPLATE.read())
};
#[cfg(
debug_assertions
)] let __template_read = match __template_read.as_ref().map(|__template_read| __template_read.as_ref()) {
Some(Some(__template_read)) => &__template_read,
_ => __original_template(),
};
#[cfg(
debug_assertions
)] let mut __dynamic_literal_pool = dioxus_core::internal::DynamicLiteralPool::new(vec![]);
let __dynamic_nodes: [dioxus_core::DynamicNode; 0usize] = [];
let __dynamic_attributes: [Box<[dioxus_core::Attribute]>; 0usize] = []; #[doc(
hidden
)]
static __TEMPLATE_ROOTS: &[dioxus_core::TemplateNode] = &[{ dioxus_core::TemplateNode::Element { tag: dioxus_elements::elements::div::TAG_NAME, namespace: dioxus_elements::div::NAME_SPACE, attrs: &[], children: &[] } }];
#[cfg(
debug_assertions
)] {
let mut __dynamic_value_pool = dioxus_core::internal::DynamicValuePool::new(Vec::from(__dynamic_nodes), Vec::from(__dynamic_attributes), __dynamic_literal_pool);
__dynamic_value_pool.render_with(__template_read)
}
#[cfg(not(debug_assertions))] {
#[doc(hidden)]
static ___TEMPLATE: dioxus_core::Template = dioxus_core::Template { roots: __TEMPLATE_ROOTS, node_paths: &[], attr_paths: &[] };
#[allow(
clippy::let_and_return
)] let __vnodes = dioxus_core::VNode::new(None, ___TEMPLATE, Box::new(__dynamic_nodes), Box::new(__dynamic_attributes));
__vnodes
}
})
}).into_dyn_node();
___nodes
}];
let __dynamic_attributes: [Box<[dioxus_core::Attribute]>; 1usize] = [Box::new([{
dioxus_elements::events::onclick(async |_| { trigger_update().await.unwrap(); }
)
}])]; #[doc(hidden)]
static __TEMPLATE_ROOTS: &[dioxus_core::TemplateNode] = &[{ dioxus_core::TemplateNode::Element { tag: dioxus_elements::elements::button::TAG_NAME, namespace: dioxus_elements::button::NAME_SPACE, attrs: &[dioxus_core::TemplateAttribute::Dynamic { id: 0usize }], children: &[] } }, { dioxus_core::TemplateNode::Element { tag: dioxus_elements::elements::div::TAG_NAME, namespace: dioxus_elements::div::NAME_SPACE, attrs: &[], children: &[dioxus_core::TemplateNode::Dynamic { id: 0usize }] } }, dioxus_core::TemplateNode::Dynamic { id: 1usize }];
#[cfg(
debug_assertions
)] {
let mut __dynamic_value_pool = dioxus_core::internal::DynamicValuePool::new(Vec::from(__dynamic_nodes), Vec::from(__dynamic_attributes), __dynamic_literal_pool);
__dynamic_value_pool.render_with(__template_read)
}
#[cfg(not(debug_assertions))] {
#[doc(hidden)]
static ___TEMPLATE: dioxus_core::Template = dioxus_core::Template { roots: __TEMPLATE_ROOTS, node_paths: &[&[1u8, 0u8], &[2u8]], attr_paths: &[&[0u8]] };
#[allow(
clippy::let_and_return
)] let __vnodes = dioxus_core::VNode::new(None, ___TEMPLATE, Box::new(__dynamic_nodes), Box::new(__dynamic_attributes));
__vnodes
}
})
} |
Quick update here: this is likely a rustc bug. See rust-lang/rust#139142 |
The fix has been merged into master: rust-lang/rust@b17948a Related rollup: rust-lang/rust#139169 |
Confirmed - works on latest nightly (as of |
Problem
When compiling code with a loop, a server function, and some other bits and bobs, the compiler will continuously eat memory and eventually OOM. This occurs on my machine with 86GB of RAM free - it fully OOMs.
There's a few edits that prevent duplicating this - removing the onclick handler, and removing the loop around the
div {}
both prevent this occurring, but in the larger app the only way to consistently prevent this was to remove the loop(?)I do 50 here, but a loop of
0..1
is enough to cause a problem.Once you do get a hang, the issue can crop up in places that it did not previously occur - you need to
cargo clean
between each set of tests to ensure that you have a clean slate, otherwise you will get false positives in when things break.You cannot reproduce this purely with clean builds - this only occurs during incremental rebuilds.
Steps To Reproduce
Note, for all compiles,
cargo build --profile server-dev --verbose --features dioxus/server
suffices to reproduce - but this can be replicated with the dioxus CLI too. Just you can't as easily kill it and prevent the OOM killer stomping all over your machine with the dioxus CLI, as it sometimes fails to properly kill the processes when cancelling.Steps to reproduce the behavior:
src/main.rs
use_effect(move || loaded.set("Yes"));
and rebuild - should be successfulExpected behavior
Dioxus should build just fine
Screenshots
Environment:
Questionnaire
I'm interested in fixing this myself but don't know where to start. I don't know how much time I will have but if I do have time I'm happy to go for it.
Code:
Full example project: breakshit.zip
The text was updated successfully, but these errors were encountered: