Every user who works with OrientDB knows that to manipulate records he or she has to create
ODatabaseDocumetTX an instance first. But there is a wide misunderstanding about the meaning of this object. Many users think that this object may be treated as an abstraction of data which are stored on disk and placed on a server. As a result, they create a single instance of this object per thread, assign it to the class field and use the same object during whole application life. That is “not performance” wise decision. There are several reasons why you should consider using short living database instance acquired from the pool for example from OPartitionedDatabasePool instead.The most important reason is that during loading of records we put records into the local cache which is based on
WeakHashMap. We need this cache for 2 reasons:- To avoid OConcurrentModificationExceptionin the case of loading of the same record in a call stack.
- To speed up graph traversal.
Let's look how 
WeakHashMap works (in OpenJDK at least):- Every put/get/remove method of this HashMapcalls getTable() method.
- Which in turn calls the expungeStaleEntries().
The responsibility of the last method is to remove weak references which are already not accessible. 
expungeStaleEntries() use ReferenceQueue which was passed during the creation of WeakReference to detect unreachable references.
The main problem there is mechanics which is used to fill in and pull items from reference queue. When weak reference is becoming a subject of garbage collection special thread which has high priority 
java.lang.ref.Reference.ReferenceHandler put such reference into reference queue. But reference queue itself is guarded by object wide lock !
Let’s put all of this together:
- You have long living ODatabaseDocumetTXinstance.
- You use it to load many short living record objects.
- You have WeakHashMappolluted by manyWeakReferences.
- After next GC run ReferenceHandlerstarts to pull and lockReferenceQueueand as result lockWeakHashMapobjects.
- Your threads become frozen for a long time. We know situations when threads were frozen for several seconds !
So the main rule of thumb - never use long living 
ODatabaseDocumetTX instances, use database pool instead. Despite solving the problem described above pool also provides support for nested transactions.
P.S. In 3.0 version we are going to implement WeakHashMap which will be based on Hopscotch hashing algorithm and will not suffer from synchronization problem described above.

 
No comments :
Post a Comment