List:Commits« Previous MessageNext Message »
From:Olav Sandstaa Date:December 9 2008 9:01am
Subject:bzr commit into mysql-6.0-falcon-ann branch (olav:2743) WL#4654
View as plain text  
#At file:///home/os136802/mysql/develop/repo/falcon-newdeps5-allocate/ based on revid:olav@stripped

 2743 Olav Sandstaa	2008-12-09
      WL#4654 New transaction dependency manager for Falcon
            
      Patch 2 for optimization of read-only transactions: Optimize transaction
      object allocations: introduce code
      that checks if there is a transaction objects that is in state 
      available in the active transaction list when starting a new transaction. 
      It this is the case we alloacte this transaction object using a CAS
      operation while only having a shared lock on the list. In order to have
      available un-used transaction objects we pre-allocate some extra
      (10) non-used transaction objects each time we need to set an exclusive
      lock on the active transaction list.
      
      The performance improvement is achieved by being able to allocate
      a transaction object using only a shared lock on the active transaction
      list.
      
      A consequence of this change is that the active transaction list no longer
      will can be assumed to be sorted on transaction id. As a consequence,
      TransactionManager::purgeTransaction now needs to go through the list
      to find the oldest transaction in the active list instead of just
      checking the first transaction in the list.
modified:
  storage/falcon/TransactionManager.cpp
  storage/falcon/TransactionManager.h

per-file messages:
  storage/falcon/TransactionManager.cpp
    Added code to TransactionManager::startTransaction() that searches the active
    transaction list to see if there are any available transaction objects that
    can be reused (instead of having to allocated a new). If an available
    transaction object is found it is acquired using a CAS operation while having a shared lock on the list. To increas the probability of finding
    an available transaction object in the list, ten new un-used transaction
    objects is added to the list each time we need to set an exclusive lock on
    the list.
    
    This change to TransactionManager::startTransaction() changes the
    active transaction list from being sorted on transaction id to not 
    guarantee that it is sorted. TransactionManager::purgeTransaction now
    needs to go through the active transaction list to find the oldest 
    transaction instead of just checking the first transaction in the list.
  storage/falcon/TransactionManager.h
    New method for finding the oldest active transaction in the active transaction list.
=== modified file 'storage/falcon/TransactionManager.cpp'

=== modified file 'storage/falcon/TransactionManager.cpp'
--- a/storage/falcon/TransactionManager.cpp	2008-12-08 11:28:35 +0000
+++ b/storage/falcon/TransactionManager.cpp	2008-12-09 09:01:41 +0000
@@ -32,7 +32,8 @@
 #include "Thread.h"
 
 static const int EXTRA_TRANSACTIONS = 10;
-static const TransId TRANS_ID_MAX = UINT_MAX;
+
+static TransId OLD = 0;  // Temporary for debugging
 
 #ifdef _DEBUG
 #undef THIS_FILE
@@ -114,14 +115,72 @@
 	return oldest;
 }
 
+
+TransId TransactionManager::findOldestInActiveList() const
+{
+	// Find the transaction id of the oldest active transaction in the 
+	// active transaction list. If the list is empty, the
+	// latest allocated transaction id will be returned.
+	// This method assumes that the caller have set at least a shared lock
+	// on the active list.
+
+	// Note: Here we operate on a transaction list where we allow 
+	// non-locking transaction allocations and de-allocations from so be 
+	// careful when updating this method.
+
+	// NOTE: This needs to be updated when we allow transaction id to wrap
+
+	TransId oldest = transactionSequence;
+	
+	for (Transaction *transaction = activeTransactions.first; transaction; transaction = transaction->next)
+		{
+		TransId transId = transaction->transactionId;
+		if (transaction->isActive() && (transId != 0 && transId < oldest))
+			oldest = transId;
+		}
+	
+	return oldest;
+}
+
+
 Transaction* TransactionManager::startTransaction(Connection* connection)
 {
+	// Go through the active transaction list to check if there are any
+	// transaction objects in state "Available" that can be re-used.
+	// Note that this is done using a shared lock on the active transaction
+	// list.
+
 	Sync sync (&activeTransactions.syncObject, "TransactionManager::startTransaction");
+	sync.lock(Shared);
+	Transaction *transaction;
+
+	for(transaction = activeTransactions.first; transaction; transaction = transaction->next)
+		if (transaction->state == Available)
+			if (COMPARE_EXCHANGE(&transaction->state, Available, Initializing))
+				{
+				transaction->initialize(connection, INTERLOCKED_INCREMENT(transactionSequence));
+				return transaction;
+				}
+
+	sync.unlock();
+
+	// We did not find an available transaction object to re-use, 
+	// so we allocate a new and add to the active list
+
 	sync.lock(Exclusive);
 
-	Transaction *transaction = new Transaction (connection, INTERLOCKED_INCREMENT(transactionSequence));
+	transaction = new Transaction(connection, INTERLOCKED_INCREMENT(transactionSequence));
 	activeTransactions.append(transaction);
 
+	// Since we have acquired the exclusive lock on the active transaction
+	// list we allocate some extra transaction objects for future use
+
+	for (int n = 0; n < EXTRA_TRANSACTIONS; ++n)
+		{
+		Transaction *trans = new Transaction(connection, 0);
+		activeTransactions.append(trans);
+		}
+
 	return transaction;
 }
 
@@ -305,13 +364,11 @@
 
 	// Find the transaction id of the oldest active transaction
 
-	TransId oldestActive = TRANS_ID_MAX;
-
-	if (activeTransactions.first != NULL)
-		{
-		oldestActive = activeTransactions.first->transactionId;
-		}
-	
+	TransId oldestActive = findOldestInActiveList();
+
+	ASSERT(oldestActive >= OLD);   // Temporary for debugging
+	OLD = oldestActive;            // Please ignore
+
 	// Check for any fully mature transactions to ditch
   
     Transaction* transaction = committedTransactions.first;

=== modified file 'storage/falcon/TransactionManager.h'
--- a/storage/falcon/TransactionManager.h	2008-12-08 11:28:35 +0000
+++ b/storage/falcon/TransactionManager.h	2008-12-09 09:01:41 +0000
@@ -40,6 +40,7 @@
 	void			rollbackByXid(int xidLength, const UCHAR* xid);
 	void			print(void);
 	Transaction*	findOldest(void);
+	TransId			findOldestInActiveList() const;
 	void			getTransactionInfo(InfoTable* infoTable);
 	void			purgeTransactions();
 	void			purgeTransactionsWithLocks();

Thread
bzr commit into mysql-6.0-falcon-ann branch (olav:2743) WL#4654Olav Sandstaa9 Dec