func New(prof *profile.Profile, o *Options) *Graph {
	if o.CallTree {
		return newTree(prof, o)
	}
	g, _ := newGraph(prof, o)
	return g
}
New summarizes performance data from a profile into a graph.
package graph
import (
	"fmt"
	"math"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"github.com/google/pprof/profile"
)
var (
	javaRegExp = regexp.MustCompile(`^(?:[a-z]\w*\.)*([A-Z][\w\$]*\.(?:<init>|[a-z][\w\$]*(?:\$\d+)?))(?:(?:\()|$)`)
	goRegExp = regexp.MustCompile(`^(?:[\w\-\.]+\/)+(.+)`)
	goVerRegExp = regexp.MustCompile(`^(.*?)/v(?:[2-9]|[1-9][0-9]+)([./].*)$`)
	cppRegExp                = regexp.MustCompile(`^(?:[_a-zA-Z]\w*::)+(_*[A-Z]\w*::~?[_a-zA-Z]\w*(?:<.*>)?)`)
	cppAnonymousPrefixRegExp = regexp.MustCompile(`^\(anonymous namespace\)::`)
)
type Graph struct {
	Nodes Nodes
}
type Options struct {
	SampleValue       func(s []int64) int64       
	SampleMeanDivisor func(s []int64) int64       
	FormatTag         func(int64, string) string  
	ObjNames          bool                        
	OrigFnNames       bool                        
	CallTree     bool  
	DropNegative bool  
	KeptNodes NodeSet  
}
type Nodes []*Node
type Node struct {
	Info NodeInfo
	Function *Node
	Flat, FlatDiv, Cum, CumDiv int64
	In, Out EdgeMap
	LabelTags TagMap
	NumericTags map[string]TagMap
}
func (n *Node) FlatValue() int64 {
	if n.FlatDiv == 0 {
		return n.Flat
	}
	return n.Flat / n.FlatDiv
}
func (n *Node) CumValue() int64 {
	if n.CumDiv == 0 {
		return n.Cum
	}
	return n.Cum / n.CumDiv
}
func (n *Node) AddToEdge(to *Node, v int64, residual, inline bool) {
	n.AddToEdgeDiv(to, 0, v, residual, inline)
}
func (n *Node) AddToEdgeDiv(to *Node, dv, v int64, residual, inline bool) {
	if n.Out[to] != to.In[n] {
		panic(fmt.Errorf("asymmetric edges %v %v", *n, *to))
	}
	if e := n.Out[to]; e != nil {
		e.WeightDiv += dv
		e.Weight += v
		if residual {
			e.Residual = true
		}
		if !inline {
			e.Inline = false
		}
		return
	}
	info := &Edge{Src: n, Dest: to, WeightDiv: dv, Weight: v, Residual: residual, Inline: inline}
	n.Out[to] = info
	to.In[n] = info
}
type NodeInfo struct {
	Name              string
	OrigName          string
	Address           uint64
	File              string
	StartLine, Lineno int
	Objfile           string
}
func (i *NodeInfo) PrintableName() string {
	return strings.Join(i.NameComponents(), " ")
}
func (i *NodeInfo) NameComponents() []string {
	var name []string
	if i.Address != 0 {
		name = append(name, fmt.Sprintf("%016x", i.Address))
	}
	if fun := i.Name; fun != "" {
		name = append(name, fun)
	}
	switch {
	case i.Lineno != 0:
		name = append(name, fmt.Sprintf("%s:%d", i.File, i.Lineno))
	case i.File != "":
		name = append(name, i.File)
	case i.Name != "":
	case i.Objfile != "":
		name = append(name, "["+filepath.Base(i.Objfile)+"]")
	default:
		name = append(name, "<unknown>")
	}
	return name
}
type NodeMap map[NodeInfo]*Node
type NodeSet map[NodeInfo]bool
type NodePtrSet map[*Node]bool
func (nm NodeMap) FindOrInsertNode(info NodeInfo, kept NodeSet) *Node {
	if kept != nil {
		if _, ok := kept[info]; !ok {
			return nil
		}
	}
	if n, ok := nm[info]; ok {
		return n
	}
	n := &Node{
		Info:        info,
		In:          make(EdgeMap),
		Out:         make(EdgeMap),
		LabelTags:   make(TagMap),
		NumericTags: make(map[string]TagMap),
	}
	nm[info] = n
	if info.Address == 0 && info.Lineno == 0 {
		n.Function = n
		return n
	}
	info.Address = 0
	info.Lineno = 0
	n.Function = nm.FindOrInsertNode(info, nil)
	return n
}
type EdgeMap map[*Node]*Edge
type Edge struct {
	Src, Dest *Node
	Weight, WeightDiv int64
	Residual bool
	Inline bool
}
func (e *Edge) WeightValue() int64 {
	if e.WeightDiv == 0 {
		return e.Weight
	}
	return e.Weight / e.WeightDiv
}
type Tag struct {
	Name          string
	Unit          string  
	Value         int64
	Flat, FlatDiv int64
	Cum, CumDiv   int64
}
func (t *Tag) FlatValue() int64 {
	if t.FlatDiv == 0 {
		return t.Flat
	}
	return t.Flat / t.FlatDiv
}
func (t *Tag) CumValue() int64 {
	if t.CumDiv == 0 {
		return t.Cum
	}
	return t.Cum / t.CumDiv
}
type TagMap map[string]*Tag
func SortTags(t []*Tag, flat bool) []*Tag {
	ts := tags{t, flat}
	sort.Sort(ts)
	return ts.t
}