-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
scaffold for universal-capture crate (#5)
* Added memcpy benchmark * Added clone assign benchmark * Added Source and Dest traits with Vec<u8> * Added benchmarks for in-memory capture * Fixed platform specific dependency * Added swap * use tabs * Mark vaporware
- Loading branch information
Showing
13 changed files
with
701 additions
and
6 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[package] | ||
name = "universal-capture" | ||
version.workspace = true | ||
license.workspace = true | ||
repository.workspace = true | ||
edition.workspace = true | ||
rust-version.workspace = true | ||
|
||
[features] | ||
# Sources are prefixed with `source-` | ||
# Destinations are prefixed with `dest-` | ||
# In-memory sources and destinations are always supported. | ||
source-dx11 = ["dep:dxcapture"] | ||
|
||
[target.'cfg(windows)'.dependencies] | ||
dxcapture = { version = "1.1.3", optional = true } | ||
|
||
[dev-dependencies] | ||
criterion = "0.5" | ||
rand = "0.8.5" | ||
|
||
[[bench]] | ||
name = "common_mem_ops" | ||
harness = false | ||
|
||
[[bench]] | ||
name = "in_mem_capture" | ||
harness = false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# universal-capture | ||
|
||
Provides a number of different ways to capture windows on various different | ||
operating systems and with various different representations and APIs. | ||
|
||
## Project Status | ||
|
||
Vaporware. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
use rand::Fill; | ||
|
||
pub struct Dims { | ||
width: usize, | ||
height: usize, | ||
} | ||
|
||
impl Dims { | ||
pub const fn size(&self) -> usize { | ||
self.width * self.height | ||
} | ||
} | ||
|
||
pub const RES_1080: Dims = Dims { | ||
width: 1920, | ||
height: 1080, | ||
}; | ||
|
||
pub const RES_1440: Dims = Dims { | ||
width: 2560, | ||
height: 1440, | ||
}; | ||
|
||
pub fn random_frames(res: Dims, num_frames: usize) -> Vec<Vec<u8>> { | ||
let mut rng = rand::thread_rng(); | ||
let mut frames = vec![vec![0; res.size()]; num_frames]; | ||
for v in frames.iter_mut() { | ||
v.as_mut_slice().try_fill(&mut rng).unwrap(); | ||
} | ||
frames | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
//! Benchmarks common memory operations like memcpy, malloc, free, etc. | ||
mod common; | ||
|
||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; | ||
use std::hint::black_box; | ||
|
||
use common::{random_frames, RES_1080, RES_1440}; | ||
|
||
fn bench_frame_copy(c: &mut Criterion) { | ||
/// Number of source frames we hold in memory as inputs. | ||
const N_FRAMES_IN_MEMORY: usize = 128; | ||
|
||
let mut frames_1080 = random_frames(RES_1080, N_FRAMES_IN_MEMORY); | ||
let mut frames_1440 = random_frames(RES_1440, N_FRAMES_IN_MEMORY); | ||
let mut dest_1080 = vec![0; RES_1080.size()]; | ||
let mut dest_1440 = vec![0; RES_1440.size()]; | ||
|
||
let mut group = c.benchmark_group("frame copy"); | ||
group.throughput(criterion::Throughput::Elements( | ||
N_FRAMES_IN_MEMORY.try_into().unwrap(), | ||
)); | ||
|
||
#[inline] | ||
fn swap_frames(source: &mut [Vec<u8>], mut dest: &mut Vec<u8>) { | ||
let source = black_box(source); | ||
for f in source { | ||
std::mem::swap(dest, f); | ||
dest = black_box(dest); | ||
} | ||
} | ||
|
||
#[inline] | ||
fn memcpy_frames(source: &[Vec<u8>], mut dest: &mut [u8]) { | ||
let source = black_box(source); | ||
for f in source { | ||
dest.copy_from_slice(f.as_slice()); | ||
dest = black_box(dest); | ||
} | ||
} | ||
|
||
#[inline] | ||
fn clone_assign_frames(source: &[Vec<u8>], mut dest: &mut Vec<u8>) { | ||
let source = black_box(source); | ||
for f in source { | ||
// This allocates and copies | ||
let cloned_vec = f.clone(); | ||
// This deallocates the vec that used to be in `dest` | ||
*dest = cloned_vec; | ||
dest = black_box(dest); | ||
} | ||
} | ||
|
||
group.bench_with_input(BenchmarkId::new("memcpy", "1080p"), &(), |b, &()| { | ||
let source = frames_1080.as_slice(); | ||
let dest = dest_1080.as_mut_slice(); | ||
b.iter(|| memcpy_frames(source, dest)) | ||
}); | ||
group.bench_with_input(BenchmarkId::new("memcpy", "1440p"), &(), |b, &()| { | ||
let source = frames_1440.as_slice(); | ||
let dest = dest_1440.as_mut_slice(); | ||
b.iter(|| memcpy_frames(source, dest)) | ||
}); | ||
|
||
group.bench_with_input(BenchmarkId::new("clone assign", "1080p"), &(), |b, &()| { | ||
let source = frames_1080.as_slice(); | ||
let dest = &mut dest_1080; | ||
b.iter(|| clone_assign_frames(source, dest)) | ||
}); | ||
group.bench_with_input(BenchmarkId::new("clone assign", "1440p"), &(), |b, &()| { | ||
let source = frames_1440.as_slice(); | ||
let dest = &mut dest_1440; | ||
b.iter(|| clone_assign_frames(source, dest)) | ||
}); | ||
|
||
group.bench_with_input(BenchmarkId::new("swap", "1080p"), &(), |b, &()| { | ||
let source = &mut frames_1080; | ||
let dest = &mut dest_1080; | ||
b.iter(|| swap_frames(source, dest)) | ||
}); | ||
group.bench_with_input(BenchmarkId::new("swap", "1440p"), &(), |b, &()| { | ||
let source = &mut frames_1440; | ||
let dest = &mut dest_1440; | ||
b.iter(|| swap_frames(source, dest)) | ||
}); | ||
|
||
group.finish(); | ||
} | ||
|
||
criterion_group!(benches, bench_frame_copy); | ||
criterion_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
//! Benchmarks capture via in-memory `Vec<u8>`s. | ||
mod common; | ||
|
||
use criterion::{criterion_group, criterion_main, Criterion}; | ||
use std::hint::black_box; | ||
use universal_capture::Source; | ||
|
||
use common::{random_frames, RES_1080, RES_1440}; | ||
|
||
fn bench_capture(c: &mut Criterion) { | ||
/// Number of source frames we hold in memory as inputs. | ||
const N_FRAMES_IN_MEMORY: usize = 128; | ||
|
||
let mut frames_1080 = random_frames(RES_1080, N_FRAMES_IN_MEMORY); | ||
let mut frames_1440 = random_frames(RES_1440, N_FRAMES_IN_MEMORY); | ||
let mut dest_1080 = vec![0; RES_1080.size()]; | ||
let mut dest_1440 = vec![0; RES_1440.size()]; | ||
|
||
let mut group = c.benchmark_group("capture"); | ||
group.throughput(criterion::Throughput::Elements( | ||
N_FRAMES_IN_MEMORY.try_into().unwrap(), | ||
)); | ||
|
||
#[inline] | ||
fn do_capture(source: &mut [Vec<u8>], mut dest: &mut Vec<u8>) { | ||
let source = black_box(source); | ||
for f in source { | ||
f.capture(dest).unwrap(); | ||
dest = black_box(dest); | ||
} | ||
} | ||
|
||
group.bench_function("1080p", |b| { | ||
let source = &mut frames_1080; | ||
let dest = &mut dest_1080; | ||
b.iter(|| do_capture(source, dest)) | ||
}); | ||
group.bench_function("1440p", |b| { | ||
let source = &mut frames_1440; | ||
let dest = &mut dest_1440; | ||
b.iter(|| do_capture(source, dest)) | ||
}); | ||
|
||
group.finish(); | ||
} | ||
|
||
criterion_group!(benches, bench_capture); | ||
criterion_main!(benches); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
use crate::Dest; | ||
|
||
impl<T> Dest for Vec<T> {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
mod in_memory; | ||
|
||
pub use in_memory::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
pub mod dests; | ||
pub mod sources; | ||
|
||
pub trait Dest: private::Sealed {} | ||
|
||
pub trait Source<Dest>: private::Sealed { | ||
/// Error returned by [`Self::capture`] | ||
type Error; | ||
|
||
/// Captures a frame from the `Source` and puts it in `Dest`. | ||
fn capture(&mut self, dest: &mut Dest) -> Result<(), Self::Error>; | ||
} | ||
|
||
mod private { | ||
pub trait Sealed {} | ||
|
||
impl<T> Sealed for Vec<T> {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use std::convert::Infallible; | ||
|
||
use crate::Source; | ||
|
||
impl<T> Source<Vec<T>> for Vec<T> { | ||
type Error = Infallible; | ||
|
||
fn capture(&mut self, dest: &mut Vec<T>) -> Result<(), Self::Error> { | ||
std::mem::swap(dest, self); | ||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
mod in_memory; | ||
|
||
pub use in_memory::*; |