Skip to content

Commit

Permalink
refactor(libwayshot): Reduce allocations (#99)
Browse files Browse the repository at this point in the history
* refactor: remove unnecessary to_string()

* refactor: fix clippy warnings

* refactor: remove 1 level of indirection via &Vec<T> -> &[T]

Typically `&Vec<T>` isn't something you want when you need a read-only view
over a Vec, because it adds another level of indirection: Vec already stores
a pointer to heap-allocated buffer internally.

Using slices `&[T]` removes such unnecessary level of indirection and
is considered a cleaner design. It is cache friendlier and can be better
optimized by the compiler (not that it should matter in this case).
  • Loading branch information
murlakatamenka authored Mar 23, 2024
1 parent 017be62 commit f53e650
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 33 deletions.
48 changes: 21 additions & 27 deletions libwayshot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ impl WayshotConnection {
}

/// Fetch all accessible wayland outputs.
pub fn get_all_outputs(&self) -> &Vec<OutputInfo> {
&self.output_infos
pub fn get_all_outputs(&self) -> &[OutputInfo] {
self.output_infos.as_slice()
}

/// refresh the outputs, to get new outputs
Expand Down Expand Up @@ -388,37 +388,32 @@ impl WayshotConnection {

pub fn capture_frame_copies(
&self,
output_capture_regions: &Vec<(OutputInfo, Option<EmbeddedRegion>)>,
output_capture_regions: &[(OutputInfo, Option<EmbeddedRegion>)],
cursor_overlay: bool,
) -> Result<Vec<(FrameCopy, FrameGuard, OutputInfo)>> {
let frame_copies = thread::scope(|scope| -> Result<_> {
let join_handles = output_capture_regions
.into_iter()
.iter()
.map(|(output_info, capture_region)| {
scope.spawn(move || {
self.capture_frame_copy(
cursor_overlay,
&output_info,
capture_region.clone(),
)
.map(|(frame_copy, frame_guard)| {
(frame_copy, frame_guard, output_info.clone())
})
self.capture_frame_copy(cursor_overlay, output_info, *capture_region)
.map(|(frame_copy, frame_guard)| {
(frame_copy, frame_guard, output_info.clone())
})
})
})
.collect::<Vec<_>>();

join_handles
.into_iter()
.map(|join_handle| join_handle.join())
.flatten()
.flat_map(|join_handle| join_handle.join())
.collect::<Result<_>>()
})?;

Ok(frame_copies)
}

fn overlay_frames(&self, frames: &Vec<(FrameCopy, FrameGuard, OutputInfo)>) -> Result<()> {
fn overlay_frames(&self, frames: &[(FrameCopy, FrameGuard, OutputInfo)]) -> Result<()> {
let mut state = LayerShellState {
configured_outputs: HashSet::new(),
};
Expand Down Expand Up @@ -506,15 +501,15 @@ impl WayshotConnection {
region_capturer: RegionCapturer,
cursor_overlay: bool,
) -> Result<DynamicImage> {
let outputs_capture_regions: &Vec<(OutputInfo, Option<EmbeddedRegion>)> =
&match region_capturer {
let outputs_capture_regions: Vec<(OutputInfo, Option<EmbeddedRegion>)> =
match region_capturer {
RegionCapturer::Outputs(ref outputs) => outputs
.into_iter()
.iter()
.map(|output_info| (output_info.clone(), None))
.collect(),
RegionCapturer::Region(capture_region) => self
.get_all_outputs()
.into_iter()
.iter()
.filter_map(|output_info| {
tracing::span!(
tracing::Level::DEBUG,
Expand All @@ -541,15 +536,15 @@ impl WayshotConnection {
.collect(),
RegionCapturer::Freeze(_) => self
.get_all_outputs()
.into_iter()
.iter()
.map(|output_info| (output_info.clone(), None))
.collect(),
};

let frames = self.capture_frame_copies(outputs_capture_regions, cursor_overlay)?;
let frames = self.capture_frame_copies(&outputs_capture_regions, cursor_overlay)?;

let capture_region: LogicalRegion = match region_capturer {
RegionCapturer::Outputs(ref outputs) => outputs.try_into()?,
RegionCapturer::Outputs(outputs) => outputs.as_slice().try_into()?,
RegionCapturer::Region(region) => region,
RegionCapturer::Freeze(callback) => {
self.overlay_frames(&frames).and_then(|_| callback())?
Expand All @@ -565,7 +560,7 @@ impl WayshotConnection {
.map(|(output_info, _)| output_info.scale())
.fold(1.0, f64::max);

tracing::Span::current().record("max_scale", &max_scale);
tracing::Span::current().record("max_scale", max_scale);

let rotate_join_handles = frames
.into_iter()
Expand All @@ -587,8 +582,7 @@ impl WayshotConnection {

rotate_join_handles
.into_iter()
.map(|join_handle| join_handle.join())
.flatten()
.flat_map(|join_handle| join_handle.join())
.fold(
None,
|composite_image: Option<Result<_>>, image: Result<_>| {
Expand Down Expand Up @@ -666,14 +660,14 @@ impl WayshotConnection {
/// Take a screenshot from all of the specified outputs.
pub fn screenshot_outputs(
&self,
outputs: &Vec<OutputInfo>,
outputs: &[OutputInfo],
cursor_overlay: bool,
) -> Result<DynamicImage> {
if outputs.is_empty() {
return Err(Error::NoOutputs);
}

self.screenshot_region_capturer(RegionCapturer::Outputs(outputs.clone()), cursor_overlay)
self.screenshot_region_capturer(RegionCapturer::Outputs(outputs.to_owned()), cursor_overlay)
}

/// Take a screenshot from all accessible outputs.
Expand Down
6 changes: 3 additions & 3 deletions libwayshot/src/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ impl EmbeddedRegion {
};

Some(Self {
relative_to: relative_to,
relative_to,
inner: Region {
position: Position { x: x1, y: y1 },
size: Size { width, height },
Expand Down Expand Up @@ -195,10 +195,10 @@ impl From<&OutputInfo> for LogicalRegion {
}
}

impl TryFrom<&Vec<OutputInfo>> for LogicalRegion {
impl TryFrom<&[OutputInfo]> for LogicalRegion {
type Error = Error;

fn try_from(output_info: &Vec<OutputInfo>) -> std::result::Result<Self, Self::Error> {
fn try_from(output_info: &[OutputInfo]) -> std::result::Result<Self, Self::Error> {
let x1 = output_info
.iter()
.map(|output| output.logical_region.inner.position.x)
Expand Down
6 changes: 3 additions & 3 deletions wayshot/src/wayshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ fn main() -> Result<()> {
Box::new(move || {
|| -> Result<LogicalRegion> {
let slurp_output = Command::new("slurp")
.args(slurp_region.split(" "))
.args(slurp_region.split(' '))
.output()?
.stdout;

Expand All @@ -91,9 +91,9 @@ fn main() -> Result<()> {
}
} else if cli.choose_output {
let outputs = wayshot_conn.get_all_outputs();
let output_names: Vec<String> = outputs
let output_names: Vec<&str> = outputs
.iter()
.map(|display| display.name.to_string())
.map(|display| display.name.as_str())
.collect();
if let Some(index) = select_ouput(&output_names) {
wayshot_conn.screenshot_single_output(&outputs[index], cli.cursor)?
Expand Down

0 comments on commit f53e650

Please sign in to comment.