-
-
Notifications
You must be signed in to change notification settings - Fork 26
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
Reduced string allocation #104
Comments
For note, on the wasm side it will only save memory for things about 10 in length (because 32-bits, still worth it I say), I'm more curious on saving it on the server when I SSR it for hydration purposes, generating the SSR is dominating the time in the servers route processor. |
A quick test shows that though memory pressure is reduced, the extra conditional is adding enough overhead that offsets the performance boost from that for initial load, it only 'gains' for stored values over the longer time, needs more testing... |
I'm definitely glad you're looking into it! As it stands mogwai performs worst in the memory domain. I welcome any improvements, so long as they don't hamper ergonomics. |
I wonder if just using a |
Thank you for the benchmarking! It's too bad it isn't an obvious easy win.
That sounds like a great idea. I'm looking forward to any findings :) |
Didn't get time yesterday, busy at work, just looking into it this morning and I notice that non-static str's are able to be casted in (they are converted to Strings); since rust doesn't have specialization then that conversion would have to force 'static for strings, if non-static then they'd have to .to_string or whatever on it instead, so that would be a breaking change little though it may be... (which I personally think is a good change, better then hiding an allocation after all). I'm not even sure if that's even really used though, it doesn't seem to be in my code, I use either String or &'static str for mine... |
So yeah, again it seems within error bounds for speed, but it does reduce memory usage a bit, still unsure if its worth it though. It did reduce my SSR generation time by ~8-9% though, which is worth it for me anyway for sure. ^.^ I only added Cow in one 'area' (the view), haven't looked into elsewhere yet so might have more speedups... EDIT: I wonder if anyone's made a combined Cow<'static, ...> and smartstring/smolstr-like thing yet... |
It definitely seems that something like this is good to put on the roadmap. |
For reference with my SSR benchmarks here, here is a test with leptos of a trivial counter example (for simple) and that same counter put in a single div 10000 times (for many), and timed the various parts, these are the times I got (using the cow version of mogwai here, the mainline version is basically the same but about 8-9% slower): simple_counter/mogwai time: [6.4647 µs 6.4842 µs 6.5034 µs]
simple_counter/leptos time: [7.1320 µs 7.1526 µs 7.1758 µs]
many_counter/mogwai time: [123.57 ms 124.15 ms 124.77 ms]
many_counter/leptos time: [77.771 ms 78.192 ms 78.643 ms]
parts_many-mogwai/view time: [31.956 ms 32.027 ms 32.099 ms]
parts_many-mogwai/generation
time: [58.429 ms 58.926 ms 59.566 ms]
parts_many-mogwai/render
time: [29.603 ms 29.684 ms 29.768 ms]
parts_many-leptos/view time: [26.477 ms 26.657 ms 26.841 ms]
parts_many-leptos/render
time: [49.994 ms 50.909 ms 52.136 ms] This is the mogwai part of timing the 'parts': {
let mut g = c.benchmark_group("parts_many-mogwai");
g.bench_function("view", |b| {
b.to_async(&async_runtime)
.iter(|| async move { mogwai_many_counter_view() })
});
g.bench_function("generation", |b| {
b.to_async(&async_runtime).iter_custom(|iters| async move {
let mut elapsed = Duration::default();
for _ in 0..iters {
let view = mogwai_many_counter_view();
let start = Instant::now();
black_box(SsrDom::try_from(view).unwrap());
elapsed += start.elapsed();
}
elapsed
})
});
g.bench_function("render", |b| {
b.to_async(&async_runtime).iter_custom(|iters| async move {
let view = mogwai_many_counter_view();
let ssr = SsrDom::try_from(view).unwrap();
let start = Instant::now();
for _ in 0..iters {
black_box(ssr.html_string().await);
}
start.elapsed()
})
});
} And this is the mogwai simple counter: pub fn simple_counter() -> ViewBuilder {
let output_clicked = Output::<()>::default();
let mut c = 0u32;
html! {
<div
style="float:left;padding:1em;border-radius:.5em;border:1px solid #ddd;background:#f7f7f7;cursor:pointer"
on:click=output_clicked.sink().contra_map(|_: JsDomEvent| ())
>
<p>
{(
"Hello world!",
output_clicked.stream().map(move |()| {
c += 1;
match c {
0 => CowString::from("Hello world!"),
1 => CowString::from("Caught 1 click, click again 😀"),
clicks => format!("Caught {} clicks", clicks).into(),
}
})
)}
</p>
</div>
}
} |
Kind of wish a view could be rendered via a reference instead of it taking ownership of it in mogwai, would be convenient to static generate a set of them for faster rendering and manual patching for realtime updates without needing to rerun the view each time. |
@OvermindDL1 - I'm back on this - well the rendering from a reference portion. What type exactly are you referring to? Because |
Would there be any interest in replacing a lot of the
String
usages withSmolStr
instead, it would relieve a lot of memory pressure wins as a ton of strings (for example, attributes, styles, etc...) in mogwai(-dom) are less than 24 utf-8 bytes in length?The text was updated successfully, but these errors were encountered: