Explorar o código

event_graph: iterative dfs_topological_sort() instead of recursion

dasman %!s(int64=2) %!d(string=hai) anos
pai
achega
d2970c8895
Modificáronse 1 ficheiros con 37 adicións e 32 borrados
  1. 37 32
      src/event_graph/mod.rs

+ 37 - 32
src/event_graph/mod.rs

@@ -24,7 +24,6 @@ use std::{
     time::Duration,
 };
 
-use async_recursion::async_recursion;
 use darkfi_serial::{deserialize_async, serialize_async};
 use log::{debug, error, info, warn};
 use num_bigint::BigUint;
@@ -755,52 +754,58 @@ impl EventGraph {
             }
         }
 
-        ordered_events.make_contiguous().to_vec()
+        let mut ordered_events = ordered_events.make_contiguous().to_vec();
+        ordered_events.reverse();
+        ordered_events
     }
 
-    /// We do a DFS (<https://en.wikipedia.org/wiki/Depth-first_search>), and
-    /// additionally we consider the timestamps.
-    #[async_recursion]
+    /// We do a non-recursive DFS (<https://en.wikipedia.org/wiki/Depth-first_search>),
+    /// and additionally we consider the timestamps.
     async fn dfs_topological_sort(
         &self,
         event: Event,
         visited: &mut HashSet<blake3::Hash>,
         ordered_events: &mut VecDeque<blake3::Hash>,
     ) {
+        let mut stack = VecDeque::new();
         let event_id = event.id();
-        visited.insert(event_id);
-
-        for parent_id in event.parents.iter() {
-            if !visited.contains(parent_id) && parent_id != &NULL_ID {
-                let p_event = self.dag_get(parent_id).await.unwrap().unwrap();
-                self.dfs_topological_sort(p_event, visited, ordered_events).await;
-            }
-        }
+        stack.push_back(event_id);
+
+        while let Some(event_id) = stack.pop_front() {
+            if !visited.contains(&event_id) && event_id != NULL_ID {
+                visited.insert(event_id);
+                if let Some(event) = self.dag_get(&event_id).await.unwrap() {
+                    for parent in event.parents.iter() {
+                        stack.push_back(*parent);
+                    }
 
-        // Before inserting, check timestamps to determine the correct position.
-        let mut pos = ordered_events.len();
-        for (idx, existing_id) in ordered_events.iter().enumerate().rev() {
-            assert!(existing_id != &NULL_ID);
-            if self.share_same_parents(&event_id, existing_id).await {
-                let existing_event = self.dag_get(existing_id).await.unwrap().unwrap();
-
-                // Sort by timestamp
-                match event.timestamp.cmp(&existing_event.timestamp) {
-                    Ordering::Less => pos = idx,
-                    Ordering::Equal => {
-                        // In case of a tie-breaker, use the event ID
-                        let a = BigUint::from_bytes_be(event_id.as_bytes());
-                        let b = BigUint::from_bytes_be(existing_id.as_bytes());
-                        if a < b {
-                            pos = idx;
+                    // Before inserting, check timestamps to determine the correct position.
+                    let mut pos = ordered_events.len();
+                    for (idx, existing_id) in ordered_events.iter().enumerate() {
+                        assert!(existing_id != &NULL_ID);
+                        if self.share_same_parents(&event_id, existing_id).await {
+                            let existing_event = self.dag_get(existing_id).await.unwrap().unwrap();
+
+                            // Sort by timestamp
+                            match event.timestamp.cmp(&existing_event.timestamp) {
+                                Ordering::Less => pos = idx,
+                                Ordering::Equal => {
+                                    // In case of a tie-breaker, use the event ID
+                                    let a = BigUint::from_bytes_be(event_id.as_bytes());
+                                    let b = BigUint::from_bytes_be(existing_id.as_bytes());
+                                    if a < b {
+                                        pos = idx;
+                                    }
+                                }
+                                _ => {}
+                            }
                         }
                     }
-                    _ => {}
+
+                    ordered_events.insert(pos, event_id);
                 }
             }
         }
-
-        ordered_events.insert(pos, event_id);
     }
 
     /// Check if two events have the same parents