#finding and dealing with sources of leaks?

1 messages · Page 1 of 1 (latest)

acoustic otter
#

I'm trying to debug my app and figure out why it runs for around 30-60 seconds before crashing from what Im presuming are memory leaks somewhere. I've tried just looking at it through:

#[derive(Default, Debug)]
pub struct AppStats {
    pub memory_mb: Option<u64>, 
    pub virtual_memory_mb: Option<u64>,
    pub total_cpu_usage_percentage: Option<f32>
}


    let mut app_stats = use_signal(|| AppStats::default());

    
    use_future(move || async move {

        let sys =  System::new_all() ;
        let pid = sysinfo::get_current_pid().unwrap();

        let process = sys.process(pid).unwrap();

        loop {
            *app_stats.write() = AppStats { 
                memory_mb: Some(process.memory() / (1024 * 1024)), 
                virtual_memory_mb: Some(process.virtual_memory() / (1024 * 1024)),
                total_cpu_usage_percentage: Some(process.cpu_usage())
            };
            tokio::time::sleep(Duration::from_secs(1)).await;
        }


to see if memory starts ballooning, but my app's cpu usage and memory footprint (at least from within it self) don't move but my app still just freezes and crashes?

Any tips?

granite mason
#

I would check anywhere you are manually creating signals or copyvalues

#

Those only get freed when you drop then manually or the component drops

acoustic otter
granite mason
#

when it is removed from the dom/component tree

acoustic otter
# granite mason when it is removed from the dom/component tree

is this causing a removal from the dom?

        button {
            onclick: move |_|  {
                *dashboard_toggled.write() ^= true;
            },
            "dashboard",
        }
        div {
            {
                match *dashboard_toggled.read() {
                    true => dashboard(),
                    false => rsx!(h1 {"dashboard disabled"}),
                }
            }
        }

dashboard is a component

granite mason
#

rsx! { dashboard {} }

#

and it needs to have a capital first letter or underscore somewhere

acoustic otter
# granite mason `rsx! { dashboard {} }`

I mean dashboard is a function like app() that returns an element

#[derive(Default, Debug)]
pub struct AppStats {
    pub memory_mb: Option<u64>, 
    pub virtual_memory_mb: Option<u64>,
    /// percentage of total cpu usage divided among all cores on machine
    pub total_cpu_usage_percentage: Option<f32>
}

pub fn dashboard() -> Element {
    
    let mut app_stats = use_signal(|| AppStats::default());

    
    use_future(move || async move {

        let sys =  System::new_all() ;
        let pid = sysinfo::get_current_pid().unwrap();

        let process = sys.process(pid).unwrap();

        loop {
            *app_stats.write() = AppStats { 
                memory_mb: Some(process.memory() / (1024 * 1024)), 
                virtual_memory_mb: Some(process.virtual_memory() / (1024 * 1024)),
                total_cpu_usage_percentage: Some(process.cpu_usage())
            };
            tokio::time::sleep(Duration::from_secs(1)).await;
        }



    });
    rsx!(
        div {
            h1 {
                "app stats"
            }
            h3 {
                {format!("{:#?}", app_stats.read())}
            }
        }
    ) 
}
acoustic otter
# granite mason `rsx! { dashboard {} }`
                match *dashboard_toggled.read() {
                    true => dashboard {},
                    false => rsx!(h1 {"dashboard disabled"}),
                }
expected struct, variant or union type, found function `dashboard`
not a struct, variant or union typerustcClick for full compiler diagnostic
granite mason
#

notice the rsx! {} in my version

acoustic otter
# granite mason notice the `rsx! {}` in my version
        div {
            {
                match *dashboard_toggled.read() {
                    true => rsx! {dashboard {}} ,
                    false => rsx!(h1 {"dashboard disabled"}),
                }
            }
        }
failed to resolve: could not find `dashboard` in `elements`
could not find `dashboard` in `elements`
granite mason
#

that is where you need the capital first letter or underscore

#

If you add #[component] before pub fn dashboard() -> Element { it will help you debug

granite mason
acoustic otter
acoustic otter
acoustic otter
granite mason
#

Yes

#

#[component] should warn you about that

acoustic otter
#

with this syntax, is the component dropped after its been switched to the h1 rsx? and was it not dropped before this?

granite mason
#

before it was just a function call

#

probably not causing the magnatude of leak to crash anything unless you were repeatedly toggling the component, but that kind of issue will cause problems

#

dx check should also catch problems like that

acoustic otter
#

but are there like, tracing tools to visualize leaks/get a warning from one for dioxus? Bevy has, e.g, tracey for visualizing app performance.

granite mason
#

what platform are you on?

acoustic otter
granite mason
#

dioxus has tracing support which can help some, but generally just use whatever is availible on your system

#

on macos, I use instruments

acoustic otter
granite mason
#

sometimes, but it only catches very clear leaks

#

It was more useful for dioxus internally when we had a lot more unsafe code

#

There is a good chance the "leaks" you are running into would drop the memory eventually if you drop the right component which miri isn't as good at finding

acoustic otter
# granite mason sometimes, but it only catches very clear leaks

yeah I'm testing the different memory leak detection solutions, and im not finding anything conclusive.

  • valgrind takes awhile to startup(30-60 seconds), kills performance, then crashes without a log for the source of the crash both for cargo-valgrind and valgrind.
  • custom heap tracking allocaters(leaktracer, dhat) make the app very sluggish and un-responsive.
  • miri as you said is fine for compile time leaks but not runtime ones.

Are there other options for tracking memory leaks?

granite mason
#

I'm not sure for linux. I do some testing on linux, but usually do the bulk of the debugging on macos

#

You might post in #help-chat or the rust discord to see what people use for tracking down leaks on linux

acoustic otter
# granite mason You might post in <#943190605067079712> or the rust discord to see what people u...

After some more research, I think the best solution going forward is the AddressSanitzer from rust nightly. Im getting line by line leak reports from this.
https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html

For anyone reading this after searching for how to deal with memory leaks with dioxus(on linux):

run

sudo apt-get install llvm #<-- you won't get the lines of the errors if this is not installed

rustup default nightly

export RUSTFLAGS=-Zsanitizer=address RUSTDOCFLAGS=-Zsanitizer=address

cargo run -Zbuild-std --target x86_64-unknown-linux-gnu &> dioxus_leaks.txt # run and pipe into a file so can read the output more easily