Skip to content
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

high memory usage #244

Open
rafaeljesus opened this issue Feb 27, 2024 · 3 comments
Open

high memory usage #244

rafaeljesus opened this issue Feb 27, 2024 · 3 comments

Comments

@rafaeljesus
Copy link

rafaeljesus commented Feb 27, 2024

Hello, I using pprof-rs to generate pprof data and send it to GCloud,

I have a background task that runs every 5s as follows:

const FREQUENCY: i32 = 10;

// this fn is called every 5s in a loop
pub async fn cpu(&self) -> Result<protos::Profile, ProfileError> {
    let guard = pprof::ProfilerGuardBuilder::default()
        .frequency(FREQUENCY)
        .blocklist(&["libc", "libgcc", "pthread", "vdso"])
        .build()
        .map_err(|e| ProfileError::CpuError(e.to_string()))?;

    // Build the profile and return it in profile.proto format:
    guard
        .report()
        .build()
        .map_err(|e| ProfileError::CpuError(e.to_string()))?
        .pprof()
        .map_err(|e| ProfileError::CpuError(e.to_string()))
}

the caller side, take_profile runs every 5 seconds in a loop

async fn take_profile(&self) -> Result<(), ProfileError> {
    let mut profile_handle = // crate_profile RPC
    let profile_type = ...

    let profile_bytes = match profile_type {
        crate::ProfileType::Cpu => {
            let profile = self.inner.profiler.cpu().await?; // calling the cpu fn declared above
            let mut buf = bytes::BytesMut::new();
            profile
                .encode(&mut buf)
                .map_err(|e| ProfileError::EncodingError(e.to_string()))?;
            Ok(buf.freeze())
        }
        _ => Err(ProfileError::UnsupportedType(format!("{:?}", profile_type))),
    };

    match profile_bytes {
        Ok(bytes) => {
            profile_handle.profile_bytes = bytes;
            self.client()
                .upload_profile(profile_handle.clone())
                .await
                .map_err(|e| ProfileError::UpdateError(e.to_string()))?;
            Ok(())
        }
        Err(e) => Err(e),
    }
}

I have this enabled in different rust apps in our GKE cluster, and in all of them memory increased + 10x, below is a screenshot from a pod that was using 15 MB, and when the pprof-rs was enabled it jumped to +300MB

metric: jemalloc_active_bytes

Screenshot 2024-02-27 at 19 07 16

I took heap profile data using polarsignals/rust-jemalloc-pprof

Screenshot 2024-02-27 at 17 15 08
Screenshot 2024-02-27 at 17 17 28
Screenshot 2024-02-27 at 17 18 26

Does that ring any bell for you? I appreciate any help you can provide.

@rafaeljesus
Copy link
Author

I have a background task that runs every 5s

I've reduced to 60s and still the same memory consuption

@rafaeljesus
Copy link
Author

just to rule out any possible problem with the background task, I took a profile hitting the pprof/profile endpoint in a app with the background task mentioned above disabled, I took the profile just once and memory increased this much and continued that way,

in my pprof endpoint, I am also using the ProfilerGuardBuilder

Screenshot 2024-03-04 at 17 09 02

@ttys3
Copy link

ttys3 commented Apr 8, 2024

yes, I got this problem too.

We limited the process memory to 128M before, since it actully usage is around 10MB.

but after enabled pyroscope-rs (which uses tikv/pprof-rs), the meory increased to near 220MB+

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants