我有下面的代碼,它使用的內存,這是遠遠高於預期的色調。
我以前pprof
工具,它示出了功能NewEdge
被分配由程序分配的所有存儲器的94%以上。神祕而過多的內存分配函數中的圍棋程序
我的問題是,什麼是錯的這個代碼,這是使用這麼多的內存:
type Vertex struct {
Id string `json:"id"` // must be unique
Properties map[string]string `json:"properties"` // to be implemented soon
verticesThisIsConnectedTo map[string][]string `json:"-"` //id for the edges *Edge // keys are Vertex ids, each pair of vertices can be connected to each other with multiple edges
verticesConnectedToThis map[string][]string `json:"_"` //id for the edges *Edge // keys are Vertex ids,
}
type Edge struct {
id string `json:"-"` // for internal use, unique
Label string `json:"label"`
SourceId string `json:"source-id"`
TargetId string `json:"terget-id"`
Type string `json:"type"`
Properties map[string]string `json:"properties"` // to be implemented soon
}
func (v *Vertex) isPartof(g *Graph) bool {
_, b := g.Vertices[v.Id]
return b
}
func (g *Graph) NewEdge(source, target *Vertex, label, edgeType string) (Edge, error) {
if source.Id == target.Id {
return Edge{}, ERROR_NO_EDGE_TO_SELF_ALLOWED
}
if !source.isPartof(g) || !target.isPartof(g) {
return Edge{}, errors.New("InvalidEdge, source or target not in this graph")
}
e := Edge{id: <-nextId, Label: label, SourceId: source.Id, TargetId: target.Id, Type: edgeType}
g.Edges[e.id] = &e
source.verticesThisIsConnectedTo[target.Id] = append(source.verticesThisIsConnectedTo[target.Id], e.id)
target.verticesConnectedToThis[source.Id] = append(target.verticesConnectedToThis[source.Id], e.id)
return e, nil
}
分配情況通過這樣一個電話:fakeGraph(Aragog, 2000, 1)
其中:
func fakeGraph(g Graph, nodesCount, followratio int) error {
var err error
// create the vertices
for i := 0; i < nodesCount; i++ {
v := NewVertex("") //FH.RandStr(10))
g.AddVertex(v)
}
// create some "follow edges"
followcount := followratio * nodesCount/100
vkeys := []string{}
for pk := range g.Vertices {
vkeys = append(vkeys, pk)
}
for ki := range g.Vertices {
pidx := rand.Perm(nodesCount)
followcounter := followcount
for j := 0; j < followcounter; j++ {
_, err := g.NewEdge(g.Vertices[ki], g.Vertices[vkeys[pidx[j]]], <-nextId, EDGE_TYPE_FOLLOW)
if err != nil {
followcounter++ // to compensate for references to self
}
}
}
return err
}
問題/神祕:
我可以創建成千上萬的Vertex
s和內存使用是非常reaso nable。但撥打NewEdge
是非常內存密集。我首先注意到代碼使用了內存的語調。我跑pprof
與-memprofile
,然後用go tool pprof
並得到了這一點:
(pprof) top10
Total: 9.9 MB
8.9 89.9% 89.9% 8.9 89.9% main.(*Graph).NewEdge
0.5 5.0% 95.0% 0.5 5.0% allocg
0.5 5.0% 100.0% 0.5 5.0% fmt.Sprintf
0.0 0.0% 100.0% 0.5 5.0% _rt0_go
0.0 0.0% 100.0% 8.9 89.9% main.fakeGraph
0.0 0.0% 100.0% 0.5 5.0% main.func·003
0.0 0.0% 100.0% 8.9 89.9% main.main
0.0 0.0% 100.0% 0.5 5.0% mcommoninit
(pprof)
任何幫助是非常讚賞。
你沒告訴你是如何分配的頂點。也許開銷實際上是邊緣id分配給源和目標ID地圖?你爲這10MB分配了多少個對象? –
@not_a_Golfer謝謝,我編輯了這個問題,現在它包括我如何創建它們。 – Ali
我沒有特別看到問題。這取決於您創建的Edge數量以及各種Ids的大小。 – mzimmerman