mongodb 2.8.2

The official MongoDB driver for Rust
Documentation
<!DOCTYPE HTML>
<html lang="en" class="light" dir="ltr">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>Performance - MongoDB Rust Driver</title>


        <!-- Custom HTML head -->
        
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff">

        <link rel="icon" href="favicon.svg">
        <link rel="shortcut icon" href="favicon.png">
        <link rel="stylesheet" href="css/variables.css">
        <link rel="stylesheet" href="css/general.css">
        <link rel="stylesheet" href="css/chrome.css">
        <link rel="stylesheet" href="css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="highlight.css">
        <link rel="stylesheet" href="tomorrow-night.css">
        <link rel="stylesheet" href="ayu-highlight.css">

        <!-- Custom theme stylesheets -->

    </head>
    <body class="sidebar-visible no-js">
    <div id="body-container">
        <!-- Provide site root to javascript -->
        <script>
            var path_to_root = "";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script>
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script>
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('light')
            html.classList.add(theme);
            var body = document.querySelector('body');
            body.classList.remove('no-js')
            body.classList.add('js');
        </script>

        <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">

        <!-- Hide / unhide sidebar before it is displayed -->
        <script>
            var body = document.querySelector('body');
            var sidebar = null;
            var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            } else {
                sidebar = 'hidden';
            }
            sidebar_toggle.checked = sidebar === 'visible';
            body.classList.remove('sidebar-visible');
            body.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded "><a href="index.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li class="chapter-item expanded "><a href="installation_features.html"><strong aria-hidden="true">2.</strong> Installation and Features</a></li><li class="chapter-item expanded "><a href="connecting.html"><strong aria-hidden="true">3.</strong> Connecting to the Database</a></li><li class="chapter-item expanded "><a href="reading.html"><strong aria-hidden="true">4.</strong> Reading From the Database</a></li><li class="chapter-item expanded "><div><strong aria-hidden="true">5.</strong> Writing To the Database</div></li><li class="chapter-item expanded "><a href="performance.html" class="active"><strong aria-hidden="true">6.</strong> Performance</a></li><li class="chapter-item expanded "><div><strong aria-hidden="true">7.</strong> Serde Integration</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">8.</strong> Sessions and Transactions</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">9.</strong> Change Streams</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">10.</strong> Monitoring</div></li><li class="chapter-item expanded "><a href="tracing.html"><strong aria-hidden="true">11.</strong> Tracing and Logging</a></li><li class="chapter-item expanded "><a href="web_framework_examples.html"><strong aria-hidden="true">12.</strong> Web Framework Examples</a></li><li class="chapter-item expanded "><a href="encryption.html"><strong aria-hidden="true">13.</strong> Encryption</a></li><li class="chapter-item expanded affix "><li class="part-title">Development</li><li class="chapter-item expanded "><div><strong aria-hidden="true">14.</strong> Writing Tests</div></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <!-- Track and set sidebar scroll position -->
        <script>
            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
            sidebarScrollbox.addEventListener('click', function(e) {
                if (e.target.tagName === 'A') {
                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
                }
            }, { passive: true });
            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
            sessionStorage.removeItem('sidebar-scroll');
            if (sidebarScrollTop) {
                // preserve sidebar scroll position when navigating via links within sidebar
                sidebarScrollbox.scrollTop = sidebarScrollTop;
            } else {
                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
                var activeSection = document.querySelector('#sidebar .active');
                if (activeSection) {
                    activeSection.scrollIntoView({ block: 'center' });
                }
            }
        </script>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky">
                    <div class="left-buttons">
                        <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </label>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title">MongoDB Rust Driver</h1>

                    <div class="right-buttons">
                        <a href="print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script>
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="performance"><a class="header" href="#performance">Performance</a></h1>
<h2 id="client-best-practices"><a class="header" href="#client-best-practices"><code>Client</code> Best Practices</a></h2>
<p>The <a href="https://docs.rs/mongodb/latest/mongodb/struct.Client.html"><code>Client</code></a> handles many aspects of database connection behind the scenes that can require manual management for other database drivers; it discovers server topology, monitors it for any changes, and maintains an internal connection pool.  This has implications for how a <code>Client</code> should be used for best performance.</p>
<h3 id="lifetime"><a class="header" href="#lifetime">Lifetime</a></h3>
<p>A <code>Client</code> should be as long-lived as possible.  Establishing a new <code>Client</code> is relatively slow and resource-intensive, so ideally that should only be done once at application startup.  Because <code>Client</code> is implemented using an internal <a href="https://doc.rust-lang.org/std/sync/struct.Arc.html"><code>Arc</code></a>, it can safely be shared across threads or tasks, and <code>clone</code>ing it to pass to new contexts is extremely cheap.</p>
<pre><pre class="playground"><code class="language-rust no_run edition2021"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span><span class="boring">extern crate mongodb;
</span><span class="boring">use mongodb::Client;
</span><span class="boring">use std::error::Error;
</span>// This will be very slow because it's constructing and tearing down a `Client`
// with every request.
async fn handle_request_bad() -&gt; Result&lt;(), Box&lt;dyn Error&gt;&gt; {
    let client = Client::with_uri_str(&quot;mongodb://example.com&quot;).await?;
    // Do something with the client
    Ok(())
}

// This will be much faster.
async fn handle_request_good(client: &amp;Client) -&gt; Result&lt;(), Box&lt;dyn Error&gt;&gt; {
    // Do something with the client
    Ok(())
}
<span class="boring">}</span></code></pre></pre>
<p>This is especially noticeable when using a framework that provides connection pooling; because <code>Client</code> does its own pooling internally, attempting to maintain a pool of <code>Client</code>s will (somewhat counter-intuitively) result in worse performance than using a single one.</p>
<h3 id="runtime"><a class="header" href="#runtime">Runtime</a></h3>
<p>A <code>Client</code> is implicitly bound to the instance of the <code>tokio</code> or <code>async-std</code> runtime in which it was created.  Attempting to execute operations on a different runtime instance will cause incorrect behavior and unpredictable failures.  This is easy to accidentally invoke when testing, as the <code>tokio::test</code> or <code>async_std::test</code> helper macros create a new runtime for each test.</p>
<pre><pre class="playground"><code class="language-rust no_run edition2021"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span><span class="boring">extern crate mongodb;
</span><span class="boring">extern crate once_cell;
</span><span class="boring">extern crate tokio;
</span><span class="boring">use mongodb::Client;
</span><span class="boring">use std::error::Error;
</span>use tokio::runtime::Runtime;
use once_cell::sync::Lazy;

static CLIENT: Lazy&lt;Client&gt; = Lazy::new(|| {
    let rt = Runtime::new().unwrap();
    rt.block_on(async {
        Client::with_uri_str(&quot;mongodb://example.com&quot;).await.unwrap()
    })
});

// This will inconsistently fail.
#[tokio::test]
async fn test_list_dbs() -&gt; Result&lt;(), Box&lt;dyn Error&gt;&gt; {
    CLIENT.list_database_names(None, None).await?;
    Ok(())
}
<span class="boring">}</span></code></pre></pre>
<p>To work around this issue, either create a new <code>Client</code> for every async test, or bundle the <code>Runtime</code> along with the client and don't use the test helper macros.</p>
<pre><pre class="playground"><code class="language-rust no_run edition2021"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span><span class="boring">extern crate mongodb;
</span><span class="boring">extern crate once_cell;
</span><span class="boring">extern crate tokio;
</span><span class="boring">use mongodb::Client;
</span><span class="boring">use std::error::Error;
</span>use tokio::runtime::Runtime;
use once_cell::sync::Lazy;

static CLIENT_RUNTIME: Lazy&lt;(Client, Runtime)&gt; = Lazy::new(|| {
    let rt = Runtime::new().unwrap();
    let client = rt.block_on(async {
        Client::with_uri_str(&quot;mongodb://example.com&quot;).await.unwrap()
    });
    (client, rt)
});

#[test]
fn test_list_dbs() -&gt; Result&lt;(), Box&lt;dyn Error&gt;&gt; {
    let (client, rt) = &amp;*CLIENT_RUNTIME;
    rt.block_on(async {
        client.list_database_names(None, None).await
    })?;
    Ok(())
}
<span class="boring">}</span></code></pre></pre>
<p>or</p>
<pre><pre class="playground"><code class="language-rust no_run edition2021"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span><span class="boring">extern crate mongodb;
</span><span class="boring">extern crate tokio;
</span><span class="boring">use mongodb::Client;
</span><span class="boring">use std::error::Error;
</span>#[tokio::test]
async fn test_list_dbs() -&gt; Result&lt;(), Box&lt;dyn Error&gt;&gt; {
    let client = Client::with_uri_str(&quot;mongodb://example.com&quot;).await?;
    CLIENT.list_database_names(None, None).await?;
    Ok(())
}
<span class="boring">}</span></code></pre></pre>
<h2 id="parallelism"><a class="header" href="#parallelism">Parallelism</a></h2>
<p>Where data operations are naturally parallelizable, spawning many asynchronous tasks that use the driver concurrently is often the best way to achieve maximum performance, as the driver is designed to work well in such situations.</p>
<pre><pre class="playground"><code class="language-rust no_run edition2021"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span><span class="boring">extern crate mongodb;
</span><span class="boring">extern crate tokio;
</span><span class="boring">use mongodb::{bson::Document, Client, error::Result};
</span><span class="boring">use tokio::task;
</span><span class="boring">
</span><span class="boring">async fn start_workers() -&gt; Result&lt;()&gt; {
</span>let client = Client::with_uri_str(&quot;mongodb://example.com&quot;).await?;

for i in 0..5 {
    let client_ref = client.clone();

    task::spawn(async move {
        let collection = client_ref.database(&quot;items&quot;).collection::&lt;Document&gt;(&amp;format!(&quot;coll{}&quot;, i));

        // Do something with the collection
    });
}
<span class="boring">
</span><span class="boring">Ok(())
</span><span class="boring">}
</span><span class="boring">}</span></code></pre></pre>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                            <a rel="prev" href="reading.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>

                            <a rel="next prefetch" href="tracing.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                    <a rel="prev" href="reading.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>

                    <a rel="next prefetch" href="tracing.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
            </nav>

        </div>

        <!-- Livereload script (if served using the cli tool) -->
        <script>
            const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
            const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
            const socket = new WebSocket(wsAddress);
            socket.onmessage = function (event) {
                if (event.data === "reload") {
                    socket.close();
                    location.reload();
                }
            };

            window.onbeforeunload = function() {
                socket.close();
            }
        </script>



        <script>
            window.playground_copyable = true;
        </script>


        <script src="elasticlunr.min.js"></script>
        <script src="mark.min.js"></script>
        <script src="searcher.js"></script>

        <script src="clipboard.min.js"></script>
        <script src="highlight.js"></script>
        <script src="book.js"></script>

        <!-- Custom JS scripts -->


    </div>
    </body>
</html>