mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-16 04:06:44 +00:00
storage: order VolumeInfo by alignment (#10669)
* storage: order VolumeInfo by alignment The struct is held for every volume replica in the cluster, so the padding the compiler inserts is multiplied by however many volumes a master tracks. Two one-byte fields each sat at the head of a word and left the rest of it empty, which was ten of the eighteen wasted bytes. Grouping by size rather than by meaning takes the struct from 152 bytes to 136, and the map holding them shrinks with it, since a Go map's slack scales with the size of the value. 800k volumes registered from a heartbeat that has been over the wire: 211 -> 195 B/volume, 214 -> 198 tiered. * trim the comments on this change to the parts that are not evident
This commit is contained in:
+19
-13
@@ -10,23 +10,29 @@ import (
|
||||
"github.com/seaweedfs/seaweedfs/weed/storage/super_block"
|
||||
)
|
||||
|
||||
// Held for every volume replica, so the fields are grouped by size rather than
|
||||
// by meaning: interleaved, each one-byte field rounds up to a whole word.
|
||||
type VolumeInfo struct {
|
||||
Id needle.VolumeId
|
||||
Size uint64
|
||||
ReplicaPlacement *super_block.ReplicaPlacement
|
||||
Ttl *needle.TTL
|
||||
DiskType string
|
||||
DiskId uint32
|
||||
Collection string
|
||||
Version needle.Version
|
||||
FileCount int
|
||||
DeleteCount int
|
||||
DeletedByteCount uint64
|
||||
ReadOnly bool
|
||||
CompactRevision uint32
|
||||
ModifiedAtSecond int64
|
||||
DiskType string
|
||||
RemoteStorageName string
|
||||
RemoteStorageKey string
|
||||
|
||||
ReplicaPlacement *super_block.ReplicaPlacement
|
||||
Ttl *needle.TTL
|
||||
|
||||
Size uint64
|
||||
FileCount int
|
||||
DeleteCount int
|
||||
DeletedByteCount uint64
|
||||
ModifiedAtSecond int64
|
||||
|
||||
Id needle.VolumeId
|
||||
DiskId uint32
|
||||
CompactRevision uint32
|
||||
|
||||
Version needle.Version
|
||||
ReadOnly bool
|
||||
}
|
||||
|
||||
func NewVolumeInfo(m *master_pb.VolumeInformationMessage) (vi VolumeInfo, err error) {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Nothing else in the package would notice if someone grouped the fields by
|
||||
// meaning again, and the padding is multiplied by every volume a master holds.
|
||||
func TestVolumeInfoHasNoInteriorPadding(t *testing.T) {
|
||||
typ := reflect.TypeOf(VolumeInfo{})
|
||||
|
||||
var used, interior uintptr
|
||||
prevEnd := uintptr(0)
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
f := typ.Field(i)
|
||||
if gap := f.Offset - prevEnd; gap > 0 {
|
||||
t.Errorf("%d bytes of padding before %s, at offset %d: order the fields by size so they pack",
|
||||
gap, f.Name, prevEnd)
|
||||
interior += gap
|
||||
}
|
||||
used += f.Type.Size()
|
||||
prevEnd = f.Offset + f.Type.Size()
|
||||
}
|
||||
|
||||
size := unsafe.Sizeof(VolumeInfo{})
|
||||
if tail := size - prevEnd; tail > 7 {
|
||||
t.Errorf("%d bytes of padding at the end, more than alignment requires", tail)
|
||||
}
|
||||
if interior == 0 {
|
||||
t.Logf("%d bytes of fields in a %d byte struct", used, size)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user