io.Copy在golang中导致内存不足的问题。

huangapple go评论88阅读模式
英文:

io.Copy cause out of memory in golang

问题

我使用io.Copy()函数来复制一个大约700MB的文件,但是它导致了内存溢出的问题。

bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)

//关键步骤
fileWriter, err := bodyWriter.CreateFormFile(paramName, fileName)
if err != nil {
    return nil, err
}

file, err := os.Open(fileName) //文件大小约为700MB
if err != nil {
    return nil, err
}
defer file.Close()

//复制文件
copyLen, err := io.Copy(fileWriter, file) //这导致了内存溢出
if err != nil {
    fmt.Println("io.copy(): ", err)
    return nil, err
}

错误信息如下:

runtime: memory allocated by OS (0x752cf000) not in usable range [0x18700000,0x98700000)
runtime: out of memory: cannot allocate 1080229888-byte block (1081212928 in use)
fatal error: out of memory

我为buf分配了足够的内存,但在bodyWriter.CreateFormFile()函数中导致了内存溢出。

buf := make([]byte, 766509056)
bodyBuf := bytes.NewBuffer(buf)
bodyWriter := multipart.NewWriter(bodyBuf)

fileWriter, err := bodyWriter.CreateFormFile(paramName, fileName) //内存溢出
if err != nil {
    return nil, err
}
英文:

I use io.Copy() to copy a file, about 700Mb, but it cause out of memory

bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)

//key step
fileWriter, err := bodyWriter.CreateFormFile(paramName, fileName)
if err != nil {
	return nil, err
}

file, err := os.Open(fileName) //the file size is about 700Mb
if err != nil {
	return nil, err
}
defer file.Close()

//iocopy
copyLen, err := io.Copy(fileWriter, file) // this cause out of memory
if err != nil {
	fmt.Println("io.copy(): ", err)

	return nil, err
}

The error message as follow:

runtime: memory allocated by OS (0x752cf000) not in usable range [0x18700000,0x98700000)
runtime: out of memory: cannot allocate 1080229888-byte block (1081212928 in use)
fatal error: out of memory

I allocate enough memory for buf, it cause out of memory in bodyWriter.CreateFormFile()

buf := make([]byte, 766509056)
bodyBuf := bytes.NewBuffer(buf)
bodyWriter := multipart.NewWriter(bodyBuf)

fileWriter, err := bodyWriter.CreateFormFile(paramName, fileName) // out of memory
if err != nil {
    return nil, err
}

答案1

得分: 7

这是因为你正在将文件内容复制到一个内存缓冲区bodyBuf中,这会强制Go尝试分配一个与整个文件大小相同的内存块。

根据你使用multipart的方式,看起来你是想通过HTTP流式传输文件?在这种情况下,不要将bytes.Buffer传递给multipart.NewWriter,直接将你的HTTP连接传递给它即可。

英文:

That's because you are 'copying', to bodyBuf, which is an in-memory buffer, forcing Go to try an allocate a block of memory as big as the entire file.

Based on your use of multipart it looks like you are trying to stream the file over http? In that case, don't pass a bytes.Buffer to multipart.NewWriter, directly pass your http connection instead.

huangapple
  • 本文由 发表于 2014年4月23日 12:28:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/23234755.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定