How to get the size of struct and its contents in bytes in golang?

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

How to get the size of struct and its contents in bytes in golang?

问题

我有一个结构体,假设如下:

type ASDF struct {
    A   uint64
    B   uint64
    C   uint64
    D   uint64
    E   uint64
    F   string
}

我创建了一个该结构体的切片:a := []ASDF{}

我对该结构体的切片进行操作(添加/删除/更新内容不同的结构体);如何获取该切片及其内容的总大小(以字节为单位,用于内存)?是否有内置的方法可以实现这一点,还是我需要手动使用unsafe.Sizeoflen函数进行计算?

英文:

I have a struct, say:

type ASDF struct {
    A   uint64
    B   uint64
    C   uint64
    D   uint64
    E   uint64
    F   string
}

I create a slice of that struct: a := []ASDF{}

I do operations on that slice of the struct (adding/removing/updating structs that vary in contents); how can I get the total size in bytes (for memory) of the slice and its contents? Is there a built-in to do this or do I need to manually run a calculation using unsafe.Sizeof and then len each string?

答案1

得分: 8

计算所有内存的大小,不包括垃圾收集器和其他开销。例如,

package main

import (
	"fmt"
	"unsafe"
)

type ASDF struct {
	A uint64
	B uint64
	C uint64
	D uint64
	E uint64
	F string
}

func (s *ASDF) size() int {
	size := int(unsafe.Sizeof(*s))
	size += len(s.F)
	return size
}

func sizeASDF(s []ASDF) int {
	size := 0
	s = s[:cap(s)]
	size += cap(s) * int(unsafe.Sizeof(s))
	for i := range s {
		size += (&s[i]).size()
	}
	return size
}

func main() {
	a := []ASDF{}

	b := ASDF{}
	b.A = 1
	b.B = 2
	b.C = 3
	b.D = 4
	b.E = 5
	b.F = "ASrtertetetetetetetDF"
	fmt.Println((&b).size())
	a = append(a, b)

	c := ASDF{}
	c.A = 10
	c.B = 20
	c.C = 30
	c.D = 40
	c.E = 50
	c.F = "ASetDF"
	fmt.Println((&c).size())
	a = append(a, c)

	fmt.Println(len(a))
	fmt.Println(cap(a))
	fmt.Println(sizeASDF(a))
}

输出:

69
54
2
2
147
http://play.golang.org/p/5z30vkyuNM
英文:

Sum the size of all memory, excluding garbage collector and other overhead. For example,

package main
import (
"fmt"
"unsafe"
)
type ASDF struct {
A uint64
B uint64
C uint64
D uint64
E uint64
F string
}
func (s *ASDF) size() int {
size := int(unsafe.Sizeof(*s))
size += len(s.F)
return size
}
func sizeASDF(s []ASDF) int {
size := 0
s = s[:cap(s)]
size += cap(s) * int(unsafe.Sizeof(s))
for i := range s {
size += (&s[i]).size()
}
return size
}
func main() {
a := []ASDF{}
b := ASDF{}
b.A = 1
b.B = 2
b.C = 3
b.D = 4
b.E = 5
b.F = "ASrtertetetetetetetDF"
fmt.Println((&b).size())
a = append(a, b)
c := ASDF{}
c.A = 10
c.B = 20
c.C = 30
c.D = 40
c.E = 50
c.F = "ASetDF"
fmt.Println((&c).size())
a = append(a, c)
fmt.Println(len(a))
fmt.Println(cap(a))
fmt.Println(sizeASDF(a))
}

Output:

69
54
2
2
147

http://play.golang.org/p/5z30vkyuNM

答案2

得分: 3

很抱歉,如果你想要得到任何结果,unsafe.Sizeof是唯一的选择。结构体的内存大小不是你应该依赖的。请注意,即使是unsafe.Sizeof的结果也是不准确的:运行时可能会添加你无法观察到的数据头以帮助垃圾回收。

对于你的特定示例(查找缓存大小),我建议你使用一个对许多处理器都合理的静态大小。在几乎所有情况下,进行这种微观优化是得不偿失的。

英文:

I'm afraid to say that unsafe.Sizeof is the way to go here if you want to get any result at all. The in-memory size of a structure is nothing you should rely on. Notice that even the result of unsafe.Sizeof is inaccurate: The runtime may add headers to the data that you cannot observe to aid with garbage collection.

For your particular example (finding a cache size) I suggest you to go with a static size that is sensible for many processors. In almost all cases doing such micro-optimizations is not going to pay itself off.

huangapple
  • 本文由 发表于 2015年7月19日 08:16:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/31496804.html
匿名

发表评论

匿名网友

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

确定