首页  >  文章  >  后端开发  >  使用字符串和指针时,如何优化 Go 程序中的内存使用和垃圾收集?

使用字符串和指针时,如何优化 Go 程序中的内存使用和垃圾收集?

Mary-Kate Olsen
Mary-Kate Olsen原创
2024-11-04 04:10:30880浏览

 How can I optimize memory usage and garbage collection in my Go program when working with strings and pointers?

Go 中的垃圾收集和指针的正确使用

垃圾收集的背景

Go 使用垃圾收集器来自动管理内存。垃圾收集器会释放不再被任何指针引用的内存。

指针和字符串

在 Go 中,字符串是按值传递的不可变值。当函数接收字符串时,它接收的是字符串值的副本,而不是对原始字符串的引用。

使用指针

在提供的代码中,映射代码的以下版本不是最佳的。

版本 1:

tagToUrlMap := make(map[string][]*string)

for _, image := range result {
    for _, tag := range image.Tags {
        tagToUrlMap[tag.Name] = append(tagToUrlMap[tag.Name], &image.URL)
    }
}

版本 2:

tagToUrlMap := make(map[string][]*string)

for _, image := range result {
    imageUrl = image.URL
    for _, tag := range image.Tags {
        tagToUrlMap[tag.Name] = append(tagToUrlMap[tag.Name], &imageUrl)
    }
}

问题:

  • 在这两个版本中,存储 Image 结构的 URL 字段的地址将防止 Image 结构被垃圾收集。
  • 版本 2 引入了额外的间接级别,并且不必要的对象分配。

最佳解决方案

最佳解决方案是使用以下代码:

tagToUrlMap := make(map[string][]string)

for _, image := range result {
    imageURL := image.URL // Store the string value directly

    for _, tag := range image.Tags {
        tagName := tag.Name  // Store the string value directly
        tagToUrlMap[tagName] = append(tagToUrlMap[tagName], imageURL)
    }
}

String Interning

此代码为遇到的每个 URL 和标记名称创建一个新字符串。为了进一步优化内存使用,可以使用字符串驻留。

字符串驻留涉及在中央缓存中存储唯一的字符串值。当遇到新字符串时,会根据缓存进行检查。如果字符串已经在缓存中,则使用缓存的值而不是创建新字符串。

这是一个简单的字符串内部函数:

var cache = map[string]string

func intern(s string) string {
    if s2, ok := cache[s]; ok {
        return s2
    }
    cache[s] = s
    return s
}

要使用内部函数,请修改映射代码如下:

tagToUrlMap := make(map[string][]string)

for _, image := range result {
    imageURL := intern(image.URL) // Intern the string

    for _, tag := range image.Tags {
        tagName := intern(tag.Name) // Intern the string
        tagToUrlMap[tagName] = append(tagToUrlMap[tagName], imageURL)
    }
}

清除缓存

要释放interner缓存使用的内存,请在interning完成后将nil分配给缓存变量:

cache = nil

进一步优化

  • 构建 tagToUrlMap 后,修剪映射中切片的任何多余容量以节省内存。
  • 如果需要,可以使用自定义内存分配器来进一步优化

结论

通过直接使用字符串值、字符串实习以及清除实习者的缓存,您可以在 Go 程序中实现最佳的内存使用和高效的垃圾收集。

以上是使用字符串和指针时,如何优化 Go 程序中的内存使用和垃圾收集?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn