Эх сурвалжийг харах

avoided unnecessary cloning, +other little optimizations

Berke 1 жил өмнө
parent
commit
2e7e04e129
1 өөрчлөгдсөн 47 нэмэгдсэн , 67 устгасан
  1. 47 67
      src/charts/heatmap.rs

+ 47 - 67
src/charts/heatmap.rs

@@ -110,41 +110,25 @@ impl Heatmap {
     
     pub fn render_start(&mut self) {
         let timestamp_now = Utc::now().timestamp_millis();
-
+    
         let latest: i64 = timestamp_now - ((self.translation.x*100.0)*(self.timeframe as f32)) as i64;
         let earliest: i64 = latest - ((64000.0*self.timeframe as f32) / (self.scaling / (self.bounds.width/800.0))) as i64;
-
-        let visible_trades: Vec<&(DateTime<Utc>, f32, f32, bool)> = self.data_points.iter()
-            .filter(|(time, _, _, _)| {
-                let timestamp = time.timestamp_millis();
-                timestamp >= earliest && timestamp <= latest
-            })
-            .collect::<Vec<_>>();
-
-        let visible_depth = self.depth.iter()
-            .filter(|(time, _, _)| {
-                let timestamp = time.timestamp_millis();
-                timestamp >= earliest && timestamp <= latest
-            })
-            .collect::<Vec<_>>();
-
-        if visible_trades.is_empty() || visible_trades.len() < 5 {
-            return;
+    
+        let mut highest: f32 = 0.0;
+        let mut lowest: f32 = std::f32::MAX;
+    
+        for (time, bids, asks) in &self.depth {
+            let timestamp = time.timestamp_millis();
+            if timestamp >= earliest && timestamp <= latest {
+                if let Some(max_price) = asks.iter().map(|(price, _)| price).max_by(|a, b| a.partial_cmp(b).unwrap()) {
+                    highest = highest.max(*max_price);
+                }
+                if let Some(min_price) = bids.iter().map(|(price, _)| price).min_by(|a, b| a.partial_cmp(b).unwrap()) {
+                    lowest = lowest.min(*min_price);
+                }
+            }
         }
-
-        let highest = visible_depth.iter().map(|(_, bids, asks)| {
-            let highest_bid = bids.iter().map(|(price, _)| price).max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap_or(&0.0);
-            let highest_ask = asks.iter().map(|(price, _)| price).max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap_or(&0.0);
-
-            highest_bid.max(*highest_ask)
-        }).max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap_or(0.0);
-        let lowest = visible_depth.iter().map(|(_, bids, asks)| {
-            let lowest_bid = bids.iter().map(|(price, _)| price).min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap_or(&0.0);
-            let lowest_ask = asks.iter().map(|(price, _)| price).min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap_or(&0.0);
-
-            lowest_bid.min(*lowest_ask)
-        }).min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap_or(0.0);
-
+    
         if earliest != self.x_min_time || latest != self.x_max_time {            
             self.x_labels_cache.clear();
             self.x_crosshair_cache.clear();
@@ -153,7 +137,7 @@ impl Heatmap {
             self.y_labels_cache.clear();
             self.y_croshair_cache.clear();
         }
-
+    
         self.x_min_time = earliest;
         self.x_max_time = latest;
         self.y_min_price = lowest;
@@ -448,43 +432,33 @@ impl canvas::Program<Message> for Heatmap {
         bounds: Rectangle,
         cursor: mouse::Cursor,
     ) -> Vec<Geometry> {    
-        let latest = self.x_max_time;
-        let earliest = self.x_min_time;
-    
-        let (filtered_visible_trades, visible_trades) = self.data_points.iter()
-            .filter(|(time, _, _, _)| {
-                let timestamp = time.timestamp_millis();
-                timestamp >= earliest && timestamp <= latest
-            })
-            .fold((vec![], vec![]), |(mut filtered, mut visible), trade| {
-                visible.push(*trade);
-                if (trade.2 * trade.1) >= self.size_filter {
-                    filtered.push(*trade);
-                }
-                (filtered, visible)
-            });
-
-        let visible_depth: Vec<&(DateTime<Utc>, Vec<(f32, f32)>, Vec<(f32, f32)>)> = self.depth.iter()
-            .filter(|(time, _, _)| {
-                let timestamp = time.timestamp_millis();
-                timestamp >= earliest && timestamp <= latest
-            })
-            .collect::<Vec<_>>();
+        let (latest, earliest) = (self.x_max_time, self.x_min_time);    
+        let (lowest, highest) = (self.y_min_price, self.y_max_price);
 
-        let highest = self.y_max_price;
-        let lowest = self.y_min_price;
+        let y_range: f32 = highest - lowest;
 
-        let y_range = highest - lowest;
-
-        let volume_area_height = bounds.height / 8.0; 
-        let heatmap_area_height = bounds.height - volume_area_height;
+        let volume_area_height: f32 = bounds.height / 8.0; 
+        let heatmap_area_height: f32 = bounds.height - volume_area_height;
 
         let heatmap = self.heatmap_cache.draw(renderer, bounds.size(), |frame| {
+            let (filtered_visible_trades, visible_trades) = self.data_points.iter()
+                .filter(|(time, _, _, _)| {
+                    let timestamp = time.timestamp_millis();
+                    timestamp >= earliest && timestamp <= latest
+                })
+                .fold((vec![], vec![]), |(mut filtered, mut visible), trade| {
+                    visible.push(*trade);
+                    if (trade.2 * trade.1) >= self.size_filter {
+                        filtered.push(*trade);
+                    }
+                    (filtered, visible)
+                });
+            
             // volume bars
             let mut aggregated_volumes: HashMap<i64, (f32, f32)> = HashMap::new();
             for &(time, _, qty, is_sell) in &visible_trades {
                 let timestamp = time.timestamp_millis();
-                aggregated_volumes.entry(timestamp).and_modify(|e| {
+                aggregated_volumes.entry(timestamp).and_modify(|e: &mut (f32, f32)| {
                     if is_sell {
                         e.1 += qty;
                     } else {
@@ -535,15 +509,22 @@ impl canvas::Program<Message> for Heatmap {
             }
             
             // orderbook heatmap
+            let visible_depth: Vec<&(DateTime<Utc>, Vec<(f32, f32)>, Vec<(f32, f32)>)> = self.depth.iter()
+                .filter(|(time, _, _)| {
+                    let timestamp = time.timestamp_millis();
+                    timestamp >= earliest && timestamp <= latest
+                })
+                .collect::<Vec<_>>();
+
             let max_order_quantity = visible_depth.iter()
                 .map(|(_, bids, asks)| {
                 bids.iter().map(|(_, qty)| qty).chain(asks.iter().map(|(_, qty)| qty)).fold(f32::MIN, |current_max: f32, qty: &f32| f32::max(current_max, *qty))
             }).fold(f32::MIN, f32::max);
             for i in 0..20 { 
-                let bids_i: Vec<(DateTime<Utc>, f32, f32)> = visible_depth.iter()
-                    .map(|&(time, bid, _ask)| ((*time).clone(), bid[i].0, bid[i].1)).collect();
-                let asks_i: Vec<(DateTime<Utc>, f32, f32)> = visible_depth.iter()
-                    .map(|&(time, _bid, ask)| ((*time).clone(), ask[i].0, ask[i].1)).collect();
+                let bids_i: Vec<(&DateTime<Utc>, f32, f32)> = visible_depth.iter()
+                    .map(|&(time, bid, _ask)| (time, bid[i].0, bid[i].1)).collect();
+                let asks_i: Vec<(&DateTime<Utc>, f32, f32)> = visible_depth.iter()
+                    .map(|&(time, _bid, ask)| (time, ask[i].0, ask[i].1)).collect();
 
                 bids_i.iter().zip(asks_i.iter()).for_each(|((time, bid_price, bid_qty), (_, ask_price, ask_qty))| {
                     let bid_y_position = heatmap_area_height - ((bid_price - lowest) / y_range * heatmap_area_height);
@@ -557,7 +538,6 @@ impl canvas::Program<Message> for Heatmap {
                     let bid_circle = Path::circle(Point::new(x_position as f32, bid_y_position), 1.0);
                     frame.fill(&bid_circle, Color::from_rgba8(0, 144, 144, bid_color_alpha));
 
-
                     let ask_circle = Path::circle(Point::new(x_position as f32, ask_y_position), 1.0);
                     frame.fill(&ask_circle, Color::from_rgba8(192, 0, 192, ask_color_alpha));
                 });