allocation - Can (the underlying array of) a slice with large starting index in Go be allocated memory-efficiently? -
i'm trying use slice, myslice, large starting index. rather explicitly subtracting starting index using myslice[index - myslicestartindex], tempted define slice in such way can use without such arithmetic myslice[index]. can done without allocating memory unused low indices?
the naive way of doing this, allocating slice , reslicing (e.g. myslice = myslice[3*1024*1024*1024:4*1024*1024*1024]) is memory inefficient because underlying array not needs allocated entire range, remains allocated. not work, because afterwards data formerly @ index 3*1024*1024*1024 @ index 0, whilst goal keep @ original index.
can allocate slice (or underlying array) in such way indices below slice's start not allocated, ideally not initially?
this not possible without /not/ allocating unused parts. way slice defined in go, through reflect.sliceheader
type sliceheader struct { data uintptr len int cap int } it contains no starting index field. merely reference underlying, fixed size array. underlying array holds actual data. slice 'window' array, begins @ index 0. wherever 0 may in underlying array.
for instance, consider following code:
a := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} b := a[2:8] c := a[8:] d := b[2:4] this yields memory layout follows:
fixed array: [ 0 1 2 3 4 5 6 7 8 9 ] > [10]int @ address 273785072 slice : . . . . . . . . . . > sliceheader{data:273785072 len:10 cap:10} slice b : . . . . . . > sliceheader{data:273785080 len:6 cap:8} slice c : . . > sliceheader{data:273785104 len:2 cap:2} slice d : . . > sliceheader{data:273785088 len:2 cap:6} the values data address offsets fixed array , 4 slices share underlying storage.
a =:= $273785072 b =:= $273785080 =:= $a + sizeof(int)*2 =:= $a + 8 c =:= $273785104 =:= $a + sizeof(int)*8 =:= $a + 32 d =:= $273785088 =:= $b + sizeof(int)*2 =:= $a + sizeof(int)*4 =:= $a + 16 at whatever index re-slice existing slice, new slice indexed 0 len(s), because address in underlying fixed array points puts there.
memory mapping
if data loaded file on disk, can have different option: use syscall.mmap provide access data through slice, starting @ desired index. returned slice index 0 , covers range specified.
func mmap(fd *os.file, start, size int) ([]byte, error) { _, err := fd.seek(0, 0) if err != nil { return nil, err } return syscall.mmap(int(fd.fd()), start, size, syscall.prot_read, syscall.map_shared) } do not forget call syscall.munmap on returned slice, when done using it.
Comments
Post a Comment