public inbox for pbs-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Max Carrara <m.carrara@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH v2 pxar 1/2] Add `compare-read.rs` to examples and drop feature `async-examples`
Date: Mon, 31 Jul 2023 15:34:03 +0200	[thread overview]
Message-ID: <20230731133404.859756-1-m.carrara@proxmox.com> (raw)

`compare-read.rs` may be used to compare read speeds between pxar
accessors and decoders, both synchronous and asynchronous versions.

The `async-examples` feature is dropped in favour of declaring
`[dev-dependencies]` in `Cargo.toml`.

Signed-off-by: Max Carrara <m.carrara@proxmox.com>
---
 Changes v1 --> v2:
  * Remove addition of `tokio/io-util` as dependency
  * Add example `compare-read`
  * Remove feature `async-example` in favour of `[dev-dependencies]`

 Cargo.toml               |  20 +++---
 examples/compare-read.rs | 150 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 162 insertions(+), 8 deletions(-)
 create mode 100644 examples/compare-read.rs

diff --git a/Cargo.toml b/Cargo.toml
index d120e70..8669e30 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,7 +15,10 @@ exclude = [
 [[example]]
 name = "apxar"
 path = "examples/apxar.rs"
-required-features = [ "async-example" ]
+
+[[example]]
+name = "compare-read"
+path = "examples/compare-read.rs"

 [[example]]
 name = "pxarcmd"
@@ -47,6 +50,14 @@ siphasher = "0.3"

 tokio = { version = "1.0", optional = true, default-features = false }

+[dev-dependencies]
+anyhow = "1.0"
+tokio = { version = "1.0", default-features = false, features = [
+    "fs",
+    "macros",
+    "rt-multi-thread"
+] }
+
 [target.'cfg(target_os = "linux")'.dependencies]
 libc = "0.2"

@@ -57,11 +68,4 @@ tokio-fs = [ "tokio-io", "tokio/fs" ]

 full = [ "tokio-fs"]

-async-example = [
-    "tokio-io",
-    "tokio-fs",
-    "tokio/rt-multi-thread",
-    "tokio/macros",
-]
-
 test-harness = []
diff --git a/examples/compare-read.rs b/examples/compare-read.rs
new file mode 100644
index 0000000..c908077
--- /dev/null
+++ b/examples/compare-read.rs
@@ -0,0 +1,150 @@
+//! # Compare Read Speeds of Accessors and Decoders
+//!
+//! This example is used to compare read speeds between:
+//!
+//! * [`aio::Accessor`][pxar::accessor::aio::Accessor]
+//! * [`sync::Accessor`][pxar::accessor::sync::Accessor]
+//! * [`aio::Decoder`][pxar::decoder::aio::Decoder]
+//! * [`sync::Decoder`][pxar::decoder::sync::Decoder]
+//!
+//! ## Usage
+//!
+//! You may run this example directly on a PXAR archive:
+//!
+//! ```bash
+//! cargo run -q --example compare-read [FILE_PATH]
+//! cargo run -q --release --example compare-read [FILE_PATH]
+//! ```
+
+use std::ffi::OsStr;
+use std::future::Future;
+use std::time::Duration;
+
+use anyhow::{Context, Result};
+use pxar::accessor::aio::Accessor as AioAccessor;
+use pxar::accessor::sync::Accessor as SyncAccessor;
+use pxar::decoder::aio::Decoder as AioDecoder;
+use pxar::decoder::sync::Decoder as SyncDecoder;
+
+async fn read_with_decoder(file: &OsStr) -> Result<()> {
+    let file = tokio::fs::File::open(file)
+        .await
+        .context("failed to open file")?;
+
+    let mut reader = AioDecoder::from_tokio(file)
+        .await
+        .context("failed to open pxar archive contents")?;
+
+    let mut entries = vec![];
+
+    while let Some(entry) = reader.next().await {
+        let entry = entry.context("failed to parse entry")?;
+
+        entries.push(entry);
+    }
+
+    Ok(())
+}
+
+async fn read_with_decoder_sync(file: &OsStr) -> Result<()> {
+    let file = std::fs::File::open(file).context("failed to open file")?;
+
+    let reader = SyncDecoder::from_std(file).context("failed to open pxar archive contents")?;
+
+    let mut entries = vec![];
+
+    for entry in reader {
+        let entry = entry.context("failed to parse entry")?;
+        entries.push(entry);
+    }
+
+    Ok(())
+}
+
+async fn read_with_accessor(file: &OsStr) -> Result<()> {
+    let accessor = AioAccessor::open(file)
+        .await
+        .context("failed to open pxar archive contents")?;
+
+    let dir = accessor.open_root_ref().await?;
+    let mut decode_full = dir.decode_full().await?;
+
+    let mut entries = vec![];
+
+    while let Some(entry) = decode_full.next().await {
+        let entry = entry.context("failed to parse entry")?;
+
+        entries.push(entry);
+    }
+
+    Ok(())
+}
+
+async fn read_with_accessor_sync(file: &OsStr) -> Result<()> {
+    let accessor = SyncAccessor::open(file).context("failed to open pxar archive contents")?;
+
+    let dir = accessor.open_root_ref()?;
+    let decode_full = dir.decode_full()?;
+
+    let mut entries = vec![];
+
+    for entry in decode_full {
+        let entry = entry.context("failed to parse entry")?;
+
+        entries.push(entry);
+    }
+
+    Ok(())
+}
+
+async fn measure_duration<F, R>(future: F) -> (R, Duration)
+where
+    F: Future<Output = R>,
+    R: Send + 'static,
+{
+    use std::time::Instant;
+    let start = Instant::now();
+    let return_value = future.await;
+    let elapsed = start.elapsed();
+
+    (return_value, elapsed)
+}
+
+async fn run_reads(file: &OsStr) -> Result<()> {
+    let (result, elapsed) = measure_duration(read_with_decoder(&file)).await;
+    println!("With aio::Decoder:   {result:?} (elapsed: {elapsed:#?})");
+
+    let (result, elapsed) = measure_duration(read_with_decoder_sync(&file)).await;
+    println!("With sync::Decoder:  {result:?} (elapsed: {elapsed:#?})");
+
+    let (result, elapsed) = measure_duration(read_with_accessor(&file)).await;
+    println!("With aio::Accessor:  {result:?} (elapsed: {elapsed:#?})");
+
+    let (result, elapsed) = measure_duration(read_with_accessor_sync(&file)).await;
+    println!("With sync::Accessor: {result:?} (elapsed: {elapsed:#?})");
+
+    Ok(())
+}
+
+#[tokio::main]
+async fn main() -> Result<()> {
+    let mode = if cfg!(debug_assertions) {
+        "debug"
+    } else {
+        "release"
+    };
+
+    println!("PXAR Read Performance Comparison");
+    println!("Running in mode: {mode}\n");
+
+    let mut args = std::env::args_os().skip(1);
+
+    let file = args.next().context("expected file name")?;
+    println!("First pass:");
+    run_reads(&file).await?;
+
+    println!("\nSecond pass:");
+    run_reads(&file).await?;
+
+    Ok(())
+}
--
2.39.2





             reply	other threads:[~2023-07-31 13:34 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-31 13:34 Max Carrara [this message]
2023-07-31 13:34 ` [pbs-devel] [PATCH v2 pxar 2/2] decoder: aio: improve performance of async file reads Max Carrara
2023-07-31 14:57   ` Fabian Grünbichler
2023-07-31 15:14     ` Max Carrara
2023-08-04 11:32   ` Wolfgang Bumiller
2023-07-31 14:58 ` [pbs-devel] [PATCH v2 pxar 1/2] Add `compare-read.rs` to examples and drop feature `async-examples` Fabian Grünbichler

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230731133404.859756-1-m.carrara@proxmox.com \
    --to=m.carrara@proxmox.com \
    --cc=pbs-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal