Skip to content

Commit 4c7cbb4

Browse files
authored
perf!: move depth computation from visualizer to tree builder (#281)
BREAKING: * `TreeBuilder` and `FsTreeBuilder` now asks for `max_depth`. * `Visualizer::max_depth` has been removed. * The types of some `max_depth` fields have been changed from `NonZeroUsize` to `NonZeroU64`. COMMITS: * feat(api): add `max_depth` to the tree builder * feat(api): remove `max_depth` from visualizer * fix: pass the correct `max_depth` into children * docs: add a todo * feat(api): pass `current_depth` to `retain`'s' callback * test: fix * docs: fix * docs: remove a todo * docs: better sentence flow * feat(api)!: replace `NonZeroUsize` with `NonZeroU64`
1 parent 879ee7d commit 4c7cbb4

File tree

18 files changed

+75
-73
lines changed

18 files changed

+75
-73
lines changed

src/app.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ impl App {
5757
bytes_format,
5858
top_down,
5959
align_right,
60-
max_depth,
6160
..
6261
} = self.args;
6362
let direction = Direction::from_top_down(top_down);
@@ -79,7 +78,6 @@ impl App {
7978
column_width_distribution,
8079
direction,
8180
bar_alignment,
82-
max_depth,
8381
}
8482
.to_string()
8583
}};

src/app/sub.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
visualizer::{BarAlignment, ColumnWidthDistribution, Direction, Visualizer},
1313
};
1414
use serde::Serialize;
15-
use std::{io::stdout, iter::once, num::NonZeroUsize, path::PathBuf};
15+
use std::{io::stdout, iter::once, num::NonZeroU64, path::PathBuf};
1616

1717
/// The sub program of the main application.
1818
pub struct Sub<Size, SizeGetter, Report>
@@ -35,7 +35,7 @@ where
3535
/// Distribution and number of characters/blocks can be placed in a line.
3636
pub column_width_distribution: ColumnWidthDistribution,
3737
/// Maximum number of levels that should be visualized.
38-
pub max_depth: NonZeroUsize,
38+
pub max_depth: NonZeroU64,
3939
/// [Get the size](GetSize) of files/directories.
4040
pub size_getter: SizeGetter,
4141
/// Reports measurement progress.
@@ -76,6 +76,7 @@ where
7676
reporter: &reporter,
7777
root,
7878
size_getter,
79+
max_depth: max_depth.get(),
7980
}
8081
.into()
8182
});
@@ -100,6 +101,7 @@ where
100101
OsStringDisplay::os_string_from("(total)"),
101102
Size::default(),
102103
children,
104+
max_depth.get(),
103105
)
104106
};
105107

@@ -142,7 +144,6 @@ where
142144
direction,
143145
bar_alignment,
144146
column_width_distribution,
145-
max_depth,
146147
};
147148

148149
print!("{visualizer}"); // visualizer already ends with "\n", println! isn't needed here.

src/args.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pub use threads::Threads;
88

99
use crate::{bytes_format::BytesFormat, visualizer::ColumnWidthDistribution};
1010
use clap::{ColorChoice, Parser};
11-
use std::{num::NonZeroUsize, path::PathBuf};
11+
use std::{num::NonZeroU64, path::PathBuf};
1212
use terminal_size::{terminal_size, Width};
1313
use text_block_macros::text_block;
1414

@@ -105,7 +105,7 @@ pub struct Args {
105105

106106
/// Maximum depth to display the data (must be greater than 0).
107107
#[clap(long, default_value = "10")]
108-
pub max_depth: NonZeroUsize,
108+
pub max_depth: NonZeroU64,
109109

110110
/// Width of the visualization.
111111
#[clap(long, conflicts_with = "column_width")]

src/data_tree/constructors.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ use crate::size;
33

44
impl<Name, Size: size::Size> DataTree<Name, Size> {
55
/// Create a tree representation of a directory.
6-
pub fn dir(name: Name, inode_size: Size, children: Vec<Self>) -> Self {
6+
pub fn dir(name: Name, inode_size: Size, children: Vec<Self>, depth: u64) -> Self {
77
let size = inode_size + children.iter().map(DataTree::size).sum();
8+
let children = if depth > 0 { children } else { Vec::new() };
89
DataTree {
910
name,
1011
size,
@@ -26,6 +27,6 @@ impl<Name, Size: size::Size> DataTree<Name, Size> {
2627
where
2728
Size: Copy,
2829
{
29-
move |name, children| DataTree::dir(name, inode_size, children)
30+
move |name, children| DataTree::dir(name, inode_size, children, 1)
3031
}
3132
}

src/data_tree/retain.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,30 @@ where
77
Self: Send,
88
Size: size::Size,
99
{
10-
/// Recursively cull all descendants that do not satisfy given `predicate`, in parallel.
11-
pub fn par_retain(&mut self, predicate: impl Fn(&Self) -> bool + Copy + Sync) {
12-
self.children.retain(predicate);
10+
/// Internal function to be used by [`Self::par_retain`].
11+
fn par_retain_with_depth(
12+
&mut self,
13+
current_depth: u64,
14+
predicate: impl Fn(&Self, u64) -> bool + Copy + Sync,
15+
) {
16+
self.children
17+
.retain(|child| predicate(child, current_depth));
18+
let next_depth = current_depth + 1;
1319
self.children
1420
.par_iter_mut()
15-
.for_each(|child| child.par_retain(predicate));
21+
.for_each(|child| child.par_retain_with_depth(next_depth, predicate))
22+
}
23+
24+
/// Recursively cull all descendants that do not satisfy given `predicate`, in parallel.
25+
pub fn par_retain(&mut self, predicate: impl Fn(&Self, u64) -> bool + Copy + Sync) {
26+
self.par_retain_with_depth(0, predicate)
1627
}
1728

1829
/// Process the tree via [`par_retain`](Self::par_retain) method.
19-
pub fn into_par_retained(mut self, predicate: impl Fn(&Self) -> bool + Copy + Sync) -> Self {
30+
pub fn into_par_retained(
31+
mut self,
32+
predicate: impl Fn(&Self, u64) -> bool + Copy + Sync,
33+
) -> Self {
2034
self.par_retain(predicate);
2135
self
2236
}
@@ -28,7 +42,7 @@ where
2842
Size: Into<u64>,
2943
{
3044
let minimal = self.size().into() as f32 * min_ratio;
31-
self.par_retain(|descendant| descendant.size().into() as f32 >= minimal);
45+
self.par_retain(|descendant, _| descendant.size().into() as f32 >= minimal);
3246
}
3347

3448
/// Process the tree via [`par_cull_insignificant_data`](Self::par_cull_insignificant_data) method.

src/data_tree/retain/test.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ type SampleData = Bytes;
77
type SampleTree = DataTree<SampleName, SampleData>;
88

99
fn dir<const INODE_SIZE: u64>(name: &'static str, children: Vec<SampleTree>) -> SampleTree {
10-
SampleTree::dir(name.to_string(), INODE_SIZE.into(), children)
10+
SampleTree::dir(name.to_string(), INODE_SIZE.into(), children, 10)
1111
}
1212

1313
fn file(name: &'static str, size: u64) -> SampleTree {
@@ -23,6 +23,7 @@ fn culled_dir<const INODE_SIZE: u64>(
2323
name.to_string(),
2424
(INODE_SIZE + culled_size).into(),
2525
children,
26+
10,
2627
)
2728
}
2829

@@ -156,7 +157,7 @@ fn edge_cases() {
156157
),
157158
],
158159
)
159-
.into_par_retained(|descendant| descendant.name().starts_with('!').not())
160+
.into_par_retained(|descendant, _| descendant.name().starts_with('!').not())
160161
.into_reflection();
161162
let expected = dir(
162163
"root",

src/fs_tree_builder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use std::{
2929
/// root: std::env::current_dir().unwrap(),
3030
/// size_getter: GetApparentSize,
3131
/// reporter: ErrorOnlyReporter::new(ErrorReport::SILENT),
32+
/// max_depth: 10,
3233
/// };
3334
/// let data_tree: DataTree<OsStringDisplay, Bytes> = builder.into();
3435
/// ```
@@ -45,6 +46,8 @@ where
4546
pub size_getter: SizeGetter,
4647
/// Reports progress to external system.
4748
pub reporter: Report,
49+
/// Deepest level of descendent display in the graph. The sizes beyond the max depth still count toward total.
50+
pub max_depth: u64,
4851
}
4952

5053
impl<Size, SizeGetter, Report> From<FsTreeBuilder<Size, SizeGetter, Report>>
@@ -60,6 +63,7 @@ where
6063
root,
6164
size_getter,
6265
reporter,
66+
max_depth,
6367
} = builder;
6468

6569
TreeBuilder::<PathBuf, OsStringDisplay, Size, _, _> {
@@ -118,6 +122,8 @@ where
118122
},
119123

120124
join_path: |prefix, name| prefix.join(&name.0),
125+
126+
max_depth,
121127
}
122128
.into()
123129
}

src/tree_builder.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ where
2323
pub get_info: GetInfo,
2424
/// Function to join parent's `path` with a child's name to make the child's `name`.
2525
pub join_path: JoinPath,
26+
/// Deepest level of descendent to store as arrays. The sizes beyond the max depth still count toward total.
27+
pub max_depth: u64,
2628
}
2729

2830
impl<Path, Name, Size, GetInfo, JoinPath> From<TreeBuilder<Path, Name, Size, GetInfo, JoinPath>>
@@ -41,9 +43,11 @@ where
4143
name,
4244
get_info,
4345
join_path,
46+
max_depth,
4447
} = builder;
4548

4649
let Info { size, children } = get_info(&path);
50+
let max_depth = max_depth.saturating_sub(1);
4751

4852
let children: Vec<_> = children
4953
.into_par_iter()
@@ -52,10 +56,11 @@ where
5256
name,
5357
get_info,
5458
join_path,
59+
max_depth,
5560
})
5661
.map(Self::from)
5762
.collect();
5863

59-
DataTree::dir(name, size, children)
64+
DataTree::dir(name, size, children, max_depth)
6065
}
6166
}

src/visualizer.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub use proportion_bar::{ProportionBar, ProportionBarBlock};
1515
pub use tree::{TreeHorizontalSlice, TreeSkeletalComponent};
1616

1717
use super::{data_tree::DataTree, size};
18-
use std::{fmt::Display, num::NonZeroUsize};
18+
use std::fmt::Display;
1919

2020
/// Visualize a [`DataTree`].
2121
///
@@ -38,7 +38,6 @@ use std::{fmt::Display, num::NonZeroUsize};
3838
/// direction: Direction::BottomUp,
3939
/// bar_alignment: BarAlignment::Right,
4040
/// column_width_distribution: ColumnWidthDistribution::total(100),
41-
/// max_depth: std::num::NonZeroUsize::new(10).unwrap(),
4241
/// };
4342
/// println!("{visualizer}");
4443
/// # }
@@ -59,8 +58,6 @@ where
5958
pub bar_alignment: BarAlignment,
6059
/// Distribution and total number of characters/blocks can be placed in a line.
6160
pub column_width_distribution: ColumnWidthDistribution,
62-
/// Maximum number of levels that should be visualized.
63-
pub max_depth: NonZeroUsize,
6461
}
6562

6663
mod copy;

src/visualizer/methods/initial_table.rs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ where
4646
{
4747
#[derive(Clone)]
4848
struct Param<Name, NodeData> {
49-
remaining_depth: usize,
5049
index_as_child: usize,
5150
ancestors: Vec<NodeInfo<Name, NodeData>>,
5251
preceding_sibling: Option<NodeInfo<Name, NodeData>>,
@@ -69,11 +68,7 @@ where
6968
Size: size::Size,
7069
Act: FnMut(&'a DataTree<Name, Size>, Param<&'a Name, Size>) -> ActResult<&'a Name, Size>,
7170
{
72-
if param.remaining_depth == 0 {
73-
return None;
74-
}
7571
let ActResult { node_info } = act(tree, param.clone());
76-
let remaining_depth = param.remaining_depth - 1;
7772
let mut preceding_sibling = None;
7873
for (index_as_child, child) in tree.children().iter().enumerate() {
7974
let mut ancestors = Vec::with_capacity(param.ancestors.len() + 1);
@@ -83,7 +78,6 @@ where
8378
child,
8479
act,
8580
Param {
86-
remaining_depth,
8781
index_as_child,
8882
ancestors,
8983
preceding_sibling,
@@ -103,18 +97,12 @@ where
10397
let Param {
10498
index_as_child,
10599
ancestors,
106-
remaining_depth,
107100
preceding_sibling,
108101
} = param;
109102
let name = node.name();
110103
let node_data = node.size();
111104
let row_index = initial_table.len();
112-
debug_assert_op!(remaining_depth > 0);
113-
let children_count = if remaining_depth != 1 {
114-
node.children().len()
115-
} else {
116-
0
117-
};
105+
let children_count = node.children().len();
118106
let fs_size = node.size().into();
119107
let percentage = if total_fs_size == 0 {
120108
"0%".to_string()
@@ -134,7 +122,6 @@ where
134122
sibling_count,
135123
index_as_child,
136124
children_count,
137-
remaining_depth,
138125
};
139126

140127
initial_table.column_width.size_column_width =
@@ -151,7 +138,6 @@ where
151138
ActResult { node_info }
152139
},
153140
Param {
154-
remaining_depth: visualizer.max_depth.get(),
155141
index_as_child: 0,
156142
ancestors: Vec::new(),
157143
preceding_sibling: None,

0 commit comments

Comments
 (0)