Skip to content

Commit 14d452f

Browse files
committed
Remove extra lookups and memory allocations from tsort graph construction
1 parent 0ccc67f commit 14d452f

File tree

2 files changed

+15
-19
lines changed

2 files changed

+15
-19
lines changed

src/uu/tsort/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ clap = { workspace = true }
2222
thiserror = { workspace = true }
2323
uucore = { workspace = true }
2424
fluent = { workspace = true }
25+
itertools = {workspace = true }
2526

2627
[[bin]]
2728
name = "tsort"

src/uu/tsort/src/tsort.rs

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use uucore::{format_usage, show};
1414

1515
use uucore::translate;
1616

17+
use itertools::Itertools;
18+
1719
mod options {
1820
pub const FILE: &str = "file";
1921
}
@@ -63,11 +65,15 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
6365

6466
// Create the directed graph from pairs of tokens in the input data.
6567
let mut g = Graph::new(input.to_string_lossy().to_string());
66-
for ab in data.split_whitespace().collect::<Vec<&str>>().chunks(2) {
67-
match ab {
68-
[a, b] => g.add_edge(a, b),
69-
_ => return Err(TsortError::NumTokensOdd(input.to_string_lossy().to_string()).into()),
70-
}
68+
for mut ab in &data.split_whitespace().chunks(2) {
69+
let a = ab.next();
70+
let b = ab.next();
71+
72+
let Some((a, b)) = a.zip(b) else {
73+
return Err(TsortError::NumTokensOdd(input.to_string_lossy().to_string()).into());
74+
};
75+
76+
g.add_edge(a, b);
7177
}
7278

7379
g.run_tsort();
@@ -127,19 +133,11 @@ impl<'input> Graph<'input> {
127133
}
128134
}
129135

130-
fn add_node(&mut self, name: &'input str) {
131-
self.nodes.entry(name).or_default();
132-
}
133-
134136
fn add_edge(&mut self, from: &'input str, to: &'input str) {
135-
self.add_node(from);
137+
let from_node = self.nodes.entry(from).or_default();
136138
if from != to {
137-
self.add_node(to);
138-
139-
let from_node = self.nodes.get_mut(from).unwrap();
140139
from_node.add_successor(to);
141-
142-
let to_node = self.nodes.get_mut(to).unwrap();
140+
let to_node = self.nodes.entry(to).or_default();
143141
to_node.predecessor_count += 1;
144142
}
145143
}
@@ -233,10 +231,7 @@ impl<'input> Graph<'input> {
233231

234232
fn detect_cycle(&self) -> Vec<&'input str> {
235233
// Sort the nodes just to make this function deterministic.
236-
let mut nodes = Vec::new();
237-
for node in self.nodes.keys() {
238-
nodes.push(node);
239-
}
234+
let mut nodes: Vec<_> = self.nodes.keys().copied().collect();
240235
nodes.sort_unstable();
241236

242237
let mut visited = HashSet::new();

0 commit comments

Comments
 (0)