Optimise (further) the ChartCalculations methods 'getItemsPerInterval' &
'getCandleData' by replacing HashSets in the former with sorted sets,
which avoids relatively expensive calls to 'TradeStatistics3.hashCode'
and needless subsequent re-sorting by date in 'getCandleData'. (Forming
the trade statistics into an ImmutableSortedSet, OTOH, is cheap since
they are already encountered in chronological order.)
Further optimise the latter by using a primitive array sort of the trade
prices to calculate their median, instead of needlessly boxing them and
using 'Collections.sort'.
Provide a 'RangeUtils' class for computing subsets of a navigable set
with natural element order, with each bound defined by a mathematical
filter (that is, a predicate specifying whether an element is 'big' -
true, or 'small' - false), instead of a specific element. This allows
the subset of all elements which map into a given range to be computed,
provided the mapping function is (strictly or non-strictly) increasing.
Provide a fluent interface for this in RangeUtils (with unit tests).
To support this, provide a Comparable sub-interface, 'ComparableExt', of
elements which may be compared with marks/delimiters instead of just
elements of the same type, to work round the limitation that sorted (&
navigable) Sets/Maps in Java do not support general binary searching
with a filter (predicate) on the keys instead of just a specific key.
This will make it possible to efficiently take subsets of objects within
a given date range, say, without having to scan the entire set, provided
it is sorted (w.r.t. a suitable natural order).
The DaoStateStorageService submits tasks to a daemon thread executor
service. The JVM continues to execute threads until all non-daemon
threads have terminated. So the JVM will kill the DaoStateStorageService
during write requests leading to data corruption.
This change uses a non-daemon thread executor service at waits during
shutdown until all data is written to disk.
The previously used newCachedThreadPool carries higher risk for execution exceptions if exceeded.
Originally we had only one executor with a corePoolSize of 15 and a maximumPoolSize of 30 and queueCapacity was set to maximumPoolSize.
This was risky when the 15 corePool threads have been busy and new messages or connection creation threads are
queued up with potentially significant delay until getting served leading to timeouts.
Now we use (if maxConnections is 12) corePoolSize of 24, maximumPoolSize 36 and queueCapacity 10. This gives
considerable headroom. We also have split up the executors in 2 distinct ones.
Signed-off-by: HenrikJannsen <boilingfrog@gmx.com>