-
-
Save kaisersparpick/a49930795e9f505c5924cbddb8a5aa49 to your computer and use it in GitHub Desktop.
constant width = 80; | |
my Int $total-lines = 0; | |
my Int $total-words = 0; | |
my $excludes = set <cache css data node_modules vendor views>; | |
sub say-so($name, $lines, $words) { say sprintf('%-60.s | %5.d | %6.d', $name, $lines, $words) } | |
sub count-stuff(Str $dir) { | |
my Int $subtotal-lines = 0; | |
my Int $subtotal-words = 0; | |
sub doit($dir) { | |
for dir $dir -> $file { | |
if ($file.IO.f && $file.IO.extension eq 'js') { | |
my Int $lines = $file.IO.open.lines.elems; | |
my Int $words = $file.IO.open.words.elems; | |
$subtotal-lines += $lines; | |
$subtotal-words += $words; | |
say-so($file, $lines, $words); | |
} | |
elsif ($file.IO.d && $file.IO.basename ∉ $excludes ) { | |
doit($file); | |
} | |
} | |
} | |
doit($dir); | |
say '-' x width; | |
say-so('Subtotal', $subtotal-lines, $subtotal-words); | |
say ''; | |
$total-lines += $subtotal-lines; | |
$total-words += $subtotal-words; | |
} | |
my $start = now; | |
count-stuff('/home/user/project1'); | |
count-stuff('/home/user/project2'); | |
say '=' x width; | |
say-so('Total', $total-lines, $total-words); | |
my $stop = now; | |
say ''; | |
say "start: $start, stop: $stop, diff: {$stop-$start}"; |
Why do you open and read the contents of the file twice?
my Int $lines = $file.IO.open.lines.elems;
my Int $words = $file.IO.open.words.elems;
Also I think .open.lines
leaves the file open until it gets garbage collected, so it is probably better to leave off the .open
and just call .lines
.
There is no reason to keep calling .IO
on $file
, as dir
returns IO::Path objects.
I would loop over the lines read, and use that to get both counts at the same time.
my Int $lines;
my Int $words;
for $file.lines {
++$lines;
$words += .words
}
$subtotal-lines += $lines;
$subtotal-words += $words;
Or perhaps use map
with a race
thrown in as it probably wouldn't hurt.
my @result = $file.lines.race.map: *.words.elems;
my Int $lines = @result.elems;
my Int $words = @result.sum;
$subtotal-lines += $lines;
$subtotal-words += $words;
Assuming the number of words and lines will fit into an atomicint
, you could try doing it this way:
my atomicint $lines;
my atomicint $words;
race for $file.lines {
$lines⚛++; # atomic-inc-fetch( $lines );
$words ⚛+= .words; # atomic-fetch-add( $words, .words );
}
$subtotal-lines += $lines;
$subtotal-words += $words;
Rather than incrementing $lines
, you could just count the iterations.
my atomicint $words;
my Int $lines = +do race for $file.lines {
$words ⚛+= .words; # atomic-fetch-add( $words, .words );
}
$subtotal-lines += $lines;
$subtotal-words += $words;
You may want to do some testing to see which is the fastest.
b2gills: Thanks a bunch for your feedback! Much appreciated. I'm still in the phase of learning how IO operations work in P6.
Interesting ways of doing the same thing. I've tried the above suggestions and here are my findings.
Initial run:
start: Instant:1532009937.977974, stop: Instant:1532010033.088108, diff: 95.1101349
do
start: Instant:1532008874.049037, stop: Instant:1532008874.557006, diff: 0.5079693
race
start: Instant:1532009239.234297, stop: Instant:1532009239.735399, diff: 0.5011022
atomic
start: Instant:1532008968.334444, stop: Instant:1532008968.837879, diff: 0.503434
P5
start: 1531915523.57893, stop: 1531915523.61466, diff: 0.0357320308685303
P6
start: Instant:1531911842.580733, stop: Instant:1531911843.004005, diff: 0.4232726
start: Instant:1531915946.321035, stop: Instant:1531916051.987524, diff: 105.6664888