Many JavaSpace applications follow the same 'principle of locality' (referred to as POL throughout the rest of this text) as their single-process, non-remote brethren. The POL essentially amounts to a rule of thumb - 'a program will access 10% of a program 90% of the time'. This same principle also applies to data access, though not quite as strongly. What does this mean for JavaSpace applications?
Clearly, not all entry's written to a space fall into any of the above categories. Those that do form the working set.
Microprocessors and operating systems exploit the POL to boost performance using caching. In any given situation, the perfect cache is one that:
So, for Blitz to perform at it's best, we'd like the entire working set of entry's to be held in cache. Clearly, in cases where the working set is large, we may not be able to fit it all in cache. When this happens, we rely on the cache replacement policy to make best use of the cache.
Blitz stores segments Entry's by type storing them in separate repositories. Each respository contains two kinds of cache:
The Entry Cache is designed to accelerate repeated access to Entry's such as queue heads/tails or tokens. Write Buffer is designed to take advantage of the fact that many JavaSpace applications use flow-type models which results in many recently written Entry's being taken almost immediately afterward. It caches recently written entry's anticipating that they will be almost immediately taken/deleted. Everytime this happens, Write Buffer saves us disk accesses.
Blitz provides various storage models offering different tradeoffs between level of persistence and performance - see Appendix A for more details.
take
is commonly used), size the cache as size_of_working_set + (25% of size_of_working_set)
. The Write Queue should then be configured to at least 2 * entry_cache_size
.If at all possible, leave lease reaping turned off (lease reaping is the term we use for the process of actively trawling through all entries in a Blitz instance deleting those that have expired).
If your application requires significant RemoteEvent
throughput (as the result of using notify
) or needs to handle dispatching of a large number of blocking queries (as the result of a large number of clients waiting for entry's using read*
or take*
with non-zero timeouts), increase the number of task threads.
Both persistent and time-barrier persistent storage models make use of a log to provide their persistence guarentees. In the case of persistent, once all the above steps have been taken, Blitz's performance will most likely be determined by the speed with which it can log sequentially to disk. This aspect of the persistent model should be tuned as follows:
write
s and take*
s (if you wish to tune for these situations set the window to zero) but will provide a performance boost at any reasonable concurrent load.take*
s, read*
s or write
s performed with a null
transaction are treated as transactions containing a single operation. Adjusting this value changes the balance between speed of recovery versus overall throughput.
The time-barrier persistent storage model doesn't support concurrent batching (this is achieved naturally by the design) but usually requires a much larger log buffer than the default persistent storage model because it will tend towards writing larger numbers of log records in batches.
As of Blitz 2.0, it is possible to configure a number of different persistence profiles. They are currently:
OutOfMemoryError
's if they are over-filled. Blitz avoids this problem by swapping to disk when the number of stored Entry
's overflows it's available cache space. Obviously, performance will degrade relative to the amount of swapping Blitz is required to perform. When the caches are sufficiently large, Blitz will make minimal use of disk, yielding maximal performance.The actual model used is determined by the value of the configuration variable storageModel
. The standard configuration file contains example settings for all three modes which should provide reasonable starting points for more precise tuning. For more details on the exact settings for each model, including tuning options, see the Javadoc for org.dancres.blitz.config.Persistent
, org.dancres.blitz.config.Transient
and org.dancres.blitz.config.TimeBarrierPersistent
.
persistDir
- location for persistent storage. Contains entry's, entry meta data, indexes etc.logDir
- location for log files.dbCache
- the size (in bytes) of the Berkeley DB cache.entryReposCacheSize
- the size of the entry cache - each entry type has it's own cache.leaseReapInterval
- not a performance option as such - determines how often Blitz actively searches for and delete's lease expired entry's.maxTaskThreads
- the maximum number of threads to use to dispatch blocked takes or reads or deliver RemoteEvents.dumpDbStats
- enable dumping of Berkeley Db cache stats. Fewer misses means better performance.dumpWQStats
- enable dumping of write queue statistics. Used to monitor disk I/O (only truly useful to a Blitz system engineer).logCkpts
- enable dumping of checkpointing stats.stats
- sets defaults for statistics available via the statistics API (see Blitz Extensions).