pub struct Profiler { /* private fields */ }Expand description
Rust profiler based on async-profiler.
Spawning a profiler can be done either in an attached (controllable) mode, which allows for stopping the profiler (and, in fact, stops it when the relevant handle is dropped), or in detached mode, in which the profiler keeps running forever. Applications that can shut down the profiler at run-time, for example applications that support reconfiguration of a running profiler, generally want to use controllable mode. Other applications (most of them) should use detached mode.
In addition, the profiler can either be spawned into the current Tokio runtime, or into a new one. Normally, applications should spawn the profiler into their own Tokio runtime, but applications that don’t have a default Tokio runtime should spawn it into a different one
This leaves 4 functions:
- Self::spawn - detached, same runtime
- Self::spawn_thread_to_runtime - detached, different runtime
- Self::spawn_controllable - controllable, same runtime
- Self::spawn_controllable_thread_to_runtime - controllable, different runtime
In addition, there’s a helper function that just spawns the profiler to a new runtime in a new thread, for applications that don’t have a Tokio runtime and don’t need complex control:
- Self::spawn_thread - detached, new runtime in a new thread
Implementations§
Source§impl Profiler
impl Profiler
Sourcepub fn spawn(self) -> Result<JoinHandle<()>, SpawnError>
pub fn spawn(self) -> Result<JoinHandle<()>, SpawnError>
Start profiling. The profiler will run in a tokio task at the configured interval.
This is the same as calling Profiler::spawn_controllable followed by RunningProfiler::detach, except it returns a JoinHandle.
The returned JoinHandle can be used to detect if the profiler has exited due to a fatal error.
This function will fail if it is unable to start async-profiler, for example
if it can’t find or load libasyncProfiler.so.
§Tokio Runtime
This function must be run within a Tokio runtime, otherwise it will panic. If
your application does not have a main Tokio runtime, see
Profiler::spawn_thread.
§Example
This example uses ProfilerBuilder::with_local_reporter which reports the profiles to a directory. It works with any other Reporter using ProfilerBuilder::with_reporter.
let profiler = ProfilerBuilder::default()
.with_local_reporter("/tmp/profiles")
.build();
profiler.spawn()?;Sourcepub fn spawn_thread_to_runtime(
self,
runtime: Runtime,
spawn_fn: impl FnOnce(Box<dyn FnOnce() + Send>) -> JoinHandle<()>,
) -> Result<(), SpawnError>
pub fn spawn_thread_to_runtime( self, runtime: Runtime, spawn_fn: impl FnOnce(Box<dyn FnOnce() + Send>) -> JoinHandle<()>, ) -> Result<(), SpawnError>
Like Self::spawn, but instead of spawning within the current Tokio runtime, spawns within a set Tokio runtime and then runs a thread that calls block_on on that runtime.
If your configuration is standard, use Profiler::spawn_thread.
If you want to be able to stop the resulting profiler, use Profiler::spawn_controllable_thread_to_runtime.
spawn_fn should be std::thread::spawn, or some function that behaves like it (to
allow for configuring thread properties, for example thread names).
This is to be used when your program does not have a “main” Tokio runtime already set up.
§Example
This example uses ProfilerBuilder::with_local_reporter which reports the profiles to a directory. It works with any other Reporter using ProfilerBuilder::with_reporter.
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()?;
let profiler = ProfilerBuilder::default()
.with_local_reporter("/tmp/profiles")
.build();
profiler.spawn_thread_to_runtime(
rt,
|t| {
std::thread::Builder::new()
.name("asprof-agent".to_owned())
.spawn(t)
.expect("thread name contains nuls")
}
)?;Sourcepub fn spawn_thread(self) -> Result<(), SpawnThreadError>
pub fn spawn_thread(self) -> Result<(), SpawnThreadError>
Like Self::spawn, but instead of spawning within the current Tokio runtime, spawns within a new Tokio runtime and then runs a thread that calls block_on on that runtime, setting up the runtime by itself.
If your configuration is less standard, use Profiler::spawn_thread_to_runtime. Calling Profiler::spawn_thread is equivalent to calling Profiler::spawn_thread_to_runtime with the following:
- a current thread runtime with background worker threads (these exist for blocking IO) named “asprof-worker”
- a controller thread (the “main” thread of the runtime) named “asprof-agent”
If you want to be able to stop the resulting profiler, use Profiler::spawn_controllable_thread_to_runtime.
This is to be used when your program does not have a “main” Tokio runtime already set up.
§Example
This example uses ProfilerBuilder::with_local_reporter which reports the profiles to a directory. It works with any other Reporter using ProfilerBuilder::with_reporter.
let profiler = ProfilerBuilder::default()
.with_local_reporter("/tmp/profiles")
.build();
profiler.spawn_thread()?;Sourcepub fn spawn_controllable(self) -> Result<RunningProfiler, SpawnError>
pub fn spawn_controllable(self) -> Result<RunningProfiler, SpawnError>
Like Self::spawn, but returns a RunningProfiler that allows for controlling (currently only stopping) the profiler.
This allows for changing the configuration of the profiler at runtime, by stopping it and then starting a new Profiler with a new configuration. It also allows for stopping profiling in case the profiler is suspected to cause operational issues.
Dropping the returned RunningProfiler will cause the profiler to quit, so if your application doen’t need to change the profiler’s configuration at runtime, it will be easier to use Profiler::spawn.
This function will fail if it is unable to start async-profiler, for example
if it can’t find or load libasyncProfiler.so.
§Tokio Runtime
This function must be run within a Tokio runtime, otherwise it will panic. If
your application does not have a main Tokio runtime, see
Profiler::spawn_controllable_thread_to_runtime.
§Example
This example uses ProfilerBuilder::with_local_reporter which reports the profiles to a directory. It works with any other Reporter using ProfilerBuilder::with_reporter.
let profiler = ProfilerBuilder::default()
.with_local_reporter("/tmp/profiles")
.build();
let profiler = profiler.spawn_controllable()?;
// [insert your signaling/monitoring mechanism to have a request to disable
// profiling in case of a problem]
let got_request_to_disable_profiling = async move {
// ...
};
// spawn a task that will disable profiling if requested
tokio::task::spawn(async move {
if got_request_to_disable_profiling.await {
profiler.stop().await;
}
});Sourcepub fn spawn_controllable_thread_to_runtime(
self,
runtime: Runtime,
spawn_fn: impl FnOnce(Box<dyn FnOnce() + Send>) -> JoinHandle<()>,
) -> Result<RunningProfilerThread, SpawnError>
pub fn spawn_controllable_thread_to_runtime( self, runtime: Runtime, spawn_fn: impl FnOnce(Box<dyn FnOnce() + Send>) -> JoinHandle<()>, ) -> Result<RunningProfilerThread, SpawnError>
Like Self::spawn_controllable, but instead of spawning within the current Tokio runtime, spawns within a set Tokio runtime and then runs a thread that calls block_on on that runtime.
spawn_fn should be std::thread::spawn, or some function that behaves like it (to
allow for configuring thread properties, for example thread names).
This is to be used when your program does not have a “main” Tokio runtime already set up.
§Example
This example uses ProfilerBuilder::with_local_reporter which reports the profiles to a directory. It works with any other Reporter using ProfilerBuilder::with_reporter.
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()?;
let profiler = ProfilerBuilder::default()
.with_local_reporter("/tmp/profiles")
.build();
let profiler = profiler.spawn_controllable_thread_to_runtime(
rt,
|t| {
std::thread::Builder::new()
.name("asprof-agent".to_owned())
.spawn(t)
.expect("thread name contains nuls")
}
)?;
// spawn a task that will disable profiling if requested
std::thread::spawn(move || {
if got_request_to_disable_profiling() {
profiler.stop();
}
});Auto Trait Implementations§
impl Freeze for Profiler
impl !RefUnwindSafe for Profiler
impl Send for Profiler
impl Sync for Profiler
impl Unpin for Profiler
impl !UnwindSafe for Profiler
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more