@@ -25,6 +25,12 @@ type intIterator struct {
2525 hs uint64
2626 iter roaring.IntPeekable
2727 highlowcontainer * roaringArray64
28+
29+ // These embedded iterators per container type help reduce load in the GC.
30+ // This way, instead of making up-to 4 billion allocations per full iteration
31+ // we get a single allocation and simply reinitialize the embedded iterator
32+ // and point to it in the generic `iter` member on each key bound.
33+ bitmapIter roaring.IntIterator
2834}
2935
3036// HasNext returns true if there are more integers to iterate over
@@ -34,8 +40,9 @@ func (ii *intIterator) HasNext() bool {
3440
3541func (ii * intIterator ) init () {
3642 if ii .highlowcontainer .size () > ii .pos {
37- ii .iter = ii .highlowcontainer .getContainerAtIndex (ii .pos ).Iterator ()
3843 ii .hs = uint64 (ii .highlowcontainer .getKeyAtIndex (ii .pos )) << 32
44+ ii .bitmapIter .Initialize (ii .highlowcontainer .getContainerAtIndex (ii .pos ))
45+ ii .iter = & ii .bitmapIter
3946 }
4047}
4148
@@ -74,11 +81,21 @@ func (ii *intIterator) AdvanceIfNeeded(minval uint64) {
7481 }
7582}
7683
84+ // IntIterator64 is meant to allow you to iterate through the values of a bitmap, see Initialize(a *Bitmap)
85+ type IntIterator64 = intIterator
86+
87+ // Initialize configures the existing iterator so that it can iterate through the values of
88+ // the provided bitmap.
89+ // The iteration results are undefined if the bitmap is modified (e.g., with Add or Remove).
90+ func (ii * intIterator ) Initialize (a * Bitmap ) {
91+ ii .pos = 0
92+ ii .highlowcontainer = & a .highlowcontainer
93+ ii .init ()
94+ }
95+
7796func newIntIterator (a * Bitmap ) * intIterator {
7897 p := new (intIterator )
79- p .pos = 0
80- p .highlowcontainer = & a .highlowcontainer
81- p .init ()
98+ p .Initialize (a )
8299 return p
83100}
84101
@@ -87,6 +104,9 @@ type intReverseIterator struct {
87104 hs uint64
88105 iter roaring.IntIterable
89106 highlowcontainer * roaringArray64
107+
108+ // Stack-allocated embedded iterator to reduce GC pressure.
109+ bitmapIter roaring.IntReverseIterator
90110}
91111
92112// HasNext returns true if there are more integers to iterate over
@@ -96,8 +116,9 @@ func (ii *intReverseIterator) HasNext() bool {
96116
97117func (ii * intReverseIterator ) init () {
98118 if ii .pos >= 0 {
99- ii .iter = ii .highlowcontainer .getContainerAtIndex (ii .pos ).ReverseIterator ()
100119 ii .hs = uint64 (ii .highlowcontainer .getKeyAtIndex (ii .pos )) << 32
120+ ii .bitmapIter .Initialize (ii .highlowcontainer .getContainerAtIndex (ii .pos ))
121+ ii .iter = & ii .bitmapIter
101122 } else {
102123 ii .iter = nil
103124 }
@@ -113,11 +134,21 @@ func (ii *intReverseIterator) Next() uint64 {
113134 return x
114135}
115136
137+ // IntReverseIterator64 is meant to allow you to iterate through the values of a bitmap in reverse, see Initialize(a *Bitmap)
138+ type IntReverseIterator64 = intReverseIterator
139+
140+ // Initialize configures the existing iterator so that it can iterate through the values of
141+ // the provided bitmap in reverse.
142+ // The iteration results are undefined if the bitmap is modified (e.g., with Add or Remove).
143+ func (ii * intReverseIterator ) Initialize (a * Bitmap ) {
144+ ii .highlowcontainer = & a .highlowcontainer
145+ ii .pos = a .highlowcontainer .size () - 1
146+ ii .init ()
147+ }
148+
116149func newIntReverseIterator (a * Bitmap ) * intReverseIterator {
117150 p := new (intReverseIterator )
118- p .highlowcontainer = & a .highlowcontainer
119- p .pos = a .highlowcontainer .size () - 1
120- p .init ()
151+ p .Initialize (a )
121152 return p
122153}
123154
@@ -132,12 +163,16 @@ type manyIntIterator struct {
132163 hs uint64
133164 iter roaring.ManyIntIterable
134165 highlowcontainer * roaringArray64
166+
167+ // Stack-allocated embedded iterator to reduce GC pressure.
168+ bitmapIter roaring.ManyIntIterator
135169}
136170
137171func (ii * manyIntIterator ) init () {
138172 if ii .highlowcontainer .size () > ii .pos {
139- ii .iter = ii .highlowcontainer .getContainerAtIndex (ii .pos ).ManyIterator ()
140173 ii .hs = uint64 (ii .highlowcontainer .getKeyAtIndex (ii .pos )) << 32
174+ ii .bitmapIter .Initialize (ii .highlowcontainer .getContainerAtIndex (ii .pos ))
175+ ii .iter = & ii .bitmapIter
141176 } else {
142177 ii .iter = nil
143178 }
@@ -160,10 +195,20 @@ func (ii *manyIntIterator) NextMany(buf []uint64) int {
160195 return n
161196}
162197
198+ // ManyIntIterator64 is meant to allow you to iterate through the values of a bitmap, see Initialize(a *Bitmap)
199+ type ManyIntIterator64 = manyIntIterator
200+
201+ // Initialize configures the existing iterator so that it can iterate through the values of
202+ // the provided bitmap.
203+ // The iteration results are undefined if the bitmap is modified (e.g., with Add or Remove).
204+ func (ii * manyIntIterator ) Initialize (a * Bitmap ) {
205+ ii .pos = 0
206+ ii .highlowcontainer = & a .highlowcontainer
207+ ii .init ()
208+ }
209+
163210func newManyIntIterator (a * Bitmap ) * manyIntIterator {
164211 p := new (manyIntIterator )
165- p .pos = 0
166- p .highlowcontainer = & a .highlowcontainer
167- p .init ()
212+ p .Initialize (a )
168213 return p
169214}
0 commit comments