- Run fmt

- Use built-in async benching
- Use custom Resize::None when making ratatui images to save some cycles
This commit is contained in:
itsjunetime
2024-06-04 16:50:51 -06:00
parent 5825849434
commit 8feea1127b
9 changed files with 61 additions and 48 deletions
Generated
+19 -1
View File
@@ -398,6 +398,7 @@ dependencies = [
"ciborium", "ciborium",
"clap", "clap",
"criterion-plot", "criterion-plot",
"futures",
"is-terminal", "is-terminal",
"itertools 0.10.5", "itertools 0.10.5",
"num-traits", "num-traits",
@@ -410,6 +411,7 @@ dependencies = [
"serde_derive", "serde_derive",
"serde_json", "serde_json",
"tinytemplate", "tinytemplate",
"tokio",
"walkdir", "walkdir",
] ]
@@ -574,6 +576,20 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "futures"
version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.30" version = "0.3.30"
@@ -581,6 +597,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink",
] ]
[[package]] [[package]]
@@ -637,6 +654,7 @@ checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-macro", "futures-macro",
"futures-sink",
"futures-task", "futures-task",
"pin-project-lite", "pin-project-lite",
"pin-utils", "pin-utils",
@@ -1452,7 +1470,7 @@ dependencies = [
[[package]] [[package]]
name = "ratatui-image" name = "ratatui-image"
version = "1.0.0" version = "1.0.0"
source = "git+https://github.com/itsjunetime/ratatui-image.git?branch=vb64_on_personal#e5c13ed29c9decdff093c2be5d673d84fb3589a9" source = "git+https://github.com/itsjunetime/ratatui-image.git?branch=vb64_on_personal#88876c749898cce7801379345eb4e0bc69111b8a"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"dyn-clone", "dyn-clone",
+1 -1
View File
@@ -42,7 +42,7 @@ default = []
tracing = ["tokio/tracing", "dep:console-subscriber"] tracing = ["tokio/tracing", "dep:console-subscriber"]
[dev-dependencies] [dev-dependencies]
criterion = "0.5.1" criterion = { version = "0.5.1", features = ["async_tokio"] }
[[bench]] [[bench]]
name = "rendering" name = "rendering"
+12 -19
View File
@@ -1,25 +1,19 @@
mod utils; mod utils;
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use utils::{render_doc, render_first_page}; use utils::{render_doc, render_first_page};
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
const FILES: [&str; 2] = [ const FILES: [&str; 2] = [
"./benches/example_dictionary.pdf", "benches/example_dictionary.pdf",
"./benches/adobe_example.pdf" "benches/adobe_example.pdf"
]; ];
fn render_full(c: &mut Criterion) { fn render_full(c: &mut Criterion) {
for file in FILES { for file in FILES {
c.bench_with_input( c.bench_with_input(BenchmarkId::new("render_full", file), &file, |b, &file| {
BenchmarkId::new("render_full", file), b.to_async(tokio::runtime::Runtime::new().unwrap())
&file, .iter(|| render_doc(file))
|b, &file| b.iter(|| });
tokio::runtime::Runtime::new()
.unwrap()
.block_on(render_doc(file))
)
);
} }
} }
@@ -28,18 +22,17 @@ fn render_to_first_page(c: &mut Criterion) {
c.bench_with_input( c.bench_with_input(
BenchmarkId::new("render_first_page", file), BenchmarkId::new("render_first_page", file),
&file, &file,
|b, &file| b.iter(|| |b, &file| {
tokio::runtime::Runtime::new() b.to_async(tokio::runtime::Runtime::new().unwrap())
.unwrap() .iter(|| render_first_page(file))
.block_on(render_first_page(file)) }
)
); );
} }
} }
criterion_group!( criterion_group!(
name = benches; name = benches;
config = Criterion::default().sample_size(10); config = Criterion::default().sample_size(40);
targets = render_full, render_to_first_page targets = render_full, render_to_first_page
); );
criterion_main!(benches); criterion_main!(benches);
+12 -11
View File
@@ -2,21 +2,24 @@ use std::{hint::black_box, path::Path};
use crossterm::terminal::WindowSize; use crossterm::terminal::WindowSize;
use flume::{r#async::RecvStream, unbounded, Sender}; use flume::{r#async::RecvStream, unbounded, Sender};
use futures_util::stream::StreamExt as _;
use ratatui::layout::Rect; use ratatui::layout::Rect;
use ratatui_image::picker::{Picker, ProtocolType}; use ratatui_image::picker::{Picker, ProtocolType};
use tdf::{converter::{run_conversion_loop, ConvertedPage, ConverterMsg}, renderer::{fill_default, start_rendering, RenderError, RenderInfo, RenderNotif}}; use tdf::{
use futures_util::stream::StreamExt as _; converter::{run_conversion_loop, ConvertedPage, ConverterMsg},
renderer::{fill_default, start_rendering, RenderError, RenderInfo, RenderNotif}
};
fn handle_renderer_msg( fn handle_renderer_msg(
msg: Result<RenderInfo, RenderError>, msg: Result<RenderInfo, RenderError>,
pages: &mut Vec<Option<ConvertedPage>>, pages: &mut Vec<Option<ConvertedPage>>,
to_converter_tx: &mut Sender<tdf::converter::ConverterMsg>, to_converter_tx: &mut Sender<tdf::converter::ConverterMsg>
) { ) {
match msg { match msg {
Ok(RenderInfo::NumPages(num)) => { Ok(RenderInfo::NumPages(num)) => {
fill_default(pages, num); fill_default(pages, num);
to_converter_tx.send(ConverterMsg::NumPages(num)).unwrap(); to_converter_tx.send(ConverterMsg::NumPages(num)).unwrap();
}, }
Ok(RenderInfo::Page(info)) => to_converter_tx.send(ConverterMsg::AddImg(info)).unwrap(), Ok(RenderInfo::Page(info)) => to_converter_tx.send(ConverterMsg::AddImg(info)).unwrap(),
Err(e) => panic!("Got error from renderer: {e:?}") Err(e) => panic!("Got error from renderer: {e:?}")
} }
@@ -32,13 +35,13 @@ fn handle_converter_msg(
pages[num] = Some(page); pages[num] = Some(page);
let num_got = pages.iter() let num_got = pages.iter().filter(|p| p.is_some()).count();
.filter(|p| p.is_some())
.count();
// we have to tell it to jump to a certain page so that it will actually render it (since // we have to tell it to jump to a certain page so that it will actually render it (since
// it only renders fanning out from the page that we currently have selected) // it only renders fanning out from the page that we currently have selected)
to_converter_tx.send(ConverterMsg::GoToPage(num_got)).unwrap(); to_converter_tx
.send(ConverterMsg::GoToPage(num_got))
.unwrap();
} }
struct RenderState { struct RenderState {
@@ -66,9 +69,7 @@ fn start_all_rendering(path: impl AsRef<Path>) -> RenderState {
width: columns * font_size.0 width: columns * font_size.0
}; };
std::thread::spawn(move || { std::thread::spawn(move || start_rendering(str_path, to_main_tx, from_main_rx, size));
start_rendering(str_path, to_main_tx, from_main_rx, size)
});
let (to_converter_tx, from_main_rx) = unbounded(); let (to_converter_tx, from_main_rx) = unbounded();
let (to_main_tx, from_converter_rx) = unbounded(); let (to_main_tx, from_converter_rx) = unbounded();
+2 -2
View File
@@ -1,8 +1,8 @@
use flume::{Receiver, SendError, Sender, TryRecvError}; use flume::{Receiver, SendError, Sender, TryRecvError};
use futures_util::stream::StreamExt;
use image::ImageFormat; use image::ImageFormat;
use itertools::Itertools; use itertools::Itertools;
use ratatui_image::{picker::Picker, protocol::Protocol, Resize}; use ratatui_image::{picker::Picker, protocol::Protocol, Resize};
use futures_util::stream::StreamExt;
use crate::renderer::{fill_default, PageInfo, RenderError}; use crate::renderer::{fill_default, PageInfo, RenderError};
@@ -67,7 +67,7 @@ pub async fn run_conversion_loop(
// size for the area given, so to save ratatui the work of having to // size for the area given, so to save ratatui the work of having to
// resize it, we tell them to crop it to fit. // resize it, we tell them to crop it to fit.
let txt_img = picker let txt_img = picker
.new_protocol(dyn_img, img_area, Resize::Crop) .new_protocol(dyn_img, img_area, Resize::None)
.map_err(|e| { .map_err(|e| {
RenderError::Render(format!( RenderError::Render(format!(
"Couldn't convert DynamicImage to ratatui image: {e}" "Couldn't convert DynamicImage to ratatui image: {e}"
+2 -2
View File
@@ -1,6 +1,6 @@
#![feature(if_let_guard)] #![feature(if_let_guard)]
pub mod renderer;
pub mod converter; pub mod converter;
pub mod tui; pub mod renderer;
pub mod skip; pub mod skip;
pub mod tui;
+3 -1
View File
@@ -44,7 +44,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
#[cfg(feature = "tracing")] #[cfg(feature = "tracing")]
console_subscriber::init(); console_subscriber::init();
let file = std::env::args().nth(1).ok_or("Program requires a file to process")?; let file = std::env::args()
.nth(1)
.ok_or("Program requires a file to process")?;
let path = PathBuf::from_str(&file)?.canonicalize()?; let path = PathBuf::from_str(&file)?.canonicalize()?;
//let (watch_tx, render_rx) = tokio::sync::mpsc::unbounded_channel(); //let (watch_tx, render_rx) = tokio::sync::mpsc::unbounded_channel();
+9 -10
View File
@@ -198,11 +198,10 @@ pub fn start_rendering(
// We know this is in range 'cause we're iterating over it but we still just want // We know this is in range 'cause we're iterating over it but we still just want
// to be safe // to be safe
let Some(page) = doc.page(num as i32) else { let Some(page) = doc.page(num as i32) else {
sender sender.send(Err(RenderError::Render(format!(
.send(Err(RenderError::Render(format!( "Couldn't get page {num} ({}) of doc?",
"Couldn't get page {num} ({}) of doc?", num as i32
num as i32 ))))?;
))))?;
continue; continue;
}; };
@@ -242,7 +241,7 @@ pub fn start_rendering(
render_ctx_to_png(ctx, &mut sender, (col_w, col_h), num) render_ctx_to_png(ctx, &mut sender, (col_w, col_h), num)
}); });
} }
}, }
// And if we got an error, then obviously we need to propagate that // And if we got an error, then obviously we need to propagate that
Err(e) => sender.send(Err(RenderError::Render(e)))? Err(e) => sender.send(Err(RenderError::Render(e)))?
} }
@@ -285,7 +284,7 @@ fn render_single_page_to_ctx(
page: Page, page: Page,
search_term: &Option<String>, search_term: &Option<String>,
already_rendered_no_results: bool, already_rendered_no_results: bool,
(area_w, area_h): (f64, f64), (area_w, area_h): (f64, f64)
) -> Result<Option<RenderedContext>, String> { ) -> Result<Option<RenderedContext>, String> {
let mut result_rects = search_term let mut result_rects = search_term
.as_ref() .as_ref()
@@ -393,9 +392,9 @@ fn render_ctx_to_png(
let mut img_data = Vec::with_capacity((ctx.surface_height * ctx.surface_width) as usize); let mut img_data = Vec::with_capacity((ctx.surface_height * ctx.surface_width) as usize);
match ctx.surface.write_to_png(&mut img_data) { match ctx.surface.write_to_png(&mut img_data) {
Err(e) => sender.send(Err(RenderError::Render( Err(e) => sender.send(Err(RenderError::Render(format!(
format!("Couldn't write surface to png: {e}") "Couldn't write surface to png: {e}"
))), )))),
Ok(()) => sender.send(Ok(RenderInfo::Page(PageInfo { Ok(()) => sender.send(Ok(RenderInfo::Page(PageInfo {
img_data: ImageData { img_data: ImageData {
data: img_data, data: img_data,