Optimizing JDataStore applications

JDataStore is a feature of JBuilder Professional and Enterprise, and the Inprise Application Server.
This chapter discusses issues that will help improve the performance, reliability, and size of JDataStore applications. Unless otherwise specified, DataStoreConnection refers to either a DataStoreConnection or DataStore object used to open a connection to a JDataStore file.


General usage recommendations

Here are a few items that concern usage for all types of JDataStore applications.

Closing the JDataStore

Be sure to call DataStoreConnection.close() when the DataStoreConnection is no longer needed, or call DataStore.shutdown() to close the JDataStore file regardless of how many connections there may be. In particular,

Closing a JDataStore ensures that all modifications are saved to disk. There is a daemon thread for all open DataStoreConnection instances that is constantly saving modified cache data (by default modified data is saved every 100 milliseconds). If you directly exit the Java VM, the daemon thread might not have the opportunity to save the last set of changes. There is a small chance that a non-transactional JDataStore may get corrupted.

A transactional JDataStore is guaranteed to not lose data, but the transaction manager rolls back any uncommitted changes.

If a JDataStore file isn't closed properly, it takes several seconds to reset/recover the JDataStore file. Proper closure means that the JDataStore reopens quickly every time.

Another benefit to closing DataStoreConnection objects is that when they are all closed, the memory allocated to the JDataStore cache is released.

Close all StorageDataSets that have their store property set to a DataStoreConnection when you are done with them. This frees up JDataStore resources associated with the StorageDataSet and allows the StorageDataSet to be garbage collected.

Controlling how often cache blocks are written to disk

Use the saveMode property of the DataStore component to control how often cache blocks are written to disk. This property applies only to non-transactional JDataStores. The following are valid values for the method:

Unlike other properties of DataStore, saveMode can be changed when the connection is open. For example, if you are using a DataStoreConnection, you can access the value through the dataStore property:

DataStoreConnection store = new DataStoreConnection();
// ...
store.getDataStore().setSaveMode(2);

Note that this changes the behavior for all DataStoreConnection objects that access that particular JDataStore file.

Tuning memory

You can tune the use of memory in a number of ways. Be aware that asking for too much memory can be as bad as having too little.

Miscellaneous performance tips

Here are some tips that can help performance:

DataStore companion components

The dbSwing component library provides two components (on the More dbswing page of the component palette) that make it easier to produce robust JDataStore applications.


Using data modules

When using a JDataStore with a StorageDataSet, you should almost always group them all inside data modules. Make any references to these StorageDataSets through DataModule accessor methods such as businessModule.getCustomer(). You should do this because much of the functionality surfaced through StorageDataSets is driven by property and event settings. Although most of the important structural StorageDataSet properties are persisted in the JDataStore itself, the classes that implement the event listener interfaces aren't. By instantiating the StorageDataSet with all event listener settings, constraints, calculated fields, and filters implemented with events, they are properly maintained at run time and design time.


Optimizing transactional applications

The increased reliability and flexibility you gain from using transactional JDataStores comes at the price of some performance. You can reduce this cost in several ways.

Using read-only transactions

For transactions that are reading but not writing, significant performance improvements can be realized by using a read-only transaction. The DataStoreConnection's readOnlyTx property controls whether a transaction is read-only. This property must be set to true before the connection is open. For JDBC connections, it is controlled by the readOnly property of the java.sql.Connection object (returned by the java.sql.DriverManager.getConnection() and com.borland.dx.dataset.sql.Database.getJdbcConnection() methods).

Read-only transactions work by simulating a snapshot of the JDataStore. Only data from transactions committed at the point the transaction started are seen in this snapshot (otherwise, the connection would have to see if there are pending changes and roll them back whenever it accesses the data). A snapshot is taken when the DataStoreConnection opens, and it refreshes every time its commit() method is called.

Another benefit of read-only transactions is that they aren't blocked by writers (or other readers). Both reading and writing usually require a stream lock. But because a read-only transaction uses a snapshot, it doesn't need a lock. Therefore it won't be blocked by a writer that has a lock on a stream that it's modifying.

You can further optimize the application by specifying a readOnlyTxDelay. By default, this property is zero, which means that whenever a read-only transaction starts or refreshes, a new snapshot is taken. The readOnlyTxDelay property specifies the maximum age (in milliseconds) for an existing snapshot that the connection can share. When the property is non-zero, existing snapshots are searched from most recent to oldest. If there is one that is under readOnlyTxDelay in age, it is used and no new snapshot is taken.

Using soft commit mode

If you enable soft commit mode through the TxManager's softCommit property, the transaction manager forces disk writes for the purposes of crash recovery, but it doesn't guarantee transaction commits. This improves performance, but makes you slightly more susceptible to power loss, operating system crashes, and hardware failures.

Very recently committed transactions--depending on the operating system, but in general those committed within approximately the last second--aren't guaranteed to be written. This isn't the case when soft commit mode is disabled (the default), when committed changes are written immediately.

Transaction log files

The TxManager's ALogDir and BLogDir properties control the location of the transaction log files.

Disabling status logging

You can also improve performance by disabling the logging of status messages. To do this, set the recordStatus property of the TxManager to false.


Pruning deployed resources

When deploying a JDataStore application, you can exclude certain classes and graphics files that aren't used. In particular: