Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memory management go程序中函数中神秘且过多的内存分配_Memory Management_Go_Profiling - Fatal编程技术网

Memory management go程序中函数中神秘且过多的内存分配

Memory management go程序中函数中神秘且过多的内存分配,memory-management,go,profiling,Memory Management,Go,Profiling,我有下面的代码,它使用了比预期要高的内存音调。 我曾经使用过pprof工具,它显示函数NewEdge正在分配程序分配的所有内存的94%以上 我的问题是,这段代码有什么问题,占用了这么多内存: type Vertex struct { Id string `json:"id"` // must be unique Properties map[string]stri

我有下面的代码,它使用了比预期要高的内存音调。
我曾经使用过
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
}
问题/谜团

我可以创建数千个
顶点
s,内存使用非常合理。但是对
NewEdge
的调用非常占用内存。我首先注意到代码使用的是记忆音调。我用
-memprofile
运行了
pprof
,然后使用
go工具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)

非常感谢您的帮助。

@ali我认为这段记忆中没有什么神秘之处。 首先,若你们检查你们的结构的大小,你们会看到边结构比顶点结构大2倍。(您可以通过unsafe.Sizeof()检查结构的大小) 因此,如果您将调用fakeGraph(Aragog,2000,1),Go将分配:

  • 2000顶点结构
  • 至少2000*20=40000个边缘结构
    如您所见,NewEdge()将分配比fakeGraph()至少多40倍的内存
此外,每次尝试创建新边缘时,都会分配新边缘结构-即使NewEdge()返回错误

另一个因素是-返回struct本身,而不是指向struct的指针。In-Go结构是值类型,所以当您从NewEdge()返回时,整个结构将被复制,并且它还可能导致新的分配。
是的,我看到了您从未使用过的返回结构,但我不确定Go编译器是否会检查调用方的上下文并跳过边复制

您没有显示如何分配顶点。也许开销实际上是将边缘id分配给源id映射和目标id映射?你要为这10MB创建多少个要分配的对象?@not_a_Golfer谢谢,我编辑了这个问题,现在它包括了我如何创建它们。我看不出有什么问题。这取决于您创建的边的数量和各种ID的大小。您的
顶点中的切片可以快速增长。您可能需要检查它们的容量。如果是这样的话,除了默认的代码>附录< /代码>之外,你可以考虑另一种分配策略。我想你在Go 1.3下尝试过了吗?对于堆栈上的值,GC得到了改进。我这样问是因为您的
NewEdge
确实分配了。。然后在调用中丢弃。我已经看到了1.3版本中内存使用量减半的截图——那么不妨试一试?不会受伤吗?谢谢@varyous我不知道这是否解释了所有的问题,但我忽略了基本数学(边的数量),这是我发疯的主要原因。我还需要更深入地挖掘,但这解释了很多问题,而且作为记录,我在几个小时前就发现了这个问题,当时我试图向一个朋友解释这个问题,并开始计算物体的数量。不过,还是要感谢您花时间阅读代码。我很感激。
(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)