Posix wrapper for profiling (getrusage)


#1

Hi, I am trying to add some profiling to a small rust application for multithreading perfomance testing.

getrusage from posix seems to be a perfect match for my use case.

I found an unsafe wrapper of getrusage from the libc wrapper library but with no much documentation. also the fact that it is qualified as unsafe does not really make me want to use it.

There is nix-rust but it’s sys package does not contain the resource package (sys/resource.h contains getrusage in libc)

Is there any available similar function in Rust’s standard library, or in a crate ?


#2

Everything in libc is marked as unsafe on principle, because it comes from C, and Rust doesn’t control what C does. It doesn’t mean it’s bad, it means you need to read manual of the C function and ensure that you don’t misuse it.

Rust’s libc doesn’t do anything itself. It only exposes functions that already exist in C exactly as they are. So read manual for the getrusage for C, and everything will apply to Rust.

unsafe {
  let mut out: libc::rusage = std::mem::zeroed(); 
  libc::getrusage(libc::RUSAGE_SELF, &mut out);
}

#3

If you end up wrapping getrusage, we would love to add it to nix. We could even walk you through it’s addition in a PR if you’re interested in starting there. Do note, however, that docs for these functions are primarily in the man pages and higher-level wrapers usually defer to those docs primarily.


#4

Thanks a lot @kornel !
Also for the working sample, I was looking over the internet for this :

  let mut out: libc::rusage = std::mem::zeroed(); 

and had found much more verbose ways of doing it (using std::default::Default).

I am not sure tough about memory allocation and freeing when using these functions, I’ll look it up.


#5

@susurrus I would definitely be glad to contribute if possible. But beware, my C is rusty, and I am beginning with Rust.


#6

This defines a struct on stack. It’s automatically freed when goes out of scope.

I’ve used mem::zeroed() here because Rust requires variables to be initialized with something (it’s equivalent of memset with 0). Because getrusage is supposed to overwrite the entire struct, mem::uninitialized() would have worked as well (it pretends to initialize, but doesn’t :)).

Default is roughly similar, but it only works on structs that explicitly implement it and use struct-specific defaults.