Re: [TinkerPop] Pipes NoSuchElementExceptions overhead hasNext evaluation (particularly on SingleIterators)

165 views
Skip to first unread message

Marko Rodriguez

unread,
Jul 30, 2012, 10:48:24 AM7/30/12
to gremli...@googlegroups.com
Hi,

Yes, that is how it works.

The problem is that with filter-based pipes, you never know if the .next() of the previous pipe is going to return something as even if the previous iterator .hasNext(), it might not come through to a future Pipe. What I typically do is NOT use hasNext(). If you look at the methods like iterate(), toList(), fill(), count(), etc., they work like this:

try {
while(true) {
pipe.next()
}
} catch() {}

This way, there is only one try/catch for the entire pipeline sequence.

If you can come up with a better solution, I'm more than happy to incorporate it as I've never liked the fact that hasNext() uses try/catch.

Take care,
Marko.



On Jul 30, 2012, at 5:36 AM, Danny Thomas wrote:

I noticed a large number of NoSuchElementExceptions are thrown by SingleIterator because AbstractPipe determines hasNext() by calling next() optimistically and expects an exception if no element is available. These exceptions are for flow control and are caught and handled in AbstractPipe, so there's no benefit to allocating a new exception or having the stack trace - have fast exceptions been considered?

Danny Thomas

unread,
Jul 31, 2012, 6:15:45 AM7/31/12
to gremli...@googlegroups.com
Thanks Marko,

I don't see any particular problem with using exceptions for flow control and wouldn't want to even begin refactoring the code. Fast exceptions deal with this just fine:

Before:

SingleIterator for single object: 100000 iterators constructed and next()'d twice to cause NoSuchElementException in 295.4235050678253ms

After (with other timing tests shown for comparison):

Running com.tinkerpop.pipes.util.iterators.SingleIteratorTest
        Arrays.asList() for single object: 100000 arrays constructed and next()'d in 27.52272403240204ms
        SingleIterator for single object: 100000 iterators constructed and next()'d in 8.329906940460205ms
        Arrays.asList() for single object: 100000 arrays constructed and next()'d in 18.0261470079422ms
        SingleIterator for single object: 100000 iterators constructed and next()'d in 7.1221760511398315ms
        SingleIterator for single object: 100000 iterators constructed and next()'d twice to cause NoSuchElementException in 13.894812941551208ms


Danny

Marko Rodriguez

unread,
Jul 31, 2012, 10:50:11 AM7/31/12
to gremli...@googlegroups.com
Wow. That is a very nifty trick.

Moreover, I appreciate the detailed 'pull request' comment with runtimes. 

If only all contributions could be so useful, clean, and easy.

Thank you,
Marko.

Danny Thomas

unread,
Jul 31, 2012, 11:42:15 AM7/31/12
to gremli...@googlegroups.com
Yeah, fast exceptions are my new favourite thing - I only just discovered this myself. I knew the HotSpot VM had this feature for core-exceptions, so went looking for whether people had done something for non-core exceptions. Scala uses the same trick with a ControlException trait, but without the static instance.

Background on HotSpot fast throw:


Danny

Marko Rodriguez

unread,
Jul 31, 2012, 11:54:56 AM7/31/12
to gremli...@googlegroups.com
Interesting. I didn't know that the time to throw an exception was based upon the time to gather the stack trace -- makes sense though. 

Now, if only someone could solve this problem:

Nudge nudge,
Reply all
Reply to author
Forward
0 new messages