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
2742 Olav Sandstaa 2008-12-08
WL#4654 New transaction dependency manager for Falcon
Patch 1 for optimization of read-only transactions: re-enable the call to
Transaction::commitNoUpdates(). The transaction object is deleted at the
end of Transaction::commitNoUpdates() and that no re-use of transaction objects
is implemented yet.
modified:
storage/falcon/Transaction.cpp
=== 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 push into mysql-6.0-falcon-ann branch (olav:2742 to 2743) WL#4654 | Olav Sandstaa | 9 Dec |