| # 21. Tuning The following is an overview over possible tuning switches that can be set when working with db4o. Users that do not care about performance may like to read this chapter also because it provides a side glance at db4o features with Alternate Strategies and some insight on how db4o works. ## 21.1. Enable Field Indexes The fastest way to improve the performance of your queries is to enable indexing on some of your class's key fields. Indexing is discussedelsewherein this tutorial. ## 21.2. Discarding Free Space
`Db4o.configure().discardFreeSpace(byteCount);`
Recommended settings for byteCount: - Integer.MAX_VALUE will turn freespace management off - Moderate range: 10 to 50 - Default built-in setting: 0 Advantage will reduce the RAM memory overhead and the speed loss from maintaining the freespace lists. Effect When objects are updated or deleted, the space previously occupied in the database file is marked as "free", so it can be reused. db4o maintains two lists in RAM, sorted by address and by size. Adjacent entries are merged. After a large number of updates or deletes have been executed, the lists can become large, causing RAM consumption and performance loss for maintenance. With this method you can specify an upper bound for the byte slot size to discard. Alternate Strategies Regular defragment will also keep the number of free space slots small. See:
`com.db4o.tools.Defragment`
(supplied as source code insrc/com/db4o/tools) If defragment can be frequently run, it will also reclaim lost space and decrease the database file to the minimum size. Therefore #discardFreeSpace() may be a good tuning mechanism for setups with frequent defragment runs. ## 21.3. Calling constructors
`Db4o.configure().callConstructors(true);`
Advantage will configure db4o to use constructors to instantiate objects. Effect On VMs where this is supported (Sun Java VM > 1.4, .NET, Mono) db4o tries to create instances of objects without calling a constructor. On Java VMs db4o is using reflection for this feature so this may be considerably slower than using a constructor. For the best performance on Java it is recommended to add a public zero-parameter constructor to every persistent class and to turn constructors on. Benchmarks on .NET have shown that the default setting ( #callConstructors(false) ) is faster. Alternate Strategies Constructors can also be turned on for individual classes only with
`Db4o.configure().objectClass(Foo.class).callConstructor(true);`
There are some classes (e.g. java.util.Calendar) that require a constructor to be called to work. Further details can be found in the chapter on Constructors. ## 21.4. Turning Off Weak References
`Db4o.configure().weakReferences(false);`
Advantage will configure db4o to use hard direct references instead of weak references to control instantiated and stored objects. Effect A db4o database keeps a reference to all persistent objects that are currently held in RAM, whether they were stored to the database in this session or instantiated from the database in this session. This is how db4o can "know" than an object is to be updated: Any "known" object must be an update, any "unknown" object will be stored as "new". (Note that the reference system will only be in place as long as an ObjectContainer is open. Closing and reopening an ObjectContainer will clean the references system of the ObjectContainer and all objects in RAM will be treated as "new" afterwards.) In the default configuration db4o uses weak references and a dedicated thread to clean them up after objects have been garbage collected by the VM. Weak references need extra ressources and the cleanup thread will have a considerable impact on performance since it has to be synchronized with the normal operations within the ObjectContainer. Turning off weak references will improve speed. The downside: To prevent memory consumption from growing consistantly, the application has to take care of removing unused objects from the db4o reference system by itself. This can be done by calling
`ExtObjectContainer.purge(object);`
Alternate Strategies
`ExtObjectContainer.purge(object);`
can also be called in normal weak reference operation mode to remove an object from the reference cache. This will help to keep the reference tree as small as possible. After calling #purge(object) an object will be unknown to the ObjectContainer so this feature is also suitable for batch inserts. ## 21.5. Defragment
`new Defragment().run("db.yap", delete);`
Advantage It is recommended to run Defragment frequently to reduce the database file size and to remove unused fields and freespace slots. Effect db4o does not discard fields from the database file that are no longer being used. Within the database file quite a lot of space is used for transactional processing. Objects are always written to a new slot when they are modified. Deleted objects continue to occupy 8 bytes until the next Defragment run. Defragment cleans all this up by writing all objects to a completely new database file. The resulting file will be smaller and faster. Alternate Strategies Instead of deleting objects it can be an option to mark objects as deleted with a "deleted" boolean field and to clean them out (by not copying them to the new database file) during the Defragment run. Two advantages: (1) Deleted objects can be restored. (2) In case there are multiple references to a deleted object, none of them would point to null. To clean out objects during the Defragment run, the Defragment source code would have to be modified. com.db4o.tools.Defragment is only supplied as source code to encourage embedding maintenance tasks. ## 21.6. No Shutdown Thread
`Db4o.configure().automaticShutDown(false);`
Advantage can prevent the creation of a shutdown thread on some platforms. Effect On some platforms db4o uses a ShutDownHook to cleanly close all database files upon system termination. If a system is terminated without calling ObjectContainer#close() for all open ObjectContainers, these ObjectContainers will still be usable but they will not be able to write back their freespace management system back to the database file. Accordingly database files will be observed to grow. Alternate Strategies Database files can be reduced to their minimal size with
`com.db4o.tools.Defragment`
(supplied as source code in /src/com/db4o/tools) ## 21.7. No callbacks
`Db4o.configure().callbacks(false);`
Advantage will prevent db4o from looking for callback methods in all persistent classes on system startup. Effect Upon system startup, db4o will scan all persistent classes for methods with the same signature as the methods defined in com.db4o.ext.ObjectCallbacks, even if the interface is not implemented. db4o uses reflection to do so and on constrained environments this can consume quite a bit of time. If callback methods are not used by the application, callbacks can be turned off safely. Alternate Strategies Class configuration features are a good alternative to callbacks. The most recommended mechanism to cascade updates is:
`Db4o.configure().objectClass("yourPackage.yourClass").cascadeOnUpdate(true);`
## 21.8. No schema changes
`Db4o.configure().detectSchemaChanges(false);`
Advantage will prevent db4o from analysing the class structure upon opening a database file. Effect Upon system startup, db4o will use reflection to scan the structure of all persistent classes. This process can take some time, if a large number of classes are present in the database file. For the best possible startup performance on "warm" database files (all classes already analyzed in a previous startup), this feature can be turned off. Alternate Strategies Instead of using one database file to store a huge and complex class structure, a system may be more flexible and faster, if multiple database files are used. In a client/server setup, database files can also be switched from the client side with
`((ExtClient)objectContainer).switchToFile(databaseFile);`
## 21.9. No lock file thread
`Db4o.configure().lockDatabaseFile(false);`
Advantage will prevent the creation of a lock file thread on Java platforms without NIO (< JDK 1.4.1). Effect If file locking is not available on the system, db4o will regularily write a timestamp lock information to the database file, to prevent other VM sessions from accessing the database file at the same time. Uncontrolled concurrent access would inevitably lead to corruption of the database file. If the application ensures that it can not be started multiple times against the database file, db4o file locking may not be necessary. Alternate Strategies Database files can safely be opened from multiple sessions in readonly mode. Use:
`Db4o.configure().readOnly(true)`
## 21.10. No test instances
`Db4o.configure().testConstructors(false);`
Advantage will prevent db4o from creating a test instance of persistent classes upon opening a database file. Effect Upon system startup, db4o attempts to create a test instance of all persistent classes, to ensure that a public zero-parameter constructor is present. This process can take some time, if a large number of classes are present in the database file. For the best possible startup performance this feature can be turned off. Alternate Strategies In any case it's always good practice to create a zero-parameter constructor. If this is not possible because a class from a third party is used, it may be a good idea to write a translator that translates the third party class to one's own class. The dowload comes with the source code of the preconfigured translators in src/com/db4o/samples/translators. The default configuration can be found in the above folder in the file Default.java/Default.cs Take a look at the way the built-in translators work to get an idea how to write a translator. It just requires implementing 3 (4 for ObjectConstructors) methods and configuring db4o to use a translator on startup with
`Db4o.configure().objectClass("yourPackage.yourClass").translate()`
## 21.11. Increasing the maximum database file size
`Db4o.configure().blockSize(newBlockSize); Defragment.main(new String[] {"mydb.yap"});`
Advantage Increasing the block size from the default of 1 to a higher value permits you to store more data in a db4o database. Effect By default db4o databases can have a maximum size of 2GB. By increasing the block size that db4o should internally use, the upper limit for database files sizes can be raised to multiples of 2GB. Any value between 1 byte (2GB) to 127 bytes (254GB) can be chosen as the block size. Because of possible padding for objects that are not exact multiples in length of the block size, database files will naturally tend to be bigger if a higher value is chosen. Because of less file access cache hits a higher value will also have a negative effect on performance. A very good choice for this value is 8 bytes, because that corresponds to the slot length of the pointers (address + length) that db4o internally uses. Alternate Strategies It can also be very efficient to use multiple ObjectContainers instead of one big one. Objects can be freely moved, copied and replicated between Objectcontainers. ## 21.12. FlushFileBuffers(false)
`Db4o.Configure().FlushFileBuffers(false);`
Advantage Setting FlushFileBuffers to false can considerably improve the performance saving time on physical disk access. Effect FlushFileBuffers setting is provided to ensure correct transaction flow in cases of hardware, power or operating system failures. ACID transaction is ensured when disc writes are fulfilled in the following order. 1) a list of "pointers that are to be modified" is written to the database file; 2) the database file is switched into "in-commit" mode; 3) the pointers are actually modified in the database file; 4) the database file is switched to "not-in-commit" mode. The Configuration.FlushFileBuffers(true) setting ensures that after each stage of commit process all the buffered data is written to the database file. The write process is comparatively slow and can have a strong impact on performance. Setting FlushFileBuffers(false) reduces the time spent on transaction commit. From the other side this setting can be potentially dangerous on systems using in-memory file caching. The buffer cache is usually used to improve writing performance. Instead of carrying out all writes immediately, the kernel stores data temporally in the buffer cache, waiting to see if it is possible to group several writes together. Cached file changes can also be reversed. For example, if the same place in a file was changed several times it is enough to write only the final change. In case of transaction commit such cache management means that transaction data may be lost. Lets consider the case when crash occurs on stage 2-4 and list of "pointers to be modified" is still in cache (completely or partly). After the database file is reopened the commit will be restarted using the list of pointers that is supposed to be written to disc. But in fact we do not know, whether the list was written to disc completely or part of it was still in cache and lost during restart, - so the database can be corrupted. Alternate Strategies On operating systems that cache file access, this configuration has to be set to true to ensure each step of transaction being written in order.
`Db4o.Configure().FlushFileBsuffers(true);`
Otherwise file caching can be switched off in OS settings. -- generated by Doctor courtesy of db4objects Inc.