Commit a4a82241 authored by Robert Griesemer's avatar Robert Griesemer

use a bootstrap array to avoid allocation for short vectors

R=r
https://golang.org/cl/165078
parent 8c22dd24
...@@ -9,12 +9,28 @@ package vector ...@@ -9,12 +9,28 @@ package vector
// Vector is the container itself. // Vector is the container itself.
// The zero value for Vector is an empty vector ready to use. // The zero value for Vector is an empty vector ready to use.
type Vector struct { type Vector struct {
a []interface{}; a []interface{};
bootstrap [8]interface{};
}
func (p *Vector) realloc(length, capacity int) (b []interface{}) {
if length <= cap(p.bootstrap) && capacity <= cap(p.bootstrap) {
// don't allocate; use pre-allocated bootstrap array
b = p.bootstrap[0:length]
} else {
b = make([]interface{}, length, capacity)
}
copy(b, p.a);
p.a = b;
return;
} }
// Insert n elements at position i. // Insert n elements at position i.
func expand(a []interface{}, i, n int) []interface{} { func (p *Vector) expand(i, n int) {
a := p.a;
// make sure we have enough space // make sure we have enough space
len0 := len(a); len0 := len(a);
len1 := len0 + n; len1 := len0 + n;
...@@ -24,21 +40,20 @@ func expand(a []interface{}, i, n int) []interface{} { ...@@ -24,21 +40,20 @@ func expand(a []interface{}, i, n int) []interface{} {
} else { } else {
// not enough space - double capacity // not enough space - double capacity
capb := cap(a) * 2; capb := cap(a) * 2;
if capb <= len1 { if capb < len1 {
// still not enough - use required length // still not enough - use required length
capb = len1 capb = len1
} }
// capb > len1 // capb >= len1
b := make([]interface{}, len1, capb); a = p.realloc(len1, capb);
copy(b, a);
a = b;
} }
// make a hole // make a hole
for j := len0 - 1; j >= i; j-- { for j := len0 - 1; j >= i; j-- {
a[j+n] = a[j] a[j+n] = a[j]
} }
return a;
p.a = a;
} }
...@@ -46,15 +61,14 @@ func expand(a []interface{}, i, n int) []interface{} { ...@@ -46,15 +61,14 @@ func expand(a []interface{}, i, n int) []interface{} {
// If the new length is shorter than the current length, Resize discards // If the new length is shorter than the current length, Resize discards
// trailing elements. If the new length is longer than the current length, // trailing elements. If the new length is longer than the current length,
// Resize adds nil elements. The capacity parameter is ignored unless the // Resize adds nil elements. The capacity parameter is ignored unless the
// new length or capacity is longer that the current capacity. // new length or capacity is longer that the current capacity. The resized
// vector's capacity may be larger than the requested capacity.
func (p *Vector) Resize(length, capacity int) *Vector { func (p *Vector) Resize(length, capacity int) *Vector {
a := p.a; a := p.a;
if length > cap(a) || capacity > cap(a) { if length > cap(a) || capacity > cap(a) {
// not enough space or larger capacity requested explicitly // not enough space or larger capacity requested explicitly
b := make([]interface{}, length, capacity); a = p.realloc(length, capacity)
copy(b, a);
a = b;
} else if length < len(a) { } else if length < len(a) {
// clear trailing elements // clear trailing elements
for i := range a[length:] { for i := range a[length:] {
...@@ -101,7 +115,7 @@ func (p *Vector) Data() []interface{} { ...@@ -101,7 +115,7 @@ func (p *Vector) Data() []interface{} {
// Insert inserts into the vector an element of value x before // Insert inserts into the vector an element of value x before
// the current element at index i. // the current element at index i.
func (p *Vector) Insert(i int, x interface{}) { func (p *Vector) Insert(i int, x interface{}) {
p.a = expand(p.a, i, 1); p.expand(i, 1);
p.a[i] = x; p.a[i] = x;
} }
...@@ -121,7 +135,7 @@ func (p *Vector) Delete(i int) { ...@@ -121,7 +135,7 @@ func (p *Vector) Delete(i int) {
// InsertVector inserts into the vector the contents of the Vector // InsertVector inserts into the vector the contents of the Vector
// x such that the 0th element of x appears at index i after insertion. // x such that the 0th element of x appears at index i after insertion.
func (p *Vector) InsertVector(i int, x *Vector) { func (p *Vector) InsertVector(i int, x *Vector) {
p.a = expand(p.a, i, len(x.a)); p.expand(i, len(x.a));
copy(p.a[i:i+len(x.a)], x.a); copy(p.a[i:i+len(x.a)], x.a);
} }
......
...@@ -27,8 +27,8 @@ func checkSize(t *testing.T, v VectorInterface, len, cap int) { ...@@ -27,8 +27,8 @@ func checkSize(t *testing.T, v VectorInterface, len, cap int) {
if v.Len() != len { if v.Len() != len {
t.Errorf("expected len = %d; found %d", len, v.Len()) t.Errorf("expected len = %d; found %d", len, v.Len())
} }
if v.Cap() != cap { if v.Cap() < cap {
t.Errorf("expected cap = %d; found %d", cap, v.Cap()) t.Errorf("expected cap >= %d; found %d", cap, v.Cap())
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment