raw savings

arg-parsing-better
Avril 4 years ago
parent 18c7c12025
commit 9d339d9628
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -13,7 +13,7 @@ codegen-units = 1
panic = "unwind" panic = "unwind"
[features] [features]
default = ["splash", "inspect", "defer-drop", "jemalloc", "prealloc"] default = ["splash", "inspect", "defer-drop", "jemalloc"]
# Use jemalloc as global allocator instead of system allocator. # Use jemalloc as global allocator instead of system allocator.
# May potentially cause some speedups and better memory profile on large runs. # May potentially cause some speedups and better memory profile on large runs.

@ -33,7 +33,8 @@ const OPTIONS_NORMAL: &'static [&'static str] = &[
"-v Verbose mode. Output extra information.", "-v Verbose mode. Output extra information.",
#[cfg(feature="inspect")] "--save <file> Dump the collected data to this file for further inspection.", #[cfg(feature="inspect")] "--save <file> Dump the collected data to this file for further inspection.",
#[cfg(feature="inspect")] "-D Dump the collected data to `stdout` (see `--save`.)", #[cfg(feature="inspect")] "-D Dump the collected data to `stdout` (see `--save`.)",
#[cfg(feature="prealloc")] "--save-raw <file> Dump the collected data to this file uncompressed.", #[cfg(feature="inspect")] "--save-raw <file> Dump the collected data to this file uncompressed. (see `--save`.)",
#[cfg(feature="inspect")] "-Dr Dump the collected data to standard output uncompressed. (see `--save-raw`.)",
"- Stop parsing arguments, treat all the rest as paths.", "- Stop parsing arguments, treat all the rest as paths.",
]; ];
@ -143,15 +144,23 @@ fn parse<I: IntoIterator<Item=String>>(args: I) -> eyre::Result<Mode>
#[cfg(feature="inspect")] "-D" => { #[cfg(feature="inspect")] "-D" => {
cfg.serialise_output = Some(config::OutputSerialisationMode::Stdout); cfg.serialise_output = Some(config::OutputSerialisationMode::Stdout);
}, },
#[cfg(feature="inspect")] "-Dr" => {
cfg.serialise_output = Some(config::OutputSerialisationMode::RawStdout);
},
#[cfg(feature="inspect")] "--save" => { #[cfg(feature="inspect")] "--save" => {
let file = args.next().ok_or(eyre!("`--save` expects a filename parameter")) let file = args.next().ok_or(eyre!("`--save` expects a filename parameter"))
.with_suggestion(suggestion_intended_arg.clone())?; .with_suggestion(suggestion_intended_arg.clone())?;
cfg.serialise_output = Some(config::OutputSerialisationMode::File(file.into())); cfg.serialise_output = Some(config::OutputSerialisationMode::File(file.into()));
}, },
#[cfg(feature="prealloc")] "--save-raw" => { #[cfg(feature="inspect")] "--save-raw" => {
let file = args.next().ok_or(eyre!("`--save-raw` expects a filename parameter")) let file = args.next().ok_or(eyre!("`--save-raw` expects a filename parameter"))
.with_suggestion(suggestion_intended_arg.clone())?; .with_suggestion(suggestion_intended_arg.clone())?;
#[cfg(feature="prealloc")] {
cfg.serialise_output = Some(config::OutputSerialisationMode::PreallocFile(file.into())); cfg.serialise_output = Some(config::OutputSerialisationMode::PreallocFile(file.into()));
}
#[cfg(not(feature="prealloc"))] {
cfg.serialise_output = Some(config::OutputSerialisationMode::RawFile(file.into()));
}
}, },
"--recursive" => { "--recursive" => {
let max = args.next().ok_or(eyre!("`--recursive` expects a parameter")) let max = args.next().ok_or(eyre!("`--recursive` expects a parameter"))

@ -98,13 +98,29 @@ impl From<usize> for Recursion
#[cfg(feature="inspect")] #[cfg(feature="inspect")]
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum OutputSerialisationMode pub enum OutputSerialisationMode
{ {
Stdout, Stdout,
File(PathBuf), File(PathBuf),
RawFile(PathBuf),
RawStdout,
#[cfg(feature="prealloc")] PreallocFile(PathBuf), #[cfg(feature="prealloc")] PreallocFile(PathBuf),
} }
#[cfg(feature="inspect")]
impl OutputSerialisationMode
{
/// Should this serialisation mode be compressed?
#[inline] pub fn should_compress(&self) -> bool
{
match self {
Self::File(_) | Self::Stdout => true,
_ => false,
}
}
}
/// Configuration for this run /// Configuration for this run
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Config pub struct Config
@ -139,11 +155,11 @@ impl Config
#[inline] pub fn is_using_stdout(&self) -> bool #[inline] pub fn is_using_stdout(&self) -> bool
{ {
#[cfg(feature="inspect")] { #[cfg(feature="inspect")] {
return if let Some(OutputSerialisationMode::Stdout) = self.serialise_output { return match self.serialise_output {
true Some(OutputSerialisationMode::Stdout) |
} else { Some(OutputSerialisationMode::RawStdout) => true,
false _ => false,
}; }
} }
#[cfg(not(feature="inspect"))] { #[cfg(not(feature="inspect"))] {
false false

@ -73,8 +73,10 @@ async fn normal(cfg: config::Config) -> eyre::Result<()>
type BoxedWrite = Box<dyn tokio::io::AsyncWrite + Unpin>; type BoxedWrite = Box<dyn tokio::io::AsyncWrite + Unpin>;
use futures::FutureExt; use futures::FutureExt;
use config::OutputSerialisationMode; use config::OutputSerialisationMode;
let should_comp = ser_out.should_compress();
match ser_out { match ser_out {
OutputSerialisationMode::File(output_file) => { OutputSerialisationMode::File(output_file) |
OutputSerialisationMode::RawFile(output_file) => {
use tokio::fs::OpenOptions; use tokio::fs::OpenOptions;
(async move { (async move {
let stream = OpenOptions::new() let stream = OpenOptions::new()
@ -86,25 +88,27 @@ async fn normal(cfg: config::Config) -> eyre::Result<()>
.with_section(|| format!("{:?}", output_file).header("File was"))?; .with_section(|| format!("{:?}", output_file).header("File was"))?;
Ok::<BoxedWrite, eyre::Report>(Box::new(stream)) Ok::<BoxedWrite, eyre::Report>(Box::new(stream))
}.boxed(), None) }.boxed(), None, should_comp)
}, },
OutputSerialisationMode::Stdout => (async move { Ok::<BoxedWrite, _>(Box::new(tokio::io::stdout())) }.boxed(), None), OutputSerialisationMode::Stdout |
OutputSerialisationMode::RawStdout => (async move { Ok::<BoxedWrite, _>(Box::new(tokio::io::stdout())) }.boxed(), Option::<&std::path::PathBuf>::None, should_comp),
#[cfg(feature="prealloc")] OutputSerialisationMode::PreallocFile(output_file) => { #[cfg(feature="prealloc")] OutputSerialisationMode::PreallocFile(output_file) => {
(async move { (async move {
Ok::<BoxedWrite, _>(Box::new(tokio::io::sink())) // we use a sink as a shim stream since it will never be used when tuple item `.1` is Some() Ok::<BoxedWrite, _>(Box::new(tokio::io::sink())) // we use a sink as a shim stream since it will never be used when tuple item `.1` is Some()
}.boxed(), Some(output_file)) }.boxed(), Some(output_file), false)
}, },
} }
}) { }) {
// We use tuple item `.1` here to indicate if we're in normal write mode. // We use tuple item `.1` here to indicate if we're in normal write mode.
// None -> normal // None -> normal
// Some(path) -> prealloc // Some(path) -> prealloc
Some((stream_fut, None)) => { // `.2` indicates if we should compress while in normal write mode.
Some((stream_fut, None, compress)) => {
let stream = stream_fut.await?; let stream = stream_fut.await?;
serial::write_async(stream, &graph, true).await // TODO: raw version serial::write_async(stream, &graph, compress).await // TODO: raw version, how to implement?
.wrap_err(eyre!("Failed to serialise graph to stream"))?; .wrap_err(eyre!("Failed to serialise graph to stream"))?;
}, },
#[cfg(feature="prealloc")] Some((_task_fut, Some(output_file))) => { #[cfg(feature="prealloc")] Some((_task_fut, Some(output_file), _)) => {
use tokio::fs::OpenOptions; use tokio::fs::OpenOptions;
let file = OpenOptions::new() let file = OpenOptions::new()
.write(true) .write(true)

@ -17,18 +17,49 @@ const DEFER_DROP_SIZE_FLOOR: usize = 1024 * 1024; // 1 MB
enum MaybeCompressor<'a, T> enum MaybeCompressor<'a, T>
{ {
Compressing(Compressor<&'a mut T>), Compressing(Compressor<&'a mut T>),
Decompressing(Decompressor<&'a mut T>),
Raw(&'a mut T), Raw(&'a mut T),
} }
/// Compress or decompress?
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy, PartialOrd, Ord)]
enum CompKind
{
Compress,
Decompress
}
impl Default for CompKind
{
#[inline]
fn default() -> Self
{
Self::Compress
}
}
impl<'a, T> MaybeCompressor<'a, T>
{
/// What kind is this compressor set to
pub fn kind(&self) -> Option<CompKind>
{
Some(match self {
Self::Raw(_) => return None,
Self::Compressing(_) => CompKind::Compress,
Self::Decompressing(_) => CompKind::Decompress,
})
}
}
impl<'a, T> MaybeCompressor<'a, T> impl<'a, T> MaybeCompressor<'a, T>
where T: AsyncWrite + Unpin + 'a where T: AsyncWrite + Unpin + 'a
{ {
pub fn new(raw: &'a mut T, compress: bool) -> Self pub fn new(raw: &'a mut T, compress: Option<CompKind>) -> Self
{ {
if compress { match compress {
Self::Compressing(Compressor::new(raw)) Some(CompKind::Compress) => Self::Compressing(Compressor::new(raw)),
} else { Some(CompKind::Decompress) => Self::Decompressing(Decompressor::new(raw)),
Self::Raw(raw) None => Self::Raw(raw),
} }
} }
} }
@ -39,6 +70,7 @@ where T: AsyncWrite + Unpin + 'a
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
match self { match self {
Self::Compressing(t) => t, Self::Compressing(t) => t,
Self::Decompressing(t) => t,
Self::Raw(o) => o, Self::Raw(o) => o,
} }
} }
@ -51,6 +83,7 @@ where T: AsyncWrite + Unpin + 'a
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
match self { match self {
Self::Compressing(t) => t, Self::Compressing(t) => t,
Self::Decompressing(t) => t,
Self::Raw(o) => o, Self::Raw(o) => o,
} }
} }
@ -73,7 +106,7 @@ where W: AsyncWrite + Unpin
.with_section(sect_type_name.clone())?; .with_section(sect_type_name.clone())?;
{ {
let mut stream = MaybeCompressor::new(&mut to, compress); let mut stream = MaybeCompressor::new(&mut to, compress.then(|| CompKind::Compress));
cfg_eprintln!(Verbose; config::get_global(), "Writing {} bytes of type {:?} to stream of type {:?}", vec.len(), std::any::type_name::<T>(), std::any::type_name::<W>()); cfg_eprintln!(Verbose; config::get_global(), "Writing {} bytes of type {:?} to stream of type {:?}", vec.len(), std::any::type_name::<T>(), std::any::type_name::<W>());

Loading…
Cancel
Save