Skip to content

Commit 2b51e3b

Browse files
committed
Optimize several key Viewer::Tree routines
These add up to several times faster handling of very large trees. Also add timing info for major cache refills when $*DEBUG is set.
1 parent 6f9237c commit 2b51e3b

File tree

1 file changed

+37
-20
lines changed

1 file changed

+37
-20
lines changed

lib/Terminal/Widgets/Viewer/Tree.rakumod

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ my role DisplayNode {
1919
}
2020

2121
my class DisplayLeaf does DisplayNode {
22-
method branch-size(--> 1) { }
22+
method expanded(--> False) { }
23+
method branch-size(--> 1) { }
2324
}
2425

2526
my class DisplayParent does DisplayNode {
@@ -85,10 +86,24 @@ class Terminal::Widgets::Viewer::Tree
8586

8687
# Auto-cache flattened nodes and displayable lines
8788
method flat-node-cache() {
88-
@!flat-node-cache ||= self.flattened-nodes($!display-root);
89+
@!flat-node-cache ||= do {
90+
my $debug = +($*DEBUG // 0);
91+
my $t0 = now;
92+
self.flattened-nodes($!display-root, my @n);
93+
note sprintf("flattened-nodes: %.3fms (%d elems)",
94+
1000 * (now - $t0), @n.elems) if $debug;
95+
@n
96+
}
8997
}
9098
method flat-line-cache() {
91-
@!flat-line-cache ||= self.node-lines($!display-root);
99+
@!flat-line-cache ||= do {
100+
my $debug = +($*DEBUG // 0);
101+
my $t0 = now;
102+
self.node-lines($!display-root, my @l);
103+
note sprintf("node-lines: %.3fms (%d elems)",
104+
1000 * (now - $t0), @l.elems) if $debug;
105+
@l
106+
}
92107
}
93108
method max-line-width() {
94109
$!max-line-width ||= do {
@@ -124,29 +139,31 @@ class Terminal::Widgets::Viewer::Tree
124139
!! @lines[$start .. *]
125140
}
126141

127-
#| Displayable lines for a given node
128-
method node-lines($node) {
129-
my $is-parent = $node ~~ DisplayParent && $node.expanded;
130-
my $first-line = [ self.prefix-string($node),
131-
self.node-content($node) ];
132-
133-
$is-parent ?? ($first-line,
134-
$node.children.map({ self.node-lines($_).Slip })).flat
135-
!! ($first-line, )
142+
#| Flatten displayable lines for a given node into array @lines
143+
method node-lines($node, @lines) {
144+
@lines.push: [ self.prefix-string($node),
145+
self.node-content($node) ];
146+
if $node.expanded {
147+
self.node-lines($_, @lines) for $node.children;
148+
}
136149
}
137150

138-
#| Flat list of displayable nodes starting at a given node
139-
method flattened-nodes($node) {
140-
my $is-parent = $node ~~ DisplayParent && $node.expanded;
141-
$is-parent ?? ($node, |$node.children.map({ self.flattened-nodes($_).Slip }))
142-
!! ($node, )
151+
#| Flatten displayable nodes starting at a given node into array @nodes
152+
method flattened-nodes($node, @nodes) {
153+
@nodes.push: $node;
154+
if $node.expanded {
155+
self.flattened-nodes($_, @nodes) for $node.children;
156+
}
143157
}
144158

145159
#| Prefix for first line of a given node
146160
method prefix-string($node) {
147-
span('', ' ' x $node.depth
148-
~ ($node ~~ DisplayParent ?? self.arrows()[+$node.expanded] !! ' ')
149-
~ ' ')
161+
state @prefix-cache;
162+
my $expanded = $node ~~ DisplayParent ?? +$node.expanded !! 2;
163+
@prefix-cache[$node.depth][$expanded] //=
164+
span('', ' ' x $node.depth
165+
~ ($node ~~ DisplayParent ?? self.arrows()[+$node.expanded] !! ' ')
166+
~ ' ')
150167
}
151168

152169
#| Displayed content for a given node itself, not including children

0 commit comments

Comments
 (0)