Skip to content

Instantly share code, notes, and snippets.

@jonathan-beard
Last active August 29, 2015 14:04
Show Gist options
  • Save jonathan-beard/10e2916d228165d050a7 to your computer and use it in GitHub Desktop.
Save jonathan-beard/10e2916d228165d050a7 to your computer and use it in GitHub Desktop.
Stupid simple script to get leaks on programs running on OS X...doesn't quite parse the output of ps -A correctly but I don't have time to fix right now and it works well enough to be used.
#!/usr/bin/env perl
use strict;
use warnings;
##
# getProcessList - returns an array of an arrays
# first index is the pid, second the executable
# it refers to
##
sub getProcessList();
##
# runLeaks - writes the output of the "leaks" exe
# for each of the pids returned from getProcessList()
# first param is the process list, second param is
# the filename
##
sub runLeaks( $$ );
##
# processOutput - simply parses the output of the OS X 'leaks'
# exe (which it takes as the input param).
##
sub processOutput( $ );
###
# actual program starts here
###
if( ( 0 + @ARGV ) != 1 )
{
print STDERR "Must provide an outputfile for leak stats as argument, e.g.,\n./findleaks.pl outputfile.csv\nexiting!!\n";
exit( -1 );
}
my ($filename) = @ARGV;
my $processList = getProcessList();
runLeaks( $processList, $filename );
exit( 0 );
##
# start subroutines
##
sub getProcessList()
{
my @rawlist = split/\n/, `ps -A`;
##
# Discard heading
##
shift( @rawlist );
my @output;
foreach my $line( @rawlist )
{
my @fields = split /\s+/, $line;
my $pid = 0;
my $exe = "";
my $index = 0;
while ( ! $pid =~ m/\d+/ )
{
$pid = shift( @fields );
}
$exe = pop( @fields );
push( @output, [ $pid, $exe ]);
}
return( \@output );
}
sub runLeaks( $$ )
{
my ($list, $outputfile) = @_;
open(OUTPUT, ">", $outputfile) or die "Couldn't open $outputfile\n";
foreach my $info (@$list)
{
my $pid = $info->[ 0 ];
my $data = "";
$data = `leaks $pid 2> /dev/null`;
if( ! $data eq "" )
{
my $usefulLine = "";
$usefulLine = processOutput( $data );
print OUTPUT "$usefulLine\n";
print OUTPUT join('', "#" x 80 )."\n";
}
}
close( OUTPUT );
}
sub processOutput( $ )
{
my ($leak) = @_;
my @lines = split /\n/, $leak;
my $output = "";
foreach my $line ( @lines )
{
if( $line =~ m/leaks for/ || $line=~ m/leak for/ )
{
$output .= $line;
return( $output );
}
elsif( $line =~ m/Path: / )
{
$output .= $line."\n";
}
}
}
@jonathan-beard
Copy link
Author

Extremely quick (as in I wrote it quickly) to find memory leaks on OS X. I finally found mine in some plugins that were eventually consuming all my memory. To run it on all processes you'll have to use 'sudo' to execute it as in 'sudo ./findleaks.pl outputFileName'. To execute it you'll have to make it executable with 'chmod u+x findleaks.pl'. One of these days I might write a bit better one, but this worked for me.

@jonathan-beard
Copy link
Author

Accidentally took out the new line...added it back in.

@jonathan-beard
Copy link
Author

Updated to throw an error when output file is not given, other than that error checking is rather basic with corner cases more than likely causing undefined behavior.

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