mirror of
https://github.com/alexpasmantier/television.git
synced 2025-06-06 11:35:25 +00:00
wip: solved the preview performance regression
This commit is contained in:
parent
fc3f24fd89
commit
07ad8d760b
@ -1,6 +1,5 @@
|
|||||||
use crate::channels::cable::prototypes::CableChannelPrototype;
|
use crate::channels::cable::prototypes::CableChannelPrototype;
|
||||||
use crate::preview::{Preview, PreviewContent};
|
use crate::preview::{Preview, PreviewContent};
|
||||||
use crate::utils::cache::RingSet;
|
|
||||||
use crate::utils::command::shell_command;
|
use crate::utils::command::shell_command;
|
||||||
use crate::{
|
use crate::{
|
||||||
channels::{entry::Entry, preview::PreviewCommand},
|
channels::{entry::Entry, preview::PreviewCommand},
|
||||||
@ -16,34 +15,25 @@ use tracing::debug;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Previewer {
|
pub struct Previewer {
|
||||||
cache: Arc<Mutex<PreviewCache>>,
|
cache: Arc<Mutex<PreviewCache>>,
|
||||||
requests: RingSet<Entry>,
|
|
||||||
concurrent_preview_tasks: Arc<AtomicU8>,
|
concurrent_preview_tasks: Arc<AtomicU8>,
|
||||||
in_flight_previews: Arc<Mutex<FxHashSet<String>>>,
|
in_flight_previews: Arc<Mutex<FxHashSet<String>>>,
|
||||||
command: PreviewCommand,
|
command: PreviewCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
const REQUEST_STACK_SIZE: usize = 10;
|
|
||||||
|
|
||||||
impl Previewer {
|
impl Previewer {
|
||||||
// we could use a target scroll here to make the previewer
|
// we could use a target scroll here to make the previewer
|
||||||
// faster, but since it's already running in the background and quite
|
// faster, but since it's already running in the background and quite
|
||||||
// fast for most standard file sizes, plus we're caching the previews,
|
// fast for most standard file sizes, plus we're caching the previews,
|
||||||
// I'm not sure the extra complexity is worth it.
|
// I'm not sure the extra complexity is worth it.
|
||||||
pub fn handle_request(&mut self, entry: &Entry) -> Option<Arc<Preview>> {
|
pub fn request(&mut self, entry: &Entry) -> Option<Arc<Preview>> {
|
||||||
// check if we have a preview in cache for the current request
|
// check if we have a preview in cache for the current request
|
||||||
if let Some(preview) = self.cached(entry) {
|
if let Some(preview) = self.cached(entry) {
|
||||||
return Some(preview);
|
return Some(preview);
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, if we haven't acknowledged the request yet, acknowledge it
|
// start a background task to compute the preview
|
||||||
self.requests.push(entry.clone());
|
self.preview(entry);
|
||||||
|
|
||||||
// lookup request stack and return the most recent preview available
|
|
||||||
for entry in self.requests.back_to_front() {
|
|
||||||
if let Some(preview) = self.preview(&entry) {
|
|
||||||
return Some(preview);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,7 +44,6 @@ impl Previewer {
|
|||||||
pub fn new(command: PreviewCommand) -> Self {
|
pub fn new(command: PreviewCommand) -> Self {
|
||||||
Previewer {
|
Previewer {
|
||||||
cache: Arc::new(Mutex::new(PreviewCache::default())),
|
cache: Arc::new(Mutex::new(PreviewCache::default())),
|
||||||
requests: RingSet::with_capacity(REQUEST_STACK_SIZE),
|
|
||||||
concurrent_preview_tasks: Arc::new(AtomicU8::new(0)),
|
concurrent_preview_tasks: Arc::new(AtomicU8::new(0)),
|
||||||
in_flight_previews: Arc::new(Mutex::new(FxHashSet::default())),
|
in_flight_previews: Arc::new(Mutex::new(FxHashSet::default())),
|
||||||
command,
|
command,
|
||||||
@ -65,18 +54,7 @@ impl Previewer {
|
|||||||
self.cache.lock().get(&entry.name)
|
self.cache.lock().get(&entry.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn preview(&mut self, entry: &Entry) -> Option<Arc<Preview>> {
|
pub fn preview(&mut self, entry: &Entry) {
|
||||||
if let Some(preview) = self.cached(entry) {
|
|
||||||
Some(preview)
|
|
||||||
} else {
|
|
||||||
// preview is not in cache, spawn a task to compute the preview
|
|
||||||
debug!("Preview cache miss for {:?}", entry.name);
|
|
||||||
self.handle_preview_request(entry);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn handle_preview_request(&mut self, entry: &Entry) {
|
|
||||||
if self.in_flight_previews.lock().contains(&entry.name) {
|
if self.in_flight_previews.lock().contains(&entry.name) {
|
||||||
debug!("Preview already in flight for {:?}", entry.name);
|
debug!("Preview already in flight for {:?}", entry.name);
|
||||||
return;
|
return;
|
||||||
|
@ -8,9 +8,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
entry::Entry,
|
entry::Entry,
|
||||||
remote_control::RemoteControl,
|
remote_control::RemoteControl,
|
||||||
// stdin::Channel as StdinChannel,
|
OnAir, TelevisionChannel,
|
||||||
OnAir,
|
|
||||||
TelevisionChannel,
|
|
||||||
},
|
},
|
||||||
config::{Config, Theme},
|
config::{Config, Theme},
|
||||||
draw::{ChannelState, Ctx, TvState},
|
draw::{ChannelState, Ctx, TvState},
|
||||||
@ -391,15 +389,11 @@ impl Television {
|
|||||||
// FIXME: this is probably redundant with the channel supporting previews
|
// FIXME: this is probably redundant with the channel supporting previews
|
||||||
&& self.previewer.is_some()
|
&& self.previewer.is_some()
|
||||||
{
|
{
|
||||||
// preview content
|
// avoid sending unnecessary requests to the previewer
|
||||||
if let Some(preview) = self
|
if self.preview_state.preview.title != selected_entry.name {
|
||||||
.previewer
|
if let Some(preview) =
|
||||||
.as_mut()
|
self.previewer.as_mut().unwrap().request(selected_entry)
|
||||||
.unwrap()
|
{
|
||||||
.handle_request(selected_entry)
|
|
||||||
{
|
|
||||||
// only update if the preview content has changed
|
|
||||||
if self.preview_state.preview.title != preview.title {
|
|
||||||
self.preview_state.update(
|
self.preview_state.update(
|
||||||
preview,
|
preview,
|
||||||
// scroll to center the selected entry
|
// scroll to center the selected entry
|
||||||
@ -576,15 +570,12 @@ impl Television {
|
|||||||
self.handle_input_action(action);
|
self.handle_input_action(action);
|
||||||
}
|
}
|
||||||
Action::SelectNextEntry => {
|
Action::SelectNextEntry => {
|
||||||
self.preview_state.reset();
|
|
||||||
self.select_next_entry(1);
|
self.select_next_entry(1);
|
||||||
}
|
}
|
||||||
Action::SelectPrevEntry => {
|
Action::SelectPrevEntry => {
|
||||||
self.preview_state.reset();
|
|
||||||
self.select_prev_entry(1);
|
self.select_prev_entry(1);
|
||||||
}
|
}
|
||||||
Action::SelectNextPage => {
|
Action::SelectNextPage => {
|
||||||
self.preview_state.reset();
|
|
||||||
self.select_next_entry(
|
self.select_next_entry(
|
||||||
self.ui_state
|
self.ui_state
|
||||||
.layout
|
.layout
|
||||||
@ -595,7 +586,6 @@ impl Television {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Action::SelectPrevPage => {
|
Action::SelectPrevPage => {
|
||||||
self.preview_state.reset();
|
|
||||||
self.select_prev_entry(
|
self.select_prev_entry(
|
||||||
self.ui_state
|
self.ui_state
|
||||||
.layout
|
.layout
|
||||||
|
Loading…
x
Reference in New Issue
Block a user