Open elliott5 opened 2 years ago
@elliott5 do by chance know the formula for growing capacity?
There is a very good blog post on slices here that explains how it works in general.
To summarise:
By default, unless told otherwise (slicing or new capacity), the length of the underlying array is the length of the contents.
The capacity of the underlying array of a slice can be set by the user on creation. This is what is done by the Go bytes.Buffer code (used by the example code for this issue) - see func AppendByte()
in the blog for similar logic.
The bigest complexity comes when using append:
func growslice(et *_type, old slice, cap int) slice
is where the logic sits. Key part copied in the code block below: newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
const threshold = 256
if old.cap < threshold {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
// Transition from growing 2x for small slices
// to growing 1.25x for large slices. This formula
// gives a smooth-ish transition between the two.
newcap += (newcap + 3*threshold) / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}
I think this may be a 2nd order problem, as the system still (mostly) works with a different slice growing strategy from Go.
I think this may be a 2nd order problem, as the system still (mostly) works with a different slice growing strategy from Go.
I agree, I did try writing up a system to exactly mimic go, but I had trouble with data transfer of the append because it doesn't keep track of the potential slice getting added into append, which I think go does keep track of?
Either way not very high on the priority list.
This issue seems to have regressed as the output now is: cap: 6303
Todo: implement this later and also look into using internally optimized functions such as Vector.fromArrayCopy
in GoArray __append__
newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
newcap = cap
} else {
const threshold = 256
if old.cap < threshold {
newcap = doublecap
} else {
// Check 0 < newcap to detect overflow
// and prevent an infinite loop.
for 0 < newcap && newcap < cap {
// Transition from growing 2x for small slices
// to growing 1.25x for large slices. This formula
// gives a smooth-ish transition between the two.
newcap += (newcap + 3*threshold) / 4
}
// Set newcap to the requested cap when
// the newcap calculation overflowed.
if newcap <= 0 {
newcap = cap
}
}
}
This issue springs from issue #120
Code:
Results: