strings.Builder 内存使用
strings.Builder memory usage
使用这个文件(data file):
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
并读入该片。如果 reader 中的数据多于切片中 space 中的数据,则该函数会分配更大的切片,将现有数据复制到该切片并读取更多数据。重复此过程直到 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 分配一个缓冲区。在阅读之前,您可以通过 growing the builder to the size of the file 改进 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 方法,因为该方法可能会泄漏对内部字节片的支持数组的引用。
根据 Muffin Top 的建议,我采用了第二个示例并添加了这个
在调用 ReadFrom
:
之前
stat_o, e := open_o.Stat()
if e != nil {
return buf_o, e
}
buf_o.Grow(bytes.MinRead + int(stat_o.Size()))
内存下降到107MB,和第一个例子基本一样
使用这个文件(data file):
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
并读入该片。如果 reader 中的数据多于切片中 space 中的数据,则该函数会分配更大的切片,将现有数据复制到该切片并读取更多数据。重复此过程直到 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 分配一个缓冲区。在阅读之前,您可以通过 growing the builder to the size of the file 改进 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 方法,因为该方法可能会泄漏对内部字节片的支持数组的引用。
根据 Muffin Top 的建议,我采用了第二个示例并添加了这个
在调用 ReadFrom
:
stat_o, e := open_o.Stat()
if e != nil {
return buf_o, e
}
buf_o.Grow(bytes.MinRead + int(stat_o.Size()))
内存下降到107MB,和第一个例子基本一样