mirror of https://github.com/zkat/cacache-rs.git
feat(mmap): new feature for mmap-based optimization
This commit is contained in:
parent
81bc84b33d
commit
ba036ab92a
|
|
@ -16,7 +16,7 @@ digest = "0.10.6"
|
||||||
either = "1.6.1"
|
either = "1.6.1"
|
||||||
futures = "0.3.17"
|
futures = "0.3.17"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
memmap2 = "0.5.8"
|
memmap2 = { version = "0.5.8", optional = true }
|
||||||
miette = "5.7.0"
|
miette = "5.7.0"
|
||||||
reflink = "0.1.3"
|
reflink = "0.1.3"
|
||||||
serde = "1.0.130"
|
serde = "1.0.130"
|
||||||
|
|
@ -53,6 +53,7 @@ name = "benchmarks"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["async-std"]
|
default = ["async-std", "mmap"]
|
||||||
|
mmap = ["memmap2"]
|
||||||
link_to = []
|
link_to = []
|
||||||
tokio-runtime = ["tokio", "tokio-stream"]
|
tokio-runtime = ["tokio", "tokio-stream"]
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use std::sync::Mutex;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
|
#[cfg(feature = "mmap")]
|
||||||
use memmap2::MmapMut;
|
use memmap2::MmapMut;
|
||||||
use ssri::{Algorithm, Integrity, IntegrityOpts};
|
use ssri::{Algorithm, Integrity, IntegrityOpts};
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
|
@ -14,8 +15,23 @@ use crate::async_lib::{AsyncWrite, JoinHandle};
|
||||||
use crate::content::path;
|
use crate::content::path;
|
||||||
use crate::errors::{IoErrorExt, Result};
|
use crate::errors::{IoErrorExt, Result};
|
||||||
|
|
||||||
|
#[cfg(feature = "mmap")]
|
||||||
pub const MAX_MMAP_SIZE: usize = 1024 * 1024;
|
pub const MAX_MMAP_SIZE: usize = 1024 * 1024;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "mmap"))]
|
||||||
|
struct MmapMut;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "mmap"))]
|
||||||
|
impl MmapMut {
|
||||||
|
fn flush_async(&self) -> std::io::Result<()> {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn copy_from_slice(&self, _: &[u8]) {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Writer {
|
pub struct Writer {
|
||||||
cache: PathBuf,
|
cache: PathBuf,
|
||||||
builder: IntegrityOpts,
|
builder: IntegrityOpts,
|
||||||
|
|
@ -44,24 +60,7 @@ impl Writer {
|
||||||
tmp_path_clone.display()
|
tmp_path_clone.display()
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let mmap = if let Some(size) = size {
|
let mmap = make_mmap(&mut tmpfile, size)?;
|
||||||
if size <= MAX_MMAP_SIZE {
|
|
||||||
tmpfile
|
|
||||||
.as_file_mut()
|
|
||||||
.set_len(size as u64)
|
|
||||||
.with_context(|| {
|
|
||||||
format!(
|
|
||||||
"Failed to configure file length for temp file at {}",
|
|
||||||
tmpfile.path().display()
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
unsafe { MmapMut::map_mut(tmpfile.as_file()).ok() }
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
Ok(Writer {
|
Ok(Writer {
|
||||||
cache: cache_path,
|
cache: cache_path,
|
||||||
builder: IntegrityOpts::new().algorithm(algo),
|
builder: IntegrityOpts::new().algorithm(algo),
|
||||||
|
|
@ -162,24 +161,7 @@ impl AsyncWriter {
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
let mut tmpfile = crate::async_lib::create_named_tempfile(tmp_path).await?;
|
let mut tmpfile = crate::async_lib::create_named_tempfile(tmp_path).await?;
|
||||||
let mmap = if let Some(size) = size {
|
let mmap = make_mmap(&mut tmpfile, size)?;
|
||||||
if size <= MAX_MMAP_SIZE {
|
|
||||||
tmpfile
|
|
||||||
.as_file_mut()
|
|
||||||
.set_len(size as u64)
|
|
||||||
.with_context(|| {
|
|
||||||
format!(
|
|
||||||
"Failed to configure file length for temp file at {}",
|
|
||||||
tmpfile.path().display()
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
unsafe { MmapMut::map_mut(tmpfile.as_file()).ok() }
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
Ok(AsyncWriter(Mutex::new(State::Idle(Some(Inner {
|
Ok(AsyncWriter(Mutex::new(State::Idle(Some(Inner {
|
||||||
cache: cache_path,
|
cache: cache_path,
|
||||||
builder: IntegrityOpts::new().algorithm(algo),
|
builder: IntegrityOpts::new().algorithm(algo),
|
||||||
|
|
@ -428,6 +410,29 @@ impl AsyncWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "mmap")]
|
||||||
|
fn make_mmap(tmpfile: &mut NamedTempFile, size: Option<usize>) -> Result<Option<MmapMut>> {
|
||||||
|
if let Some(size @ 0..=MAX_MMAP_SIZE) = size {
|
||||||
|
tmpfile
|
||||||
|
.as_file_mut()
|
||||||
|
.set_len(size as u64)
|
||||||
|
.with_context(|| {
|
||||||
|
format!(
|
||||||
|
"Failed to configure file length for temp file at {}",
|
||||||
|
tmpfile.path().display()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
Ok(unsafe { MmapMut::map_mut(tmpfile.as_file()).ok() })
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "mmap"))]
|
||||||
|
fn make_mmap(_: &mut NamedTempFile, _: Option<usize>) -> Result<Option<MmapMut>> {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue