-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#138] Add stackcollapse script for visual studio profiles
- Loading branch information
1 parent
a93d905
commit 51f96b3
Showing
2 changed files
with
99 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#!/usr/bin/perl -w | ||
# | ||
# stackcollapse-vsprof.pl | ||
# | ||
# Parses the CSV file containing a call tree from a visual studio profiler and produces an output suitable for flamegraph.pl. | ||
# | ||
# USAGE: perl stackcollapse-vsprof.pl infile > outfile | ||
# | ||
# WORKFLOW: | ||
# | ||
# This example assumes you have visual studio 2015 installed. | ||
# | ||
# 1. Profile C++ your application using visual studio | ||
# 2. On visual studio, choose export the call tree as csv | ||
# 3. Generate a flamegraph: perl stackcollapse-vsprof CallTreeSummary.csv | perl flamegraph.pl > result_vsprof.svg | ||
# | ||
# INPUT EXAMPLE : | ||
# | ||
# Level,Function Name,Inclusive Samples,Exclusive Samples,Inclusive Samples %,Exclusive Samples %,Module Name, | ||
# 1,"main","8,735",0,100.00,0.00,"an_executable.exe", | ||
# 2,"testing::UnitTest::Run","8,735",0,100.00,0.00,"an_executable.exe", | ||
# 3,"boost::trim_end_iter_select<std::iterator<std::val<std::types<char> > >,boost::is_classifiedF>",306,16,3.50,0.18,"an_executable.exe", | ||
# | ||
# OUTPUT EXAMPLE : | ||
# | ||
# main;testing::UnitTest::Run;boost::trim_end_iter_select<std::iterator<std::val<std::types<char>>>,boost::is_classifiedF> 306 | ||
|
||
use strict; | ||
|
||
sub massage_function_names; | ||
sub parse_integer; | ||
sub print_stack_trace; | ||
|
||
# data initialization | ||
my @stack = (); | ||
my $line_number = 0; | ||
my $previous_samples = 0; | ||
|
||
my $num_args = $#ARGV + 1; | ||
if ($num_args != 1) { | ||
print "$ARGV[0]\n"; | ||
print "Usage : stackcollapse-vsprof.pl <in.cvs> > out.txt\n"; | ||
exit; | ||
} | ||
|
||
my $input_csv_file = $ARGV[0]; | ||
my $line_parser_rx = qr{ | ||
^\s*(\d+?), # level in the stack | ||
("[^"]+" | [^,]+), # function name (beware of spaces) | ||
("[^"]+" | [^,]+), # number of samples (beware of locale number formatting) | ||
}ox; | ||
|
||
open(my $fh, '<', $input_csv_file) or die "Can't read file '$input_csv_file' [$!]\n"; | ||
|
||
while (my $current_line = <$fh>){ | ||
$line_number = $line_number + 1; | ||
|
||
# to discard first line which typically contains headers | ||
next if $line_number == 1; | ||
next if $current_line =~ /^\s*$/o; | ||
|
||
($current_line =~ $line_parser_rx) or die "Error in regular expression at line $line_number : $current_line\n"; | ||
|
||
my $level = int $1; | ||
my $function = massage_function_names($2); | ||
my $samples = parse_integer($3); | ||
my $stack_len = @stack; | ||
|
||
#print "[DEBUG] $line_number : $level $function $samples $stack_len\n"; | ||
|
||
next if not $level; | ||
($level <= $stack_len + 1) or die "Error in stack at line $line_number : $current_line\n"; | ||
|
||
if ($level <= $stack_len) { | ||
print_stack_trace(\@stack, $previous_samples); | ||
my $to_remove = $level - $stack_len - 1; | ||
splice(@stack, $to_remove); | ||
} | ||
|
||
$stack_len < 1000 or die "Stack overflow at line $line_number"; | ||
push(@stack, $function); | ||
$previous_samples = $samples; | ||
} | ||
print_stack_trace(\@stack, $previous_samples); | ||
|
||
sub massage_function_names { | ||
return ($_[0] =~ s/\s*|^"|"$//gro); | ||
} | ||
|
||
sub parse_integer { | ||
return int ($_[0] =~ s/[., ]|^"|"$//gro); | ||
} | ||
|
||
sub print_stack_trace { | ||
my ($stack_ref, $sample) = @_; | ||
my $stack_trace = join(";", @$stack_ref); | ||
print "$stack_trace $sample\n"; | ||
} |