Why thread::sleep Cause Low CPU and Memory Usage Than Without thread::sleep

hi, i'm new to rust and i run this code and curious what happen behind it.

use std::{thread, time, mem};

fn main ()
{
    let n: u32 = 100_000;
    let mut sample: Vec<String> = Vec::new();
    loop 
    {
        thread::sleep(time::Duration::from_secs(1));
        // let mut sample: Vec<String> = Vec::new();
        let mut i: u32 = 0;
        while i < n 
        {
            sample.push(String::from("apm"));
            i += 1;
        }

        let sample_len = sample.len();
        let sample_size = mem::size_of_val(&sample);
        println!("{} -> {}", sample_len, sample_size);
    }
}

when i remove or comment line thread::sleep(time::Duration::from_secs(1)); the cpu and memory usage get increase significantly. if i use thread::sleep cpu about <=0.6% and memory <=0.8MB but if i remove or comment that line the cpu is <30% and memory <=25MB on my windows task manager. why and what happen there behind ?

btw, i run it with command cargo single build --release test_memory.rs, copy the single exe file and run test_memory.exe from same folder with file test_memory.rs (not in target/release folder).

thanks before.

thread::sleep stops the execution on the current thread for the specified duration (1 second in this case). After that time lapses, it will continue the computation, so it will do the addition from your while loop.

thanks for reply, but i still don't understand the different about memory and cpu when using thread::sleep and without thread::sleep are huge.

what happen behind scene ?

here my guess, correct if i wrong.

if use thread::sleep the execution will have "spare" do freeing memory (variable sample) because
main thread is sleep. but if i don't use thread::sleep the execution will no have "spare" to free memory
so it will do freeing memory while execute the next instruction, in this case create inner loop again.

is my guess above correct ?

thanks before.

Without sleep, the program pushes strings into the vector as fast as it can, so obviously memory usage rises faster than if it takes a one-second break after every 100,000 strings. In both cases the memory use should grow without bound if you keep the program running, but much slower if the sleep is there.

1 Like

It won't, since sample doesn't go out of scope - it's still used at every iteration of the loop.

2 Likes

Imagin two workers building their own tower using bricks. One worker keep working without rest while the other one works in same way but sleep an hour after every single brick he placed. Even though they started building at the same time, the former worker always have done more work and consumed more bricks.

thanks everyone for reply,

first, sorry i forget to comment let mut sample: Vec<String> = Vec::new(); outside infinite loop and uncomment it inside infinite loop.

second, after i try again using perf_monitor crate i think windows task manager and resource monitor don't show real app cpu and memory. maybe they show their own cpu and memory stat for my app, so it based their own calculation not real the app.

use std::{thread, time, mem};
use perf_monitor::cpu::{ThreadStat, ProcessStat, processor_numbers};
use perf_monitor::mem::get_process_memory_info;


fn main() {
    let n: u32 = 100_000;
    // let mut sample: Vec<String> = Vec::new();
    loop 
    {
        print_info("beginning infinite loop : ");
        thread::sleep(time::Duration::from_secs(1));
        print_info("after sleep : ");

        let mut sample: Vec<String> = Vec::new();
        let mut i: u32 = 0;

        print_info("before inner loop : ");
        while i < n 
        {
            sample.push(String::from("apm"));
            i += 1;
        }
        print_info("after inner loop : ");

        let sample_len = sample.len();
        let sample_size = mem::size_of_val(&sample);
        println!("{} -> {}", sample_len, sample_size);
    }
}


fn print_info (mark: &str)
{
    println!("{}", mark);

    let core_num = processor_numbers().unwrap();
    let mut stat_p = ProcessStat::cur().unwrap();
    let mut stat_t = ThreadStat::cur().unwrap();

    let usage_p = stat_p.cpu().unwrap() * 100f64;
    let usage_t = stat_t.cpu().unwrap() * 100f64;
    let mem_info = get_process_memory_info().unwrap();

    println!("[CPU] core Number: {}, process usage: {:.2}%, current thread usage: {:.2}%", core_num, usage_p, usage_t);
    println!("[Memory] memory used: {} bytes, virtural memory used: {} bytes \n", mem_info.resident_set_size, mem_info.virtual_memory_size);
}

thank you everyone.