I've got a 66.18 Mops/sec for baseline, 1.662 Mops/sec on average for replay: 2.513% or 39.78 times slower. (Machine: C2D @ 2.4GHz, 4GB DDR2/800, Win7x86, Java 8b120).

I profiled the code and a "significant" time is taken by the onNext to get and iterate the observers of the state. A LinkedHashMap provides a traversal linear of size (HashMap is proportional to the capacity). In addition, wrapping the observer map into an unmodifiable map adds another overhead as two iterators are created per one onNext call. If I switch to direct LHM, I get 2.08 Mops/sec on average.

I've also tried removing the map from the state altogether and replaced it with a list of subscribers and observers. Adding is trivial and removing is done by not copying the observer with the given subscription. Got 2.29 Mops/sec on average.

In the third option, I ditched the collections in SubjectSubscriptionManager and implemented it over regular pair of arrays. Got 4 Mops/sec.

The next performance limit was the ```history.add```. I've tried adding an initial capacity to the ArrayList: 
- 64 -> 4.03 Mops/s
- 512 -> 3.78 Mops/s
- 1k -> 4.97 Mops/sec, 
- 2k -> 5.1 Mops/s
- 4k -> 4.1 Mops/s
-  64k -> 3.7 MOps/s

Of course, this is highly system/use case dependent, but it might be worth adding a ReplaySubject.create alternative which lets the user set the initial capacity of the buffer.

The final performance bottleneck was the SafeObserver.next. Doing a volatile swap-trick I've got 5.1 Mops/sec on average (i.e, with capacity start 1024 and object array state).