简体   繁体   English

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

[英]How to set memory limit to a process in Golang

I use syscall prlimit to set resource limit to process, it works for limit CPU time but when test memory usage, I come with the problem.我使用 syscall prlimit 来设置进程的资源限制,它适用于限制 CPU 时间,但是在测试内存使用情况时,我遇到了问题。

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
    }
}

and it's my test.这是我的测试。

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")
    }
}

this is memo:这是备忘录:

package main

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

I make a large amount of memory and set only 10 bytes for the memory , but it won't signal segment fault signal any way.我做了大量的内存,只为内存设置了 10 个字节,但它不会以任何方式发出段错误信号。

RLIMIT_DATA describes the maximum size of a processes data segment. RLIMIT_DATA描述进程数据段的最大大小。 Traditionally, programs that allocate memory enlarge the data segment with calls to brk() to allocate memory from the operating system.传统上,分配内存的程序通过调用brk()从操作系统分配内存来扩大数据段。

Go doesn't use this approach. Go 不使用这种方法。 Instead, it uses a variant of the mmap() system call to request regions of memory anywhere in the address space.相反,它使用mmap()系统调用的变体来请求地址空间中任何位置的内存区域。 This is much more flexible than a brk() based approach as you can deallocate arbitrary memory regions with munmap() , whereas a brk() based approach can only deallocate memory from the end of the data segment.这比基于brk()的方法灵活得多,因为您可以使用munmap()释放任意内存区域,而基于brk()的方法只能从数据段的末尾释放内存。

The result of this is that RLIMIT_DATA is inneffective in controlling the amount of memory a process uses.其结果是RLIMIT_DATA在控制进程使用的内存量方面无效。 Try using RLIMIT_AS instead, but beware that this limit also incorporates the address space you use for file mappings, especially in the case of shared libraries.请尝试改用RLIMIT_AS ,但请注意,此限制还包含用于文件映射的地址空间,尤其是在共享库的情况下。

There is one proposal Soft memory limit , it may be released after go 1.18有一个提议Soft memory limit ,可能会在 go 1.18 之后释放

This option comes in two flavors: a new runtime/debug function called SetMemoryLimit and a GOMEMLIMIT environment variable.此选项有两种形式:一个名为SetMemoryLimit的新runtime/debug函数和一个GOMEMLIMIT环境变量。 In sum, the runtime will try to maintain this memory limit by limiting the size of the heap, and by returning memory to the underlying platform more aggressively.总之,运行时将尝试通过限制堆的大小以及更积极地将内存返回给底层平台来维持这个内存限制。 This includes with a mechanism to help mitigate garbage collection death spirals.这包括帮助减轻垃圾收集死亡螺旋的机制。 Finally, by setting GOGC=off, the Go runtime will always grow the heap to the full memory limit.最后,通过设置 GOGC=off,Go 运行时将始终将堆增长到完整内存限制。

This new option gives applications better control over their resource economy.这个新选项使应用程序可以更好地控制其资源经济性。 It empowers users to:它使用户能够:

  • Better utilize the memory that they already have,更好地利用他们已有的内存,
  • Confidently decrease their memory limits, knowing Go will respect them,自信地减少他们的记忆限制,知道 Go 会尊重他们,
  • Avoid unsupported forms of garbage collection tuning.避免不支持的垃圾收集调整形式。

Update更新

This feature will be released in Go 1.19此功能将在Go 1.19中发布

The runtime now includes support for a soft memory limit.运行时现在包括对软内存限制的支持。 This memory limit includes the Go heap and all other memory managed by the runtime, and excludes external memory sources such as mappings of the binary itself, memory managed in other languages, and memory held by the operating system on behalf of the Go program.此内存限制包括 Go 堆和运行时管理的所有其他内存,不包括外部内存源,例如二进制文件本身的映射、以其他语言管理的内存以及操作系统代表 Go 程序持有的内存。

This limit may be managed via runtime/debug.SetMemoryLimit or the equivalent GOMEMLIMIT environment variable.此限制可以通过runtime/debug.SetMemoryLimit或等效的GOMEMLIMIT环境变量进行管理。

The limit works in conjunction with runtime/debug.SetGCPercent / GOGC , and will be respected even if GOGC=off , allowing Go programs to always make maximal use of their memory limit, improving resource efficiency in some cases.该限制与runtime/debug.SetGCPercent / GOGC结合使用,即使GOGC=off也会受到尊重,从而允许 Go 程序始终最大限度地利用其内存限制,在某些情况下提高资源效率。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM