{'fraction_non_alphanumeric': 0.04558737580362361, 'fraction_numerical': 0.0067212156633547635, 'mean_word_length': 4.584013050570962, 'pattern_counts': {'":': 0, '<': 0, '<?xml version=': 0, '>': 0, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
Analysis of Amortized Time Complexity of Concurrent Binary Search Tree

The dictionary is one of the most often-used abstract data types (ADT) in computer science. Much work has been done to implement this ADT in the concurrent setting. Most of this work uses locks (see, e.g., [2], [8]). Although locks are simple to use, this approach has a major disadvantage: it is hard to design scalable locking strategies due to problems such as deadlock, priority inversion, and convoying [6]. For this reason, it is desirable to build a non-blocking implementation. Furthermore, the non-blocking property ensures that, while a single operation may be delayed, the system as a whole will always make progress. Some other dictionary implementations use operations that are not commonly supported by multi-core machines, such as load-link/store-conditional [1] and multi-word compare-and-swap (CAS) [7]. The dictionary has also been implemented by means of software transactional memory (STM) (see, e.g., [9]). However, such an implementation is currently not efficient [2]. Most multi-core machines support single-word CAS operations. Non-blocking dictionary implementations based on linked lists and skip lists have been implemented by Sundell and Tsigas [10], Fomitchev and Ruppert [5], Fraser [7], and Valois [11]. Valois also presented a sketch of a non-blocking binary search tree (BST) [11]. The first complete non-blocking BST algorithm was presented by Ellen et al. [4]. This was also the first practical non-blocking tree data structure. In [3], we have generalized their BST to a k-ary search tree (k-ST). Each internal node contains k − 1 keys and has k children. Larger k values decrease the average depth of nodes, allowing faster searches. However, this also increases the local work done at each internal node for routing searches and performing updates to the tree. We have implemented both the BST of Ellen et al. and our k-ST in Java. We conducted an experiment to compare both implementations against the concurrent Skip List (SL) from the Java class library and the lock-based AVL tree of Bronson et al [2]. The AVL tree is the current leading concurrent search tree. In [2], Bronson et al. presented experimental results comparing their tree with SL, a lock-based red-black tree, and a red-black tree implemented using STM. Since SL and AVL drastically outperform the other two implementations, we did not include the others in our comparison. In our experimental results, BST and 4-ST (k-ST with k = 4) are the top performers in both high and low contention. When the tree is small and the contention is high, the simplicity of BST gains advantages. On the other hand, when the tree is large (low contention), the shallower tree depth of 4-ST makes it faster than other algorithms. In our experimental setup, we did not observe any significant benefit of using values of k greater than four. Our previous work focused on giving an empirical analysis of BST’s performance. In this paper, we present a modification to the non-blocking BST implementation of Ellen et al. and an analysis of the modified implementation’s amortized time complexity. Given a finite concurrent execution of a number of data structure operations, the amortized cost is defined as the total amount of work done by the system divided by the number of operations invoked. Amortized analysis ensures that, even in the worst-case execution,