#!/usr/bin/perl -w # # hotcoldgraph.pl flame/cold stack grapher. # # EXPERIMENTAL: This is a work in progress, and may not work properly. # # This takes on and off-cpu stack timings (see hcstackcollapse.pl) and # renders a call graph, allowing latency in codepaths to be quickly identified. # # USAGE: ./hotcoldgraph.pl input.txt > graph.svg # # grep funcA input.txt | ./hotcoldgraph.pl > graph.svg # # The input is stack frames and sample counts formatted as single lines. Each # frame in the stack is comma separated, with a space and count at the end of # the line. These can be generated using DTrace with stackcollapse.pl. # # The output graph shows relative presense of functions in stack samples. The # ordering on the x-axis has no meaning; since the data is samples, time order # of events is not known. The order used sorts function names alphabeticly. # # HISTORY # # This was inspired by Neelakanth Nadgir's excellent function_call_graph.rb # program, which visualized function entry and return trace events. As Neel # wrote: "The output displayed is inspired by Roch's CallStackAnalyzer which # was in turn inspired by the work on vftrace by Jan Boerhout". See: # http://blogs.sun.com/realneel/entry/visualizing_callstacks_via_dtrace_and # # For the on-CPU graph only, see flamegraph.pl. # # Copyright 2013 Joyent, Inc. All rights reserved. # Copyright 2013 Brendan Gregg. All rights reserved. # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://opensource.org/licenses/CDDL-1.0. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # 10-Sep-2011 Brendan Gregg Created this.
use strict;
# tunables
my $fonttype = "Verdana";
my $imagewidth = 1200; # max width, pixels
my $frameheight = 16; # max height is dynamic
my $fontsize = 12; # base text size
my $minwidth = 0.1; # min function width, pixels
# internals
my $ypad1 = $fontsize * 4; # pad top, include title
my $ypad2 = $fontsize * 2 + 10; # pad bottom, include labels
my $xpad = 10; # pad lefm and right
my $timemax = 0;
my $depthmax = 0;
my %Events;
# SVG functions
{ package SVG;
sub new {
my $class = shift;
my $self = {};
bless ($self, $class);
return $self;
}
sub svg {
my $self = shift;
return "$self->{svg}\n";
}
1;
}
sub color {
my $type = shift; if (defined $type and $type eq "hot") {
my $r = 205 + int(rand(50));
my $g = 0 + int(rand(230));
my $b = 0 + int(rand(55));
return "rgb($r,$g,$b)";
} if (defined $type and $type eq "cold") {
my $r = 0 + int(rand(40));
my $b = 205 + int(rand(50));
my $g = 0 + int(rand(150));
return "rgb($r,$g,$b)";
}
return "rgb(0,0,0)";
}
my %Node;
my %Tmp;
sub flow {
my ($a, $b, $ca, $cb, $v) = @_;
my @A = split ",", $a;
my @B = split ",", $b;
my $len_a = $#A;
my $len_b = $#B;
$depthmax = $len_b if $len_b > $depthmax;
my $i = 0;
my $len_same = 0; for (; $i <= $len_a; $i++) {
last if $i > $len_b;
last if $A[$i] ne $B[$i];
}
$len_same = $i;
$len_same = 0 if $ca != $cb;
for ($i = $len_a; $i >= $len_same; $i--) {
my $k = "$A[$i]-$i"; # a unique ID is constructed from func-depth-etime; # func-depth isn't unique, it may be repeated later.
$Node{"$k-$v-$ca"}->{stime} = $Tmp{$k}->{stime}; delete $Tmp{$k}->{stime}; delete $Tmp{$k};
}
for ($i = $len_same; $i <= $len_b; $i++) {
my $k = "$B[$i]-$i";
$Tmp{$k}->{stime} = $v;
}
}
# Parse input
my @Data = <>;
my $laststack = "";
my $lastcpu = 0;
my $time = 0; foreach (sort @Data) {
chomp;
my ($stack, $cpu, $samples) = split ' ';
$stack = ",$stack";
next unless defined $samples;
flow($laststack, $stack, $lastcpu, $cpu, $time);
$time += $samples;
$laststack = $stack;
$lastcpu = $cpu;
}
flow($laststack, "", $lastcpu, 0, $time);
$timemax = $time or die "ERROR: No stack counts found\n";
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.