Enhancing the Linux Radix Tree MATTHEW WILCOX LINUXCON NORTH - - PowerPoint PPT Presentation

enhancing the
SMART_READER_LITE
LIVE PREVIEW

Enhancing the Linux Radix Tree MATTHEW WILCOX LINUXCON NORTH - - PowerPoint PPT Presentation

Enhancing the Linux Radix Tree MATTHEW WILCOX LINUXCON NORTH AMERICA 2016-08-24 Enhancing the Linux Radix Tree MATTHEW WILCOX LINUXCON NORTH AMERICA 2016-08-24 Overview What is a Radix Tree? What is it used for? Large entries


slide-1
SLIDE 1

Enhancing the Linux Radix Tree

MATTHEW WILCOX LINUXCON NORTH AMERICA 2016-08-24

slide-2
SLIDE 2

Enhancing the Linux Radix Tree

MATTHEW WILCOX LINUXCON NORTH AMERICA 2016-08-24

slide-3
SLIDE 3

Overview

 What is a Radix Tree?  What is it used for?  Large entries in the Radix Tree  Radix Tree Test Suite  Other radix trees  Radix Tree Memory Consumption  RCU and the Radix Tree

slide-4
SLIDE 4

What is a Radix Tree?

 Wikipedia says Radix Trees are all about strings

 Used for string compression and inverted indices of text documents

 Linux says Radix Trees are all about converting small integers to

pointers

 I think of it as a resizable array of pointers

 The Linux Radix Tree appears to be an independent reinvention of

the Judy Array

slide-5
SLIDE 5

How does it work?

 Each layer of the Radix Tree contains 64 pointers

 The “next” 6 bits of the index determine which pointer to use  If this is the last level, the pointer is a user pointer  If not the last level, the pointer points to the next layer

 Other tree metadata is also stored at each layer:

 Tags, height (shift), reference count, parent pointer, offset in parent

slide-6
SLIDE 6

RCU and the Radix Tree

 With care, some radix tree functions can be used with only

rcu_read_lock protection

 Which (depending on kernel config options) may mean no protection

 Many CPUs may be walking the tree at the same time another CPU

is inserting or deleting an entry from the tree

 The user may get back a stale pointer from the tree walk, but it is

guaranteed to be a pointer which was in the tree for that index at some point

 Radix Tree frees tree nodes using RCU, so any CPU holding the read

lock is guaranteed not to reference freed memory

slide-7
SLIDE 7

Height 2 Radix Tree

User S=0 S=6 Root

Node Node Node Ptr Ptr NULL Node Ptr Node NULL

slide-8
SLIDE 8

How is it different from other trees?

 Tree points to objects

 RB trees embed an rb_node in data structures

 All data at leaves; no data in intermediate nodes  Never needs to be rebalanced

 A tree of height N can contain any index between 0 and 64𝑂-1  If the new index is larger than the current max index, insert new nodes

above the current top node to create a deeper tree

 If deleting an element results in a top node with only one child at offset

0, replace the top node with its only child, creating a shallower tree

slide-9
SLIDE 9

Removing an entry

User S=0 S=6 Root

Node Node Node Ptr Ptr NULL Node Ptr Node Node Ptr NULL

slide-10
SLIDE 10

Removing an entry

User S=0 S=6 Root

Node Node Node Ptr Ptr NULL Node Ptr NULL NULL

slide-11
SLIDE 11

Removing an entry

User S=0 Root

Node Node Ptr Ptr NULL Node Ptr

slide-12
SLIDE 12

What is it used for?

 Most important user is the page cache

 Every time we look up a page in a file, we consult the radix tree to see if

the page is already in the cache

 Also used by dozens of places in the kernel which want a resizable

array

 Drivers, filesystems, interrupt controllers

 More places should use it

 E.g. nvme driver

slide-13
SLIDE 13

Tagged entries in the Radix Tree

 Primary user is the page cache  Pages are tagged as dirty, under writeback, or to be written  Radix tree can be searched for entries with any of the three bits set  Tags are replicated all the way up to the root

 Setting a tag sets it on all parents  Clearing a tag may clear it on a parent if all other entries are also clear

slide-14
SLIDE 14

Large pages in the page cache

 Multiple indices return the same pointer

 E.g. indices 512-1023 all refer to the same huge page

 Support aligned power-of-two size entries

 No need for entries which are not a power of two in size  No need for entries which are not aligned to a multiple of their size

 Coalesce multiple small entries into a large entry  Split a large entry into multiple small entries

slide-15
SLIDE 15

Three solutions

1.

Insert 512 4kB entries for each 2MB page

2.

Search the tree once for 2MB pages, then again for 4kB pages

3.

Modify the radix tree to support entries with an order > 0

slide-16
SLIDE 16

Multi-order support

 Mark entries as being user pointers or internal nodes

 Concept already existed, just needed to be broadened

 If the fan-out of the radix tree happens to match the order of the

entry, simply insert the entry at the right place in the tree

 Otherwise need to refer from sibling slots to canonical slot  Need to ensure tags are set/cleared only on canonical slot

slide-17
SLIDE 17

Large entry

User S=0 S=6 S=12 Root Node Node Node Node Page Node Page Page Node Page Sblg Sblg Sblg

slide-18
SLIDE 18

Splitting a large page

User S=0 S=6 S=12 Root

Node Node Node Node Page Node Page Page Node Node Node Retry Retry Node Retry Retry Node Node Retry Retry Node Retry Retry

slide-19
SLIDE 19

Radix Tree Test Suite

 Originally written by Nick Piggin (we believe)  Curated by Andrew Morton out of tree for many years  Merged into Linux 4.6  Many tests added since  More tests needed

slide-20
SLIDE 20

Other radix trees in the Linux kernel

 assoc_array

 Maps large binary blobs to pointers

 e.g. NFS file handles

 Has a neat trick to handle very sparse areas which we should steal

 IDR

 Less efficient implementation of the radix tree

slide-21
SLIDE 21

What’s wrong with the IDR?

 Two implementations of same data structure is bad  No test suite that can be easily found  IDR root larger than Radix Tree root  Uses 256 pointers per level instead of 64

 Wastes memory on trees of almost all sizes

 Interface can be re-implemented on radix tree core, saving over a

kilobyte of code

slide-22
SLIDE 22

Radix Tree Memory Consumption

 Fundamental unit of memory consumption in Linux is the page

 SLAB allocator used for allocations smaller than a page

 On 64-bit x86, with 64 pointers per node, we can allocate 7 nodes

per page

 64 pointers × 8 bytes per pointer = 512 bytes  Plus ~64 bytes of overhead per node, need a 576 byte allocation

 With 128 pointers per node, we allocate 3 nodes per page  With 256 pointers per node, we allocate 3 nodes per two pages

slide-23
SLIDE 23

IDR API

 Alloc (find an empty slot)  Alloc_Cyclic  For_Each  Destroy  Preload  Get_Next  Replace  Remove  Init  Is_Empty

slide-24
SLIDE 24

Re-implementing the IDR

 Tag mechanism repurposed to track empty entries  Alloc_Cyclic is two calls to Alloc  Radix Tree iteration interface implements For_Each interface  Destroy implemented by freeing each entry

slide-25
SLIDE 25

Microsoft ❤ Linux

slide-26
SLIDE 26

Preloading

 Some Radix Tree users cannot sleep when they want to insert an

entry

 The Radix Tree keeps a per-CPU list of pre-allocated nodes  The IDR keeps a per-tree list of pre-allocated nodes