string - strings.Builder 内存使用情况
问题描述
使用此文件(数据文件):
package main
import (
"io/ioutil"
"time"
)
func main() {
ioutil.ReadFile("100mb.file")
time.Sleep(time.Duration(time.Minute))
}
显示我的内存使用量为 107 MB。使用这个类似的文件:
package main
import (
"bytes"
"os"
"time"
)
func read(path_s string) (bytes.Buffer, error) {
buf_o := bytes.Buffer{}
open_o, e := os.Open(path_s)
if e != nil {
return buf_o, e
}
buf_o.ReadFrom(open_o)
open_o.Close()
return buf_o, nil
}
func main() {
read("100mb.file")
time.Sleep(time.Duration(time.Minute))
}
内存使用量达到 273 MB。最后这个类似的文件:
package main
import (
"io"
"os"
"strings"
"time"
)
func read(path_s string) (strings.Builder, error) {
str_o := strings.Builder{}
open_o, e := os.Open(path_s)
if e != nil {
return str_o, e
}
io.Copy(&str_o, open_o)
open_o.Close()
return str_o, nil
}
func main() {
read("100mb.file")
time.Sleep(time.Duration(time.Minute))
}
内存使用量达到 432 MB。我尽量小心并尽可能关闭文件。为什么第二个示例的内存使用率如此之高,尤其是最后一个示例?我可以改变一些东西,使它们更接近第一个例子吗?
解决方案
ioutil.ReadFile("100mb.file")
获取文件的大小,分配一个[]byte
该大小并将字节吞入该切片。
buf_o.ReadFrom(open_o)
[]byte
分配一些大小的初始值并读入该切片。如果读取器中的数据多于切片中的空间,则该函数分配一个更大的切片,将现有数据复制到该切片并读取更多数据。这将重复直到 EOF。
函数 ioutil.ReadFile 在内部使用字节 Buffer.ReadFrom。查看 ioutil.ReadFile 实现,了解如何改进对 bytes.Buffer 的直接使用。逻辑概要是这样的:
var buf bytes.Buffer
// Open file
f, err := os.Open(path)
if err != nil {
return &buf, err
}
defer f.Close()
// Get size.
fi, err := f.Stat()
if err != nil {
return &buf, err
}
// Grow to size of file plus extra slop to ensure no realloc.
buf.Grow(int(fi.Size()) + bytes.MinRead)
_, err := buf.ReadFrom(f)
return &buf, err
strings.Builder 示例像 bytes.Buffer 示例一样多次重新分配内部缓冲区。此外,io.Copy 分配一个缓冲区。您可以通过在读取之前将构建器增大到文件大小来改进 strings.Builder 示例。
这是strings.Builder的代码:
var buf strings.Builder
// Open file
f, err := os.Open(path)
if err != nil {
return &buf, err
}
defer f.Close()
// Get size.
fi, err := f.Stat()
if err != nil {
return &buf, err
}
buf.Grow(int(fi.Size()))
_, err = io.Copy(&buf, f)
return &buf, err
io.Copy 或其他使用额外缓冲区的代码是必需的,因为 strings.Builder 没有 ReadFrom 方法。strings.Builder 类型没有 ReadFrom 方法,因为该方法可能泄漏对内部字节切片的支持数组的引用。
推荐阅读
- c# - .NET 中的异步/等待用法
- javascript - react-bootstrap navbar 折叠时不会将内容向下推
- r - 使用 {patchwork} 组装的 ggplots 之间不需要的分隔标记/线条
- typescript - 如何重用接口上的泛型参数?
- amazon-web-services - 从 AWS Lambda 函数运行:可以看到 CloudWatch 日志,但在 axios 的延续中除外
- c++ - 从不同线程同步调用公共函数
- r - 分析从移动眼动仪获得的眼动和头部运动数据
- python - 在python中使用COM接口
- php - 如何使用 in_array / array_push 获取与自定义帖子相似的帖子?
- html - 为什么我的导航栏没有显示其内容?