# Adaptive Versioning in Transactional Memory Systems +
## 4 Basic Adaptive Versioning
### Adaptive for Persistent Memories  
The idea we employ in Adaptive for persistent memories is to compute the number of data movements for eager and lazy versioning, separately, and switch between these methods when the data movement increases. Ideally, we would like to use the versioning method that gives optimum data movement performance for any specific workload. We use the following notions. Let \(N\) be the total number of transactions in any workload. When the workload finishes execution and all transactions commit, we have \(N_{commit}=N\) number of commits and \(N_{abort}\geq 0\) number of aborts (if each transaction commits without even aborting a single time, then \(N_{abort}=0\), otherwise \(N_{abort}>0\)). Suppose each transaction \(T\) has read write set \(RW(T)\) of size \(S\). If \(T\) comes to the system at time \(t>t_{0}\) after at least a transaction finishes executing one time (irrespective of whether that transaction aborts or commits), then it is executed based on the following parameters computed in Adaptive from time \(t=0\) until time \(t\). 1. \(AAR=\frac{N_{abort}}{N_{commit}+N_{abort}}\); _average abort ratio_ of transactions in Adaptive (using total aborts in both eager and lazy versioning). 2. \(AAR_{Eager}=\frac{N_{Eabort}}{N_{Ecosunit}+N_{Eabort}}\)_; average abort ratio_ of transactions in Adaptive executed using eager versorting. 3. \(ACR_{Eager}=\frac{N_{Eabort}}{N_{Ecosunit}}\)_; abort to commit ratio_ of transactions in Adaptive executed using eager versorting. 4. \(ACR_{Lazy}=\frac{N_{Labor}}{N_{Lcommit}}\)_; abort to commit ratio_ of transactions in Adaptive executed using lazy versioning. At any time \(t\geq 0\), \(0\leq AAR\leq 1\) and \(0\leq AAR_{Eager}\leq 1\). At any time \(t>t_{0}\) in Adaptive, \(T\) is executed using lazy versioning if (i) \(AAR\geq\frac{2}{3}\) or (ii) \(ACRE_{Eager}>ACR_{Lazy}\) and \(AAR_{Eager}\geq\frac{2}{3}\). Otherwise, \(T\) is executed using eager versioning. We call the value \(\frac{2}{3}\)_switching threshold_ and we describe later how this switching threshold \(\frac{2}{3}\) is computed. The motivation behind using \(\frac{2}{3}\) as switching threshold in Adaptive for persistent memories is that it works on all the benchmarks we experimented our framework against. We now discuss how the switching threshold is computed. Computation of Switching Threshold in Persistent Memories  
The computation of switching threshold is based on the total movements of data from one memory location to the other (i.e., total number of loads and stores). The motivation behind using this metric for the computation of switching threshold is that the time spent by a transaction to load and store data from and to the memory addresses plays significant role in total execution time. Our objective in the design of Adaptive is to dynamically switch between the two versioning methods to obtain less number of data movements, and in return minimize execution time. Let \(W_{Eager}\) be the total number of operations of moving data in eager versioning (i) from the original persistent memory locations to the undo log area and (ii) from the undo log area back to the original persistent memory locations. The first kind of moves are shown as 1 in Figure 0(a) and the second kind of moves are shown as 2 in Figure 0(a). The first kind of moves are always done in eager versioning and the second kind of moves are done only when the transaction aborts. Therefore,  
\[W_{Eager}=(N_{commit}+2N_{abort})\cdot S \tag{2}\]  
Let \(W_{Lazy}\) be the total number of operations of moving data in lazy versioning (i) from the original persistent memory locations to the redo log area (in volatile cache), (ii) from the redo log area (in volatile cache) to persistent memory locations to persist the redo log, and (iii) finally, writing the data back to the original persistent memory locations either from redo log area in persistent memory after restart or from redo log area in volatile cache.