首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Golang中设置进程的内存限制

如何在Golang中设置进程的内存限制
EN

Stack Overflow用户
提问于 2014-07-02 04:07:28
回答 2查看 12.3K关注 0票数 9

我使用syscall pr限度来设置进程的资源限制,它可以限制CPU时间,但是当测试内存使用情况时,我遇到了这个问题。

代码语言:javascript
运行
复制
package sandbox

import (
    "syscall"
    "unsafe"
)

func prLimit(pid int, limit uintptr, rlimit *syscall.Rlimit) error {
    _, _, errno := syscall.RawSyscall6(syscall.SYS_PRLIMIT64, uintptr(pid), limit, uintptr(unsafe.Pointer(rlimit)), 0, 0, 0)
    var err error
    if errno != 0 {
        err = errno
        return err
    } else {
        return nil
    }
}

这是我的考验。

代码语言:javascript
运行
复制
func TestMemoryLimit(t *testing.T) {
    proc, err := os.StartProcess("test/memo", []string{"memo"}, &os.ProcAttr{})
    if err != nil {
        panic(err)
    }
    defer proc.Kill()
    var rlimit syscall.Rlimit
    rlimit.Cur = 10
    rlimit.Max = 10 + 1024
    prLimit(proc.Pid, syscall.RLIMIT_DATA, &rlimit)
    status, err := proc.Wait()
    if status.Success() {
        t.Fatal("memory test failed")
    }
}

这是备忘录:

代码语言:javascript
运行
复制
package main

func main() {
    var a [10000][]int
    for i := 0; i < 1000; i++ {
        a[i] = make([]int, 1024)
    }
}

我做了大量的内存,只为内存设置了10个字节,但它不会以任何方式发出信号段故障信号。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-02 09:44:38

RLIMIT_DATA描述进程数据段的最大大小。传统上,分配内存的程序通过调用brk()从操作系统分配内存来扩大数据段。

Go不使用这种方法。相反,它使用mmap()系统调用的一个变体来请求地址空间中任何位置的内存区域。这比基于brk()的方法灵活得多,因为您可以使用munmap()来释放任意内存区域,而基于brk()的方法只能从数据段的末尾释放内存。

其结果是,RLIMIT_DATA在控制进程使用的内存量方面是不有效的。尝试使用RLIMIT_AS,但是请注意,这个限制也包含了用于文件映射的地址空间,特别是在共享库的情况下。

票数 11
EN

Stack Overflow用户

发布于 2022-01-24 08:44:43

有一个建议是软记忆极限,它可能会在go 1.18之后发布

该选项有两种形式:一个名为runtime/debug的新SetMemoryLimit函数和一个GOMEMLIMIT环境变量。总之,运行时将试图通过限制堆的大小和更积极地将内存返回到底层平台来维护这个内存限制。这包括一种帮助减少垃圾收集死亡螺旋的机制。最后,通过设置GOGC=off,Go运行时将始终将堆增长到完全内存限制。这个新选项使应用程序能够更好地控制其资源经济性。它授权用户:

  • 更好地利用他们已有的记忆,
  • 自信地减少他们的记忆限制,知道去就会尊重他们,
  • 避免不支持的垃圾收集调优形式。

更新

这个特性将在去1.19中发布。

运行时现在包括对软内存限制的支持。此内存限制包括Go堆和运行时管理的所有其他内存,并排除外部内存源,例如二进制本身的映射、以其他语言管理的内存以及操作系统代表Go程序持有的内存。

这个限制可以通过runtime/debug.SetMemoryLimit或等效的GOMEMLIMIT环境变量来管理。

该限制与runtime/debug.SetGCPercent / GOGC一起工作,即使是GOGC=off也会受到尊重,允许Go程序始终最大限度地利用其内存限制,从而在某些情况下提高资源效率。

以下是关于每个memory limit使用Go垃圾收集器指南的一些建议

虽然内存限制是一个强大的工具,Go运行时会采取步骤来减少误用造成的最坏行为,但是谨慎地使用它仍然是很重要的。下面是关于内存限制在哪里最有用和最适用,以及它可能造成的危害大于好处的建议的集合。

  • 当Go程序的执行环境完全在您的控制范围内时,Do利用内存限制,而Go程序是唯一能够访问某些资源集的程序(例如某种内存预留,例如容器内存限制)。 一个很好的例子是将web服务部署到具有固定可用内存的容器中。 在这种情况下,一个好的经验法则是为Go运行时不知道的内存源留出5-10%的额外空间。
  • Do可以实时调整内存限制,以适应不断变化的情况。 一个很好的例子是cgo程序,其中C库暂时需要使用更多的内存。
  • 如果Go程序可能与其他程序共享其有限内存,那么不要将GOGC设置为内存限制,并且这些程序通常与Go程序分离。相反,保持内存限制,因为它可能有助于抑制不受欢迎的瞬态行为,但将GOGC设置为一些较小的,合理的平均值。 虽然尝试并为共同租户程序“保留”内存很有诱惑力,除非程序完全同步(例如,Go程序在调用它的调用程序时调用一些子进程和块),但结果将不太可靠,因为不可避免的是,这两个程序都需要更多内存。让Go程序在不需要的时候使用更少的内存,总体上会产生更可靠的结果。此建议还适用于过度提交的情况,在这种情况下,运行在一台机器上的容器的内存限制之和可能超过机器可用的实际物理内存。
  • 不要在部署到不受控制的执行环境时使用内存限制,特别是当程序的内存使用与其输入成正比时。 一个很好的例子是CLI工具或桌面应用程序。当不清楚输入是什么类型的输入,或者系统上有多少内存可用时,将内存限制输入到程序中可能会导致混乱的崩溃和糟糕的性能。此外,高级终端用户可以随时设置内存限制,如果他们愿意的话。
  • 当程序已经接近其环境的内存限制时,不要设置内存限制以避免内存不足的情况。 这有效地将内存不足的风险替换为严重的应用程序放缓的风险,而这种风险往往不是一个有利的交易,即使是为了减轻打击所做的努力。在这种情况下,要么增加环境的内存限制(然后可能设置内存限制)要么减少GOGC (这将提供一个比减轻重击更干净的权衡),这将更加有效。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24522692

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档