## 1 Introduction  
Microprocessor technology has been developed to have a larger number of cores and sockets after reaching the limit of performance improvement in a way that increases the transistor density [1; 2]. Manycore systems have tens or hundreds of CPU cores to improve processing power [3; 4; 5]. However, in manycore systems, contention for shared data between the cores becomes more intense, so a large number of CPU cores cannot be fully utilized. Therefore, it causes a problem of degradation of the overall system performance [6]. As the number of cores increases, the synchronization cost including the cost of cache coherence increases exponentially, which prevents the system from reaching the expected performance improvement [6]. The main cause of such performance degradation is the lack of a proper synchronization mechanism [7; 8]. The system performance is greatly affected by the synchronization mechanism. Synchronization mechanisms are essential in designing operating systems, database systems, network stacks, storage systems, etc. and have a significant impact on performance. Synchronization approaches for linearly scalable performance on modern manycore machines have been extensively investigated, although they remain a work in progress. Synchronization mechanisms for scalable performance have been studied in various ways. The traditional way to synchronize shared data accesses between many threads is to exploit a lock mechanism for mutual exclusively accessing the data [7; 9]. Lock-based synchronization mechanisms block other competing threads when a thread acquires a lock on a shared resource. spinlock is a representative lock algorithm that is intuitive and simple; however, the performance is very poor when there are high competition for shared data, and it causes deadlock, priority inversion, etc. Although many researchers worked to improve the performance of spinlock via reducing the contention overhead [10; 11; 12], but the issue still remains in the recent manycore environment [8; 13]. To address the issues in the blocking synchronization mechanisms, the research community shifted its focus on the non-blocking synchronization mechanisms [14; 15; 16; 17; 18; 19]. The non-blocking mechanism guarantees that a thread is not blocked nor failed while accessing shared data [20]. RCU is a non-blocking mechanism that has been used for some time now due to its high performance on a manycore environment [21]. Linux adopted RCU in the kernel since 2002, and the usage has rapidly increased from 3000 in 2010 to more than 16,000 in 2020 [21; 22; 23]. One of merits of RCU is its scalability. RCU allows multiple threads to read the shared resource while a thread is writing to the shared resource. However, RCU has disadvantages in that it is difficult to program when the data structure is complex (e.g., binary search tree), and the scalability is poor when there are some write operations. To overcome the shortcomings of RCU, RLU (Read-log-update) [24] and MV-RLU (Multi-version read-log-update) [25] were introduced. RLU is a non-blocking synchronization mechanism designed to compensate for the disadvantages of RCU: its programming complexity and write performance degradation. RLU provides database transaction-like programming interfaces, making it much simpler to write applications compared to the interface of RCU. It allows reading objects concurrently and writing different objects simultaneously. However, RLU keeps only two versions per object. Thus, when there are multiple write requests to an object, RLU suffers from severe processing delay caused by cleaning up the previous version. Another non-blocking synchronization mechanism, MV-RLU, overcomes the issue by introducing multi-version logging to the mechanism. Unlike RLU, MV-RLU minimizes the request processing delay by keeping a number of different versions of the object. Since MV-RLU keeps multi-version logs of an object, multiple threads can access shared resources at the same time.