[libgee] Specialise the stream iterator



commit c1e39f58c360d6ac1b8522234361108bdce5475f
Author: Maciej Piechotka <uzytkownik2 gmail com>
Date:   Sat Jul 6 19:43:01 2013 +0200

    Specialise the stream iterator
    
    In the test this improves running time by 4%-22% depending on test.
    
    On 1048575 elements:
     - Calling filter and iterating: 1.006±0.008 → 0.80±0.02
     - Calling map and iterating: 1.65±0.03 → 1.441±0.005
     - Calling flat_map and iterating: 11.12±0.09 → 10.69±0.01

 gee/Makefile.am         |    1 +
 gee/streamiterator.vala |  165 +++++++++++++++++++++++++++++++++++++++++++++++
 gee/traversable.vala    |   64 +-----------------
 3 files changed, 169 insertions(+), 61 deletions(-)
---
diff --git a/gee/Makefile.am b/gee/Makefile.am
index 115920f..1f9a2b8 100644
--- a/gee/Makefile.am
+++ b/gee/Makefile.am
@@ -68,6 +68,7 @@ libgee_0_8_la_SOURCES = \
        set.vala \
        sortedmap.vala \
        sortedset.vala \
+       streamiterator.vala \
        task.vala \
        timsort.vala \
        traversable.vala \
diff --git a/gee/streamiterator.vala b/gee/streamiterator.vala
new file mode 100644
index 0000000..701f2e1
--- /dev/null
+++ b/gee/streamiterator.vala
@@ -0,0 +1,165 @@
+/* streamiterator.vala
+ *
+ * Copyright (C) 2011-2012  Maciej Piechotka
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ *     Maciej Piechotka <uzytkownik2 gmail com>
+ */
+
+internal class Gee.StreamIterator<A, G> : GLib.Object, Traversable<A>, Iterator<A> {
+       public StreamIterator (Iterator<G> outer, owned StreamFunc<A, G> func) {
+               _outer = outer;
+               _func = (owned)func;
+               _current = null;
+               _need_next = true;
+               _finished = false;
+
+               _state = _func (Traversable.Stream.YIELD, null, out _current);
+               switch (_state) {
+               case Traversable.Stream.WAIT:
+               case Traversable.Stream.YIELD:
+                       _need_next = !_outer.valid;
+                       break;
+               case Traversable.Stream.CONTINUE:
+                       if (_outer.valid) {
+                               _state = _func (_state, new Lazy<G> (() => {return _outer.get ();}), out 
_current);
+                               switch (_state) {
+                               case Traversable.Stream.YIELD:
+                               case Traversable.Stream.CONTINUE:
+                               case Traversable.Stream.WAIT:
+                                       break;
+                               case Traversable.Stream.END:
+                                       _finished = true;
+                                       return;
+                               default:
+                                       assert_not_reached ();
+                               }
+                       }
+                       break;
+               case Traversable.Stream.END:
+                       _finished = true;
+                       return;
+               }
+       }
+
+       public bool foreach (ForallFunc<A> f) {
+               Lazy<G>? current = null;
+               if (_current != null) {
+                       if (!f (_current.value)) {
+                               return false;
+                       }
+               }
+               if (_next != null) {
+                       current = (owned)_next;
+                       if (!f (current.value)) {
+                               return false;
+                       }
+               } else if (_finished) {
+                       return true;
+               }
+               unowned Iterator<G> outer = _outer;
+               StreamFunc<A, G> func = _func;
+               Traversable.Stream state = _state;
+               bool need_next = _need_next;
+               bool result = true;
+               Lazy<G>? next_current;
+               while ((next_current = yield_next<A, G>(outer, func, ref state, ref need_next)) != null) {
+                       current = (owned)next_current;
+                       if (!f (current.value)) {
+                               result = false;
+                               break;
+                       }
+               }
+               _state = state;
+               _need_next = need_next;
+               _finished = result;
+               _current = (owned)current;
+               return result;
+       }
+
+       public bool next () {
+               if (has_next ()) {
+                       _current = (owned)_next;
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+       public bool has_next () {
+               if (_finished) {
+                       return false;
+               }
+               if (_next != null) {
+                       return true;
+               }
+               _next = yield_next<A, G> (_outer, _func, ref _state, ref _need_next);
+               _finished = _next == null;
+               return !_finished;
+       }
+
+       public new A get () {
+               assert (_current != null);
+               return _current.value;
+       }
+
+       public void remove () {
+               assert_not_reached ();
+       }
+
+       public bool valid { get { return _current != null; } }
+       public bool read_only { get { return true; } }
+
+       private static inline Lazy<A>? yield_next<A, G> (Iterator<G> outer, StreamFunc<A, G> func, ref 
Traversable.Stream state, ref bool need_next) {
+               Lazy<A>? value = null;
+               if (state != Traversable.Stream.CONTINUE)
+                       state = func (state, null, out value);
+               while (true) {
+                       switch (state) {
+                       case Traversable.Stream.YIELD:
+                               return value;
+                       case Traversable.Stream.CONTINUE:
+                               if (need_next) {
+                                       if (!outer.next ()) {
+                                               state = func (Traversable.Stream.END, null, out value);
+                                               continue;
+                                       }
+                               } else {
+                                       need_next = true;
+                               }
+                               state = func (state, new Lazy<G> (() => {return outer.get ();}), out value);
+                               break;
+                       case Traversable.Stream.WAIT:
+                               state = func (state, null, out value);
+                               break;
+                       case Traversable.Stream.END:
+                               return null;
+                       default:
+                               assert_not_reached ();
+                       }
+               }
+       }
+
+       private Iterator<G> _outer;
+       private StreamFunc<A, G> _func;
+       private Lazy<A>? _current;
+       private Lazy<A>? _next;
+       private Traversable.Stream _state;
+       private bool _need_next;
+       private bool _finished;
+}
+
diff --git a/gee/traversable.vala b/gee/traversable.vala
index 0ab1b52..4c514fc 100644
--- a/gee/traversable.vala
+++ b/gee/traversable.vala
@@ -109,69 +109,11 @@ public interface Gee.Traversable<G> : Object {
         * @return iterator containing values yielded by stream
         */
        public virtual Iterator<A> stream<A> (owned StreamFunc<G, A> f) {
-               Iterator<G>? self;
-               Iterable<G>? iself;
+               unowned Iterator<G>? self;
+               unowned Iterable<G>? iself;
                // Yes - I've heard of polimorphism ;) but I don't want users to need to implement the method.
                if ((self = this as Iterator<G>) != null) { 
-                       Traversable.Stream str;
-                       Lazy<A>? initial = null;
-                       bool need_next = true;
-                       str = f (Stream.YIELD, null, out initial);
-                       switch (str) {
-                       case Stream.WAIT:
-                       case Stream.YIELD:
-                               if (self.valid)
-                                       need_next = false;
-                               break;
-                       case Stream.CONTINUE:
-                               if (self.valid) {
-                                       str = f (Stream.CONTINUE, new Lazy<G> (() => {return self.get ();}), 
out initial);
-                                       switch (str) {
-                                       case Stream.YIELD:
-                                       case Stream.CONTINUE:
-                                       case Stream.WAIT:
-                                               break;
-                                       case Stream.END:
-                                               return Iterator.unfold<A> (() => {return null;});
-                                       default:
-                                               assert_not_reached ();
-                                       }
-                               }
-                               break;
-                       case Stream.END:
-                               return Iterator.unfold<A> (() => {return null;});
-                       default:
-                               assert_not_reached ();
-                       }
-                       return Iterator.unfold<A> (() => {
-                               Lazy<A>? val = null;
-                               if (str != Stream.CONTINUE)
-                                       str = f (str, null, out val);
-                               while (true) {
-                                       switch (str) {
-                                       case Stream.YIELD:
-                                               return val;
-                                       case Stream.CONTINUE:
-                                               if (need_next) {
-                                                       if (!self.next ()) {
-                                                               str = f (Traversable.Stream.END, null, out 
val);
-                                                               continue;
-                                                       }
-                                               } else {
-                                                       need_next = true;
-                                               }
-                                               str = f (Stream.CONTINUE, new Lazy<G> (() => {return self.get 
();}), out val);
-                                               break;
-                                       case Stream.WAIT:
-                                               str = f (Stream.WAIT, null, out val);
-                                               break;
-                                       case Stream.END:
-                                               return null;
-                                       default:
-                                               assert_not_reached ();
-                                       }
-                               }
-                       }, initial);
+                       return new StreamIterator<A, G> (self, (owned)f);
                } else if ((iself = this as Iterable<G>) != null) {
                        return iself.iterator().stream<A> ((owned) f);
                } else {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]