Skip to content

Commit

Permalink
fix: introduce cache update cool down to console wallet (#3146)
Browse files Browse the repository at this point in the history
## Description
The current architecture of the wallet is that the AppState contains a cache of the current state that the UI uses to draw from and a second instance of the data that is updated in the background when events are received from the wallet services without interfering with drawing. When the background data has been updated by the event monitoring thread it flips a flag telling the UI that the cache has been invalidated so when the drawing is done on a Tick event the UI thread will clone the background data into the cache for future drawing calls.

A problem was found where when a large number of transactions were being processed by the wallet the UI would become unresponsive. The reason for this is that with a large amount of transactions there is quite a lot of AppState that is copied from the background into the UI cache which could take 300-400ms and this cache was being invalidated very often as the transactions are being handled by the wallet services. This would mean that a Cache copy occurred after every single draw cycle and would block the processing of Key events for 300-400ms.

This PR proposes a solution of introducing a cache update cooldown period, initially set to 2 seconds, so that if a cache update has occurred the soonest that the next update can occur is 2 seconds later giving the UI thread time to handle key events. In normal wallet operation state update events do not occur that often so this approach will allow the cache update to occur as soon as the cache is invalidated but will force a fast subsequent update to wait at least 2 seconds. In the mean time the background data can be worked on in the background thread.

## How Has This Been Tested?
Manually Tested

## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
* [x] I'm merging against the `development` branch.
* [x] I have squashed my commits into a single commit.
  • Loading branch information
aviator-app[bot] committed Aug 4, 2021
2 parents 7701846 + 0f37299 commit 5de9252
Showing 1 changed file with 34 additions and 5 deletions.
39 changes: 34 additions & 5 deletions applications/tari_console_wallet/src/ui/state/app_state.rs
Expand Up @@ -37,7 +37,11 @@ use bitflags::bitflags;
use futures::{stream::Fuse, StreamExt};
use log::*;
use qrcode::{render::unicode, QrCode};
use std::{collections::HashMap, sync::Arc};
use std::{
collections::HashMap,
sync::Arc,
time::{Duration, Instant},
};
use tari_common::{configuration::Network, GlobalConfig};
use tari_comms::{
connectivity::ConnectivityEventRx,
Expand Down Expand Up @@ -72,8 +76,10 @@ const LOG_TARGET: &str = "wallet::console_wallet::app_state";
pub struct AppState {
inner: Arc<RwLock<AppStateInner>>,
cached_data: AppStateData,
cache_update_cooldown: Option<Instant>,
completed_tx_filter: TransactionFilter,
node_config: GlobalConfig,
config: AppStateConfig,
}

impl AppState {
Expand All @@ -91,8 +97,10 @@ impl AppState {
Self {
inner: Arc::new(RwLock::new(inner)),
cached_data,
cache_update_cooldown: None,
completed_tx_filter: TransactionFilter::ABANDONED_COINBASES,
node_config,
config: AppStateConfig::default(),
}
}

Expand Down Expand Up @@ -126,10 +134,18 @@ impl AppState {
}

pub async fn update_cache(&mut self) {
let mut inner = self.inner.write().await;
let updated_state = inner.get_updated_app_state();
if let Some(data) = updated_state {
self.cached_data = data;
let update = match self.cache_update_cooldown {
Some(last_update) => last_update.elapsed() > self.config.cache_update_cooldown,
None => true,
};

if update {
let mut inner = self.inner.write().await;
let updated_state = inner.get_updated_app_state();
if let Some(data) = updated_state {
self.cached_data = data;
self.cache_update_cooldown = Some(Instant::now());
}
}
}

Expand Down Expand Up @@ -897,3 +913,16 @@ bitflags! {
const ABANDONED_COINBASES = 0b0000_0001;
}
}

#[derive(Clone)]
struct AppStateConfig {
pub cache_update_cooldown: Duration,
}

impl Default for AppStateConfig {
fn default() -> Self {
Self {
cache_update_cooldown: Duration::from_secs(2),
}
}
}

0 comments on commit 5de9252

Please sign in to comment.