Skip to content

Releases: aol/cyclops

v0.96

23 Jun 12:04
Compare
Choose a tag to compare

New in simple-react v0.96

Performance enhancements

New wait free Queue with mechanical sympathy

0.96 of simple-react adds support for simple-react Queue’s backed by a ManyToOneConcurrentArrayQueue.This is a Java implementation of an algorithm from Fast Flow, by the leading Java experts in this area (Martin Thompson, Richard Warburton, Todd Montgomery) via their Agrona project (which provides data structures and utilities used in the ultra-low-latency Aeron messaging system.

Performance characteristics

In simple benchmarking, LazyFutureStreams backed by an Agrona ManyToOneConcurrentArrayQueue can perform up to 40% faster than LazyFutureStreams backed by a JDK bounded wait free Queue (ConcurrentLinkedQueue). While results for most queue types showed significant variation in performance, throughput from LazyFutureStreams that are backed by Agrona ManyToOneConcurrentArrayQueue’s were much more stable. Differences in performance for LazyFutureStreams backed by ManyToOneConcurrentArrayQueue and ConcurrentLinkedQueue varied between 0 and over 40%. Non-blocking Queues performed up to twice as well as blocking queues (also with a lot of variation).

Bound size matters

Creating a bounded queue with a large buffer capacity can be expensive. Agrona ManyToOneConcurrentArrayQueue’s with a bound size of 200,000 entries were ~10 times slower than Agrona ManyToOneConcurrentArrayQueue’s with a bound size of 110.

JDK ConcurrentLinkedQueue is the default

Despite the improvements apparent from using the Agrona ManyToOneConcurrentArrayQueue as the backing Queue, we continue to use JDK ConcurrentLinkedQueue as the default. This is because it is impossible to tell what the bound size should be for all operations. For many / most operations, the bound size can be very similar to the concurrency level as determined by the MaxActive settings. But for other operators such as flatMap, it isn’t possible to tell how many elements would need to be buffered on the queue. For that reason, the backing queue is configurable per stage via two simple operators.

Non-blocking Queue operators

boundedWaitFree(int size)

This operator tells LazyFutureStream to use a bounded wait free queue for the subsequent stages (until configured otherwise). E.g.

new LazyReact(10,100)  //configure a LazyFutureStream builder with a thread pool of 10 threads, that accepts 100 concurrent tasks
        .react(toMyData)   //define the initial Suppliers to asynchronously react to
        .boundedWaitFree(110)  //use a bounded queue factory, with max queue size slightly above the max number of concurrent tasks
        .limit(400)    //take the first 400 elements from this async Stream. The limit operator makes use of an async Queue and can thus benefit from being backed by an Agrona wait free queue.
        .toList();

unboundedWaitFree()

This is the default operator and it tells LazyFutureStream to use an unbounded wait free Queue. Although algorithmically wait-free this Queue is more likely to experience contention at lower levels (e.g. via garbage collector activity, or invalidation of CPU caches), it is however, unbounded and as such

  1. does not incur significant queue creation costs
  2. less likely to cause data loss should flatMap based expansions turn out to be large.
 new LazyReact(10,100)  //configure a LazyFutureStream builder with a thread pool of 10 threads, that accepts 100 concurrent tasks
    .react(toMyData)   //define the initial Suppliers to asynchronously react to
    .boundedWaitFree(110)  //use a bounded queue factory, with max queue size slightly above the max number of concurrent tasks
    .limit(400)    //take the first 400 elements from this async Stream. The limit operator makes use of an async Queue and can thus benefit from being backed by an Agrona wait free queue.
    .unboundedWaitFree()  //switch to unboundedWaitFree before performing an large flatMap operation
    .flatMap(this::loadAndStream)
    .toList();

Recommendations

Use a boundedWaitFree queue where bound sizes can be reasonably asserted to be low, otherwise favor an unbounded wait free queue. Test, test, test your assumptions on performance critical paths.

What do we mean backed by a Queue?

simple-react works by perforrming aggregate operations over Streams of CompletableFutures. To perform more complex operations we often need the result that will be asynchronously populated in the Future. In order to keep data flowing smoothly through your Stream, we ‘plumb’ multiple different streams together internally, asynchronously populatng and extracting data from simple-react async.Queues. While the simple-react async.Queue provides the necessary logic to manage this, it isn’t in itself an actual Queue data structure implementation. The backing Queue is pluggable, and simple-react QueueFactories are provided for a range of blocking and non-blocking queue implementations.

Adding simple-react as a Dependency

Gradle

compile group: 'com.aol.simplereact', name:'simple-react', version:'0.96’

Maven

 <dependency>
   <groupId>com.aol.simplereact</groupId>
     <artifactId>simple-react</artifactId>
      <version>0.96</version>
     <scope>compile</scope>
   </dependency>

Javadoc

http://www.javadoc.io/doc/com.aol.simplereact/simple-react/0.96

v.095 of simple-react

11 Jun 10:21
Compare
Choose a tag to compare

New in simple-react v0.95

LazyFutureStream enhancements

Backed by a non-blocking wait free queue by default
Incremental Parallel Reduction
Collect /forEach / reduce all start fully asyncrhonous & parallel LazyFutureStreams in the same manner as Run (previously they would only allow one active chain of Futures at a time)

Interface enhancements

Creational methods following naming convention

of : data for immediate consumption
react : data for asynchronous consumption

 List<Data> result =  LazyFutureStream.of(1,2,3,4)
                                      .map(this:process)
                                      .run(Collectors.toList());

 List<Data> result =  EagerFutureStream.react(this::loadData1,this::loadData2,this::loadData3)
                                       .map(this:process)
                                       .toList();

Interface clean up

We are approaching the 1.0.0 release, and the interface will be more stable in the future. Dropped in this release where the simple-react generators and react collectors. Naming of creational methods was cleaned up to follow a pattern (see above).

General enhancements

Lombok removed as an runtime dependency
Guava replaced with lighterweight pcollections (simple-react-0.95-all.jar is ~400k)
Accept Executor rather than ExecutorService
Cyclops Monad comprehenders for use with Cyclops for comprehensions and Monad wrapper

Adding simple-react as a Dependency

Gradle

compile group: 'com.aol.simplereact', name:'simple-react', version:'0.95'

Maven

 <dependency>
   <groupId>com.aol.simplereact</groupId>
     <artifactId>simple-react</artifactId>
      <version>0.95</version>
     <scope>compile</scope>
   </dependency>

Javadoc

http://www.javadoc.io/doc/com.aol.simplereact/simple-react/0.95

v0.86 of simple-react

21 May 16:42
Compare
Choose a tag to compare

New in simple-react v0.86

Fix for #28

Adding simple-react as a Dependency

Gradle

compile group: 'com.aol.simplereact', name:'simple-react', version:'0.86'

Maven

 <dependency>
   <groupId>com.aol.simplereact</groupId>
     <artifactId>simple-react</artifactId>
      <version>0.86</version>
     <scope>compile</scope>
   </dependency>

Javadoc

http://www.javadoc.io/doc/com.aol.simplereact/simple-react/0.86

v0.85 simple-react : minor api clean up

21 Apr 16:16
Compare
Choose a tag to compare

New in simple-react v0.85

Minor API changes

Eager / Lazy static builder methods have been removed from EagerFutureStream, SimpleReactStream and LazyFutureStream.

EagerReact / LazyReact / SimpleReact .construct method has been cleaned up

Adding SimpleReact as a Dependency

Gradle

compile group: 'com.aol.simplereact', name:'simple-react', version:'0.85'

Maven

 <dependency>
   <groupId>com.aol.simplereact</groupId>
     <artifactId>simple-react</artifactId>
      <version>0.85</version>
     <scope>compile</scope>
   </dependency>

Javadoc

http://www.javadoc.io/doc/com.aol.simplereact/simple-react/0.85

v0.84 simple-react : Performance enhancements

07 Apr 13:47
Compare
Choose a tag to compare

New in simple-react v0.84

Performance enhancements

  • run operator for LazyFurtureStream uses CompletableFutures.anyOf rather than spin locking
  • new operators sync() and async()
  • new operators thenSync, peekSync, filterSync, doOnEachSync

Interface clean up

SimpleReact builder no longer supports lazy operation, use LazyReact / LazyFutureStream instead

async() and sync() operators

async() and sync() can used to determine if subsequent tasks should be executed on the same thread as the completing task, or if they should be resubmitted to an Executor Service where they may be executed on a different thread. If async() is used the next tasks will be resubmitted for execution, if sync() is used the next tasks will be executed on the same thread as the completing task.

On a quad-core Mac Book Pro it is possible to do around ~335 million map operations per second in sync mode versus ~33 million in async mode. Use async to distribute work across threads (or for blocking operations) and sync to continue working efficiently on the completing thread.

screen shot 2015-03-31 at 10 47 00 pm

A mix of async and sync execution. There is a performance overhead of submitting tasks to an ExecutorService - for non-blocking fast running code this should be avoided where possible.

screen shot 2015-03-31 at 10 47 06 pm

Typical aysnc execution where each completed task, triggers another task which submitted to an ExecutorService for execution.

Adding SimpleReact as a Dependency

Gradle

compile group: 'com.aol.simplereact', name:'simple-react', version:'0.84'

Maven

 <dependency>
   <groupId>com.aol.simplereact</groupId>
     <artifactId>simple-react</artifactId>
      <version>0.84</version>
     <scope>compile</scope>
   </dependency>

Javadoc

http://www.javadoc.io/doc/com.aol.simplereact/simple-react/0.84

v0.83 : PushableStreamBuilder

30 Mar 11:03
Compare
Choose a tag to compare

New in simple-react v0.83

v0.83 introduces the PushableStreamBuilder, a builder for building Java 8 Streams or LazyFutureStreams that can accept external data being pushed in.

Java 8 Streams operate under a pull model, pulling data along the Stream. simple-react Streams such as LazyFutureStream, EagerFutureStream and SimpleReactStream operate under a mixed pull / push model. See simple-react pull/push model for more details.

With simple-react async data structures both types of Streams (and jool Seqs) can be used on a push basis.

(simple-react pull/push model)

screen shot 2015-03-30 at 11 00 14 am

simple-react Stream accepting pushed data from an async.Queue.

screen shot 2015-03-30 at 11 10 22 am

Stream creation examples

Creating a Java 8 Stream from an async.Queue can be as simple as

 Queue<String> queue = QueueFactories.<String>unboundedQueue().build();
 queue.stream();

The PushableStreamBuilder offers a commond, simple way to build PushableStreams that allows users to configure backpressure support and whether or not the same data should be fed to multiple Streams.

e.g.

   PushableLazyFutureStream<Integer> pushable = new PushableStreamBuilder()
            .pushableLazyFutureStream();
  pushable.getInput().add(100);
  pushable.getInput().add(200);
  pushable.getInput().close();
  pushable.getStream().forEach(System.out::println)

Will print
100
200

  PushableStream<Integer> pushable = new PushableStreamBuilder()
            .pushableStream();
   pushable.getInput().add(10);
   pushable.getInput().add(20);
   pushable.getInput().close();
   pushable.getStream().forEach(System.out::println)

Will print
10
20

Adding SimpleReact as a Dependency

Gradle

compile group: 'com.aol.simplereact', name:'simple-react', version:'0.83'

Maven

 <dependency>
   <groupId>com.aol.simplereact</groupId>
     <artifactId>simple-react</artifactId>
      <version>0.83</version>
     <scope>compile</scope>
   </dependency>

Javadoc

http://www.javadoc.io/doc/com.aol.simplereact/simple-react/0.83

v0.82 simple-react

27 Mar 16:59
Compare
Choose a tag to compare

New in v0.82

All of the EagerFutureStream methods are asynchronous, but many of them will still wait until all processing of a stage is complete before moving to the next stage. See a list of affecting operators here :-
Alternatives are provided such as limitFutures, skipFutures, sliceFutures, partitionFutures, duplicateFutures, zipFutures, zipFuturesWithIndex etc.

Also new v0.82 is the ability to convert between EagerFutureStream and LazyFutureStream mid-stream and back. So users can switch to LazyFutureStream for the less efficient EagerFutureStream implementations and back again afterwards.

v0.82 also includes some performance / efficiency enhancements such as replace threads with simulated continuations in LazyFutureStream Queue population

Fixes for v0.82

runXXX methods not capturing errors : #19

Adding SimpleReact as a Dependency

Gradle

compile group: 'com.aol.simplereact', name:'simple-react', version:'0.82'

Maven

 <dependency>
   <groupId>com.aol.simplereact</groupId>
     <artifactId>simple-react</artifactId>
      <version>0.82</version>
     <scope>compile</scope>
   </dependency>

Javadoc

http://www.javadoc.io/doc/com.aol.simplereact/simple-react/0.82

v0.81 simple-react

27 Mar 15:13
Compare
Choose a tag to compare

fixes for v0.81

Fix issue with block for LazyFutureStream (was causing it run sequentially)
Fix issue #17 where xxxFutures methods running sequentially.
Fix api issue where some methods returning FutureStream rather than specific type

Adding SimpleReact as a Dependency

Gradle

compile group: 'com.aol.simplereact', name:'simple-react', version:'0.81'

Maven

 <dependency>
   <groupId>com.aol.simplereact</groupId>
     <artifactId>simple-react</artifactId>
      <version>0.81</version>
     <scope>compile</scope>
   </dependency>

Javadoc

http://www.javadoc.io/doc/com.aol.simplereact/simple-react/0.81

v0.80 Simple React : API and stability enhacements

23 Mar 14:10
Compare
Choose a tag to compare

API Enhancements

ReactPools :

Manages a pool of simple-react builder instances (REACTORs).
Streams can be executed within the pool, Pool can block if no capacity available or elastic pools that expand capacity on demand can be used.

ElasticPools

Sequential and Parallel standard REACTOR pools available for ease of use

Operator enhancements

Lot's of new and enhanced operators

zipping operators : combineLatest, withLatest
sharding operators : shard (map, fn)
Control operators - debounce, onePer, xPer, control (fn), skipUntil (stream), takeUntil (stream), jitter, fixedDelay
Batching operators - batchBySize, batchByTime, batch (fn)
Chunking operators - chunkSinceLastRead, chunkSinceLastReadIterator
Future operators for LazyFutureStream - zipFuturesWithIndex,duplicateFutures,zipFutures
clean up of Future operators API
doOnEach - perform an operation after each completion event in this stage, this operation does not form part of a stream / dataflow itself
firstOf - select first FutureStream to emit values

Fixes

Fix for #13

shard

shard allows a Stream to be partitioned by a function into multiple Streams.

eagerfuturestream shard

skipUntil

eagerfuturestream skipuntil

takeUntil

eagerfuturestream takeuntil

Zip operators

combineLatest

combineLatest takes the latest values from two Streams, unlike Zip however it does not wait for both Stream to emit new elements. Will use the last from the other Stream when one Stream emits a new element.

eagerfuturestream combinelatest

withLatest

withLatest takes the latest value from the current Stream when it emits a new value and combines it with the most recently emitted value from the provided Stream.

eagerfuturestream withlatest

Control operators

debounce

http://whatis.techtarget.com/definition/debouncing

Only allow a single element through within a specified time period, elements that aren't passed through are dropped

eagerfuturestream debounce

onePer & xPer

only allow one (or x) elements through in specified time period - slowing down the overall rate of flow. All elements are passed through.

fixedDelay

Imposes a fixedDelay between elements as they pass through the Stream

##Batching & Chunking operators

Batch

Batch takes a function to group elements into batches as they flow through. Provided functions include batchByTime and batchBySize.

eagerfuturestream batch

chunkSinceLastRead

chunks data passed through since last loop of iteration together into a batch.

eagerfuturestream chunksincelastread

Adding SimpleReact as a Dependency

Gradle

compile group: 'com.aol.simplereact', name:'simple-react', version:'0.80'

Maven

 <dependency>
   <groupId>com.aol.simplereact</groupId>
     <artifactId>simple-react</artifactId>
      <version>0.80</version>
     <scope>compile</scope>
   </dependency>

Javadoc

http://www.javadoc.io/doc/com.aol.simplereact/simple-react/0.80

v0.70 of simple-react : auto-closing streams

20 Mar 15:24
Compare
Choose a tag to compare

auto-close queues used in LazyFutureStreams. LazyFutureStream uses queues internally to perform some functions such as flatMap.

lazyfuturestream flatmap - toqueue

Improvements to the reliability of EagerFutureStream and SimpleReactStream when operating sequentially (free threaded mode).

Adding SimpleReact as a Dependency

Gradle

compile group: 'com.aol.simplereact', name:'simple-react', version:'0.70'

Maven

 <dependency>
   <groupId>com.aol.simplereact</groupId>
     <artifactId>simple-react</artifactId>
      <version>0.70</version>
     <scope>compile</scope>
   </dependency>

Javadoc

http://www.javadoc.io/doc/com.aol.simplereact/simple-react/0.70