• Peng Zhang's avatar
    maple_tree: introduce interfaces __mt_dup() and mtree_dup() · fd32e4e9
    Peng Zhang authored
    Introduce interfaces __mt_dup() and mtree_dup(), which are used to
    duplicate a maple tree.  They duplicate a maple tree in Depth-First Search
    (DFS) pre-order traversal.  It uses memcopy() to copy nodes in the source
    tree and allocate new child nodes in non-leaf nodes.  The new node is
    exactly the same as the source node except for all the addresses stored in
    it.  It will be faster than traversing all elements in the source tree and
    inserting them one by one into the new tree.  The time complexity of these
    two functions is O(n).
    
    The difference between __mt_dup() and mtree_dup() is that mtree_dup()
    handles locks internally.
    
    Analysis of the average time complexity of this algorithm:
    
    For simplicity, let's assume that the maximum branching factor of all
    non-leaf nodes is 16 (in allocation mode, it is 10), and the tree is a
    full tree.
    
    Under the given conditions, if there is a maple tree with n elements, the
    number of its leaves is n/16.  From bottom to top, the number of nodes in
    each level is 1/16 of the number of nodes in the level below.  So the
    total number of nodes in the entire tree is given by the sum of n/16 +
    n/16^2 + n/16^3 + ...  + 1.  This is a geometric series, and it has log(n)
    terms with base 16.  According to the formula for the sum of a geometric
    series, the sum of this series can be calculated as (n-1)/15.  Each node
    has only one parent node pointer, which can be considered as an edge.  In
    total, there are (n-1)/15-1 edges.
    
    This algorithm consists of two operations:
    
    1. Traversing all nodes in DFS order.
    2. For each node, making a copy and performing necessary modifications
       to create a new node.
    
    For the first part, DFS traversal will visit each edge twice.  Let
    T(ascend) represent the cost of taking one step downwards, and T(descend)
    represent the cost of taking one step upwards.  And both of them are
    constants (although mas_ascend() may not be, as it contains a loop, but
    here we ignore it and treat it as a constant).  So the time spent on the
    first part can be represented as ((n-1)/15-1) * (T(ascend) + T(descend)).
    
    For the second part, each node will be copied, and the cost of copying a
    node is denoted as T(copy_node).  For each non-leaf node, it is necessary
    to reallocate all child nodes, and the cost of this operation is denoted
    as T(dup_alloc).  The behavior behind memory allocation is complex and not
    specific to the maple tree operation.  Here, we assume that the time
    required for a single allocation is constant.  Since the size of a node is
    fixed, both of these symbols are also constants.  We can calculate that
    the time spent on the second part is ((n-1)/15) * T(copy_node) + ((n-1)/15
    - n/16) * T(dup_alloc).
    
    Adding both parts together, the total time spent by the algorithm can be
    represented as:
    
    ((n-1)/15) * (T(ascend) + T(descend) + T(copy_node) + T(dup_alloc)) -
    n/16 * T(dup_alloc) - (T(ascend) + T(descend))
    
    Let C1 = T(ascend) + T(descend) + T(copy_node) + T(dup_alloc)
    Let C2 = T(dup_alloc)
    Let C3 = T(ascend) + T(descend)
    
    Finally, the expression can be simplified as:
    ((16 * C1 - 15 * C2) / (15 * 16)) * n - (C1 / 15 + C3).
    
    This is a linear function, so the average time complexity is O(n).
    
    Link: https://lkml.kernel.org/r/20231027033845.90608-4-zhangpeng.00@bytedance.comSigned-off-by: default avatarPeng Zhang <zhangpeng.00@bytedance.com>
    Suggested-by: default avatarLiam R. Howlett <Liam.Howlett@oracle.com>
    Cc: Christian Brauner <brauner@kernel.org>
    Cc: Jonathan Corbet <corbet@lwn.net>
    Cc: Mateusz Guzik <mjguzik@gmail.com>
    Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
    Cc: Matthew Wilcox <willy@infradead.org>
    Cc: Michael S. Tsirkin <mst@redhat.com>
    Cc: Mike Christie <michael.christie@oracle.com>
    Cc: Nicholas Piggin <npiggin@gmail.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Suren Baghdasaryan <surenb@google.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    fd32e4e9
maple_tree.c 189 KB