Skip to content

Instantly share code, notes, and snippets.

@kaisersparpick
Last active July 20, 2018 18:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kaisersparpick/a49930795e9f505c5924cbddb8a5aa49 to your computer and use it in GitHub Desktop.
Save kaisersparpick/a49930795e9f505c5924cbddb8a5aa49 to your computer and use it in GitHub Desktop.
count
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}";
@kaisersparpick
Copy link
Author

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

@b2gills
Copy link

b2gills commented Jul 19, 2018

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.

@kaisersparpick
Copy link
Author

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

@kaisersparpick
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment