lib/array: remember the last used iterator so it could be used again
authorJean Privat <jean@pryen.org>
Fri, 6 Mar 2015 15:33:22 +0000 (22:33 +0700)
committerJean Privat <jean@pryen.org>
Fri, 6 Mar 2015 15:33:22 +0000 (22:33 +0700)
on nitc/nitc/nit this reduce a lot the number of allocated iterators.

before:

* 0m7.168s
* 2,706,498 new ArrayIterator
* the second most allocated class (after NativeArray)

after:

* 0m7.060s (-1.5%)
* 785,781 new ArrayIterator (-70%)
* the 7th most allocated class

Signed-off-by: Jean Privat <jean@pryen.org>

lib/standard/collection/array.nit

index 1fb8581..acc189c 100644 (file)
@@ -130,7 +130,20 @@ abstract class AbstractArrayRead[E]
                end
        end
 
-       redef fun iterator: ArrayIterator[E] do return new ArrayIterator[E](self)
+       redef fun iterator: ArrayIterator[E] do
+               var res = _free_iterator
+               if res == null then return new ArrayIterator[E](self)
+               res._index = 0
+               _free_iterator = null
+               return res
+       end
+
+       # An old iterator, free to reuse.
+       # Once an iterator is `finish`, it become reusable.
+       # Since some arrays are iterated a lot, this avoid most of the
+       # continuous allocation/garbage-collection of the needed iterators.
+       private var free_iterator: nullable ArrayIterator[E] = null
+
        redef fun reverse_iterator do return new ArrayReverseIterator[E](self)
 end
 
@@ -477,6 +490,8 @@ private class ArrayIterator[E]
        redef var index = 0
 
        var array: AbstractArrayRead[E]
+
+       redef fun finish do _array._free_iterator = self
 end
 
 private class ArrayReverseIterator[E]