Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  dump.rs

  Sprache: Rust
 

//! Snapshots of runtime state.
//!
//! See [`Handle::dump`][crate::runtime::Handle::dump].

use crate::task::Id;
use std::{fmt, future::Future, path::Path};

pub use crate::runtime::task::trace::{trace_with, Root, TraceMeta};

/// A snapshot of a runtime's state.
///
/// See [`Handle::dump`][crate::runtime::Handle::dump].
#[derive(Debug)]
pub struct Dump {
    tasks: Tasks,
}

/// Snapshots of tasks.
///
/// See [`Handle::dump`][crate::runtime::Handle::dump].
#[derive(Debug)]
pub struct Tasks {
    tasks: Vec<Task>,
}

/// A snapshot of a task.
///
/// See [`Handle::dump`][crate::runtime::Handle::dump].
#[derive(Debug)]
pub struct Task {
    id: Id,
    trace: Trace,
}

/// Represents an address that should not be dereferenced.
///
/// This type exists to get the auto traits correct, the public API
/// uses raw pointers to make life easier for users.
#[derive(Copy, Clone, Debug)]
struct Address(*mut std::ffi::c_void);

// Safe since Address should not be dereferenced
unsafe impl Send for Address {}
unsafe impl Sync for Address {}

/// A backtrace symbol.
///
/// This struct provides accessors for backtrace symbols, similar to [`backtrace::BacktraceSymbol`].
#[derive(Clone, Debug)]
pub struct BacktraceSymbol {
    name: Option<Box<[u8]>>,
    name_demangled: Option<Box<str>>,
    addr: Option<Address>,
    filename: Option<std::path::PathBuf>,
    lineno: Option<u32>,
    colno: Option<u32>,
}

impl BacktraceSymbol {
    pub(cratefn from_backtrace_symbol(sym: &backtrace::BacktraceSymbol) -> Self {
        let name = sym.name();
        Self {
            name: name.as_ref().map(|name| name.as_bytes().into()),
            name_demangled: name.map(|name| format!("{name}").into()),
            addr: sym.addr().map(Address),
            filename: sym.filename().map(From::from),
            lineno: sym.lineno(),
            colno: sym.colno(),
        }
    }

    /// Return the raw name of the symbol.
    pub fn name_raw(&self) -> Option<&[u8]> {
        self.name.as_deref()
    }

    /// Return the demangled name of the symbol.
    pub fn name_demangled(&self) -> Option<&str> {
        self.name_demangled.as_deref()
    }

    /// Returns the starting address of this symbol.
    pub fn addr(&self) -> Option<*mut std::ffi::c_void> {
        self.addr.map(|addr| addr.0)
    }

    /// Returns the file name where this function was defined. If debuginfo
    /// is missing, this is likely to return None.
    pub fn filename(&self) -> Option<&Path> {
        self.filename.as_deref()
    }

    /// Returns the line number for where this symbol is currently executing.
    ///
    /// If debuginfo is missing, this is likely to return `None`.
    pub fn lineno(&self) -> Option<u32> {
        self.lineno
    }

    /// Returns the column number for where this symbol is currently executing.
    ///
    /// If debuginfo is missing, this is likely to return `None`.
    pub fn colno(&self) -> Option<u32> {
        self.colno
    }
}

/// A backtrace frame.
///
/// This struct represents one stack frame in a captured backtrace, similar to [`backtrace::BacktraceFrame`].
#[derive(Clone, Debug)]
pub struct BacktraceFrame {
    ip: Address,
    symbol_address: Address,
    symbols: Box<[BacktraceSymbol]>,
}

impl BacktraceFrame {
    pub(cratefn from_resolved_backtrace_frame(frame: &backtrace::BacktraceFrame) -> Self {
        Self {
            ip: Address(frame.ip()),
            symbol_address: Address(frame.symbol_address()),
            symbols: frame
                .symbols()
                .iter()
                .map(BacktraceSymbol::from_backtrace_symbol)
                .collect(),
        }
    }

    /// Return the instruction pointer of this frame.
    ///
    /// See the ABI docs for your platform for the exact meaning.
    pub fn ip(&self) -> *mut std::ffi::c_void {
        self.ip.0
    }

    /// Returns the starting symbol address of the frame of this function.
    pub fn symbol_address(&self) -> *mut std::ffi::c_void {
        self.symbol_address.0
    }

    /// Return an iterator over the symbols of this backtrace frame.
    ///
    /// Due to inlining, it is possible for there to be multiple [`BacktraceSymbol`] items relating
    /// to a single frame. The first symbol listed is the "innermost function",
    /// whereas the last symbol is the outermost (last caller).
    pub fn symbols(&self) -> impl Iterator<Item = &BacktraceSymbol> {
        self.symbols.iter()
    }
}

/// A captured backtrace.
///
/// This struct provides access to each backtrace frame, similar to [`backtrace::Backtrace`].
#[derive(Clone, Debug)]
pub struct Backtrace {
    frames: Box<[BacktraceFrame]>,
}

impl Backtrace {
    /// Return the frames in this backtrace, innermost (in a task dump,
    /// likely to be a leaf future's poll function) first.
    pub fn frames(&self) -> impl Iterator<Item = &BacktraceFrame> {
        self.frames.iter()
    }
}

/// An execution trace of a task's last poll.
///
/// <div class="warning">
///
/// Resolving a backtrace, either via the [`Display`][std::fmt::Display] impl or via
/// [`resolve_backtraces`][Trace::resolve_backtraces], parses debuginfo, which is
/// possibly a CPU-expensive operation that can take a platform-specific but
/// long time to run - often over 100 milliseconds, especially if the current
/// process's binary is big. In some cases, the platform might internally cache some of the
/// debuginfo, so successive calls to `resolve_backtraces` might be faster than
/// the first call, but all guarantees are platform-dependent.
///
/// To avoid blocking the runtime, it is recommended
/// that you resolve backtraces inside of a [`spawn_blocking()`][crate::task::spawn_blocking]
/// and to have some concurrency-limiting mechanism to avoid unexpected performance impact.
/// </div>
///
/// See [`Handle::dump`][crate::runtime::Handle::dump].
#[derive(Debug)]
pub struct Trace {
    inner: super::task::trace::Trace,
}

impl Trace {
    /// Resolve and return a list of backtraces that are involved in polls in this trace.
    ///
    /// The exact backtraces included here are unstable and might change in the future,
    /// but you can expect one [`Backtrace`] for every call to
    /// [`poll`] to a bottom-level Tokio future - so if something like [`join!`] is
    /// used, there will be a backtrace for each future in the join.
    ///
    /// [`poll`]: std::future::Future::poll
    /// [`join!`]: macro@join
    pub fn resolve_backtraces(&self) -> Vec<Backtrace> {
        self.inner
            .backtraces()
            .iter()
            .map(|backtrace| {
                let mut backtrace = backtrace::Backtrace::from(backtrace.clone());
                backtrace.resolve();
                Backtrace {
                    frames: backtrace
                        .frames()
                        .iter()
                        .map(BacktraceFrame::from_resolved_backtrace_frame)
                        .collect(),
                }
            })
            .collect()
    }

    /// Runs the function `f` in tracing mode, and returns its result along with the resulting [`Trace`].
    ///
    /// This is normally called with `f` being the poll function of a future, and will give you a backtrace
    /// that tells you what that one future is doing.
    ///
    /// Use [`Handle::dump`] instead if you want to know what *all the tasks* in your program are doing.
    /// Also see [`Handle::dump`] for more documentation about dumps, but unlike [`Handle::dump`], this function
    /// should not be much slower than calling `f` directly.
    ///
    /// Due to the way tracing is implemented, Tokio leaf futures will usually, instead of doing their
    /// actual work, do the equivalent of a `yield_now` (returning a `Poll::Pending` and scheduling the
    /// current context for execution), which means forward progress will probably not happen unless
    /// you eventually call your future outside of `capture`.
    ///
    /// [`Handle::dump`]: crate::runtime::Handle::dump
    ///
    /// Example usage:
    /// ```
    /// use std::future::Future;
    /// use std::task::Poll;
    /// use tokio::runtime::dump::Trace;
    ///
    /// # async fn test_fn() {
    /// // some future
    /// let mut test_future = std::pin::pin!(async move { tokio::task::yield_now().await; 0 });
    ///
    /// // trace it once, see what it's doing
    /// let (trace, res) = Trace::root(std::future::poll_fn(|cx| {
    ///     let (res, trace) = Trace::capture(|| test_future.as_mut().poll(cx));
    ///     Poll::Ready((trace, res))
    /// })).await;
    ///
    /// // await it to let it finish, outside of a `capture`
    /// let output = match res {
    ///    Poll::Ready(output) => output,
    ///    Poll::Pending => test_future.await,
    /// };
    ///
    /// println!("{trace}");
    /// # }
    /// ```
    ///
    /// ### Nested calls
    ///
    /// Nested calls to `capture` might return partial traces, but will not do any other undesirable behavior (for
    /// example, they will not panic).
    pub fn capture<F, R>(f: F) -> (R, Trace)
    where
        F: FnOnce() -> R,
    {
        let (res, trace) = super::task::trace::Trace::capture(f);
        (res, Trace { inner: trace })
    }

    /// Create a root for stack traces captured using [`Trace::capture`]. Stack frames above
    /// the root will not be captured.
    ///
    /// Nesting multiple [`Root`] futures is fine. Captures will stop at the first root. Not having
    /// a [`Root`] is fine as well, but there is no guarantee on where the capture will stop.
    pub fn root<F>(f: F) -> Root<F>
    where
        F: Future,
    {
        crate::runtime::task::trace::Trace::root(f)
    }
}

impl Dump {
    pub(cratefn new(tasks: Vec<Task>) -> Self {
        Self {
            tasks: Tasks { tasks },
        }
    }

    /// Tasks in this snapshot.
    pub fn tasks(&self) -> &Tasks {
        &self.tasks
    }
}

impl Tasks {
    /// Iterate over tasks.
    pub fn iter(&self) -> impl Iterator<Item = &Task> {
        self.tasks.iter()
    }
}

impl Task {
    pub(cratefn new(id: Id, trace: super::task::trace::Trace) -> Self {
        Self {
            id,
            trace: Trace { inner: trace },
        }
    }

    /// Returns a [task ID] that uniquely identifies this task relative to other
    /// tasks spawned at the time of the dump.
    ///
    /// **Note**: This is an [unstable API][unstable]. The public API of this type
    /// may break in 1.x releases. See [the documentation on unstable
    /// features][unstable] for details.
    ///
    /// [task ID]: crate::task::Id
    /// [unstable]: crate#unstable-features
    #[cfg(tokio_unstable)]
    #[cfg_attr(docsrs, doc(cfg(tokio_unstable)))]
    pub fn id(&self) -> Id {
        self.id
    }

    /// A trace of this task's state.
    pub fn trace(&self) -> &Trace {
        &self.trace
    }
}

impl fmt::Display for Trace {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.inner.fmt(f)
    }
}

Messung V0.5 in Prozent
C=79 H=85 G=81

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002