This is untested! You'll need to check it carefully.
First thing to look at is the inner loop. And the first thing I noticed there is that these lines are loop invariant.
$destRow = $current->{'rowTop'} + $row - 2;
if ($destRow>$screen->{'height'})
{
$destRow = $screen->{'height'};
}
(Ie They do not vary with the value of the inner loop counter), so they should be moved outside.
Next, these three lines respectively:
$backAtt[$destRow][$destCol] =
$current->{'backAtt'}[$row - 1][$col - 1];
$self->{'zBuffer'}[$destRow][$destCol] = $active;
substr($backTxt[$destRow], $destCol, 1) =
substr($current->{'backTxt'}[$row - 1],$col - 1, 1);
- Copy a slice of an array element by element;
Which can be done more efficiently by an array slice assignment.
- Assign to an array slice element-wise.
Again, an array slice assignment.
- Copy a substr byte-wise.
Can be replaced by a single substring assigment.
For that to happen, you need to calculate the source and destination start points and the width.
- Source start is just 0
- Destination start is {colTop} - 1
- Width is min( $screen->{width}, $current->{colTop} + $screen->{width} - 2 ) - destination start.
Putting that together I get:
sub makeFullBackBuffer {
my ($self) = @_;
my (@backAtt, @backTxt, $screen, $current, $destCol, $destRow, $ac
+tive);
$screen = $self->{miniwin}[ 0 ];
for( 1 .. $screen->{height} ) {
push @backTxt, ' ' x $screen->{width};
push @backAtt, [ (0) x $screen->{width} ];
}
for $active (reverse @{ $self->{winStack} } ) {
$current = $self->{miniwin}[ $active ];
for my $row ( 1 .. $current->{height} ) {
$destRow = $current->{rowTop} + $row - 2;
$destRow = $screen->{height} if $destRow>$screen->{height}
+;
my $colMin = $current->{colTop} - 1;
my $colMax = min(
$screen->{width},
$current->{colTop} + $screen->{width} - 2
);
my $cols = $colMax - $colMin +1;
@{ $backAtt[ $destRow ] }[ $colMin .. $colMax ]
+
= @{ $current->{backAtt}[ $row - 1 ] }[ 0 .. cols ]
+;
@{ $self->{zBuffer}[$destRow] }[ $colMin .. $colMax ]
= ( $active ) x $cols;
substr( $backTxt[ $destRow ], $colMin, $cols )
= substr( $current->{backTxt}[ $row - 1 ], 0, $cols );
}
}
return \( @backAtt, @backTxt );
}
Looking at that, I see that you could simplify the $destRow also, but as-is--assuming my logic is not too screwed, you could (maybe) see an order of magnitude improvement through the elimination of the inner loop.
Update:One thing you might consider is that Win32::Console gives access to the console apis and they allow the attachment of mutliple buffers to a screen which can be switched very quickly. The api also provides primatives for copying rectangular windows of both text and attributes (and introspection), which would be far more efficient than the role-your-own equivalents in the module you're using--but the switchover would probably involve a considerable amount of work.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
|