#Can someone explain why the slice is reduced in capacity?
39 messages · Page 1 of 1 (latest)
the cap of the slice is 6
of which len is 4
if you remove the first two items
the cap still stays +2 of the length
since the end of the slice is unaffected
First:
2, 3, 5, 7, 11, 13
^ ^
| data | len, cap
Slice the slice to give it zero length.:
2, 3, 5, 7, 11, 13
^ ^
| data, len | cap
Extend its length:
2, 3, 5, 7, 11, 13
^ ^ ^
| data | len | cap
Drop its first two values.:
2, 3, 5, 7, 11, 13
^ ^ ^
| | len | cap
| data
len and cap are counted from the data pointer (start of the array) if you advance the data pointer lan and cap has to shrink to compensate
also note you can't reslice a slice back on the left, only the right
here 2 and 3 are effectively lost (you would need to copy the slice before dropping the values to not have that happen)
note: my example used [x,y] ranging go uses [x,y) ranging
I asked about this the other day, but I don't think I got an answer. When you do slicing operations like this, as well as using the full slice expression to cap a slice, do the "lost" elements get garbage-collected, or does the full array remain in memory because it's still pointed to by something?
Not gofrontend nor the go compiler.
They track allocations by block.
I don't know if this required by the language or implementation detail (because you could use unsafe to regain access FWIW)
Your graphical representation is fantastic. thanks. Isn't the slice backed by the underlying array so if you slice from index 2 to the end the array does not change? So its slices length and capacity that is changed
the array do not change because maybe an other slice is still pointing at the start
it is hard and expensive to keep track of which individual indexes of array are still reachable it is also not cheap to resize allocations so the compiler and runtime just don't if anything points anywhere the whole array continues to exists
Also with [x,y) ranging:
First:
2, 3, 5, 7, 11, 13
^ ^
| data | len, cap
Slice the slice to give it zero length.:
2, 3, 5, 7, 11, 13
^ ^
| data, len | cap
Extend its length:
2, 3, 5, 7, 11, 13
^ ^ ^
| data | len | cap
Drop its first two values.:
2, 3, 5, 7, 11, 13
^ ^ ^
| | len | cap
| data
(this is actually how the slice works but is slightly more confusing when showed like this)
What confuses me is that if you give it zero length you can still get it back the data when extend the length but if you drop the fist two you cannot get them back.
because dropping the length drops data to the right
you can access data to the right no problem
when you drop the first two you drop data on the left of the data pointer
which cannot be saved
I need it to sink in
@silver barn to do what you are suggesting you would something like this:
type slice struct{
leftCapacity, leftLen uint
data unsafe.Pointer
rightLen, rightCapacity uint
}
Thoses are called butterfly pointers
tour of go should mention this
butterfly pointers ?
I don't think so
This would be more expensive because now each slice is 5 words instead of 3 and it would make bound checks more expensive too.
Note the current slice looks like this:
type slice struct{
data unsafe.Pointer
rightLen, rightCapacity uint
}
See how it's easier to check if an index is valid, I can just check i >= rightLen which is 1, maybe 2 instructions.
Having to check both left and right would make most [] operations slower, and that is an operation your programs should do a whole lot
woah, Are you talking to me a bout butterfly pointers? that is way over my head at the moment
I'm just saying, what you are asking is called "butterfly pointers", thoses are more expensive usually.
So go just do not use that, go because that is slightly faster and the only usecase needed in most applications it only keeps track of the right part of the slice
it just does not track things on the left
so if you discard them you can't get them back
also butterfly pointers are expensive and so this is a nice reason to have them in the language, go wants to be a simple language and butterfly pointers are not simple
that is fine. but 'The Tour of Go' should mention that you loose elements on the left when slicing this way
I think you are supposed to infer that yourself by looking at the output
you can submit a PR to make the tour better if you want
I see. but I did not infer