Aleksandar Prokopec Phil Bagwell Martin Odersky École Polytechnique Fédérale de Lausanne Nathan Bronson Stanford Motivation val numbers getNumbers compute square roots numbers ID: 656218
Download Presentation The PPT/PDF document "Concurrent Tries with Efficient Non-bloc..." is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
Concurrent Tries with Efficient Non-blocking Snapshots
Aleksandar ProkopecPhil BagwellMartin OderskyÉcole Polytechnique Fédérale de Lausanne
Nathan Bronson
StanfordSlide2
Motivation
val numbers = getNumbers()// compute square rootsnumbers foreach
{ entry => x = entry.root
n = entry.number entry.root = 0.5 * (x + n / x) if (abs(entry.root - x) < eps) numbers.remove(entry)}Slide3
Hash Array Mapped Tries (HAMT)Slide4
Hash Array Mapped Tries (HAMT)
0 =
00
00002Slide5
Hash Array Mapped Tries (HAMT)
0Slide6
Hash Array Mapped Tries (HAMT)
0
16 =
0100002Slide7
Hash Array Mapped Tries (HAMT)
016Slide8
Hash Array Mapped Tries (HAMT)
016
4 =
0001002Slide9
Hash Array Mapped Tries (HAMT)
16
0
4 = 00
01
00
2Slide10
Hash Array Mapped Tries (HAMT)
16
0
4Slide11
Hash Array Mapped Tries (HAMT)
16
0
4
12 =
00
1100
2Slide12
Hash Array Mapped Tries (HAMT)
16
0
4
12 = 00
11
00
2Slide13
Hash Array Mapped Tries (HAMT)
16
0
412Slide14
Hash Array Mapped Tries (HAMT)
16
33
0412Slide15
Hash Array Mapped Tries (HAMT)
16
33
0412
48Slide16
Hash Array Mapped Tries (HAMT)
16
0
412
48
33
37Slide17
Hash Array Mapped Tries (HAMT)
16
4
12
48
33
37
0
3Slide18
Hash Array Mapped Tries (HAMT)
4
12
16
20
25
33
37
0
1
8
9
3
48
57Slide19
Immutable HAMT
used as immutable maps in functional languages
4
1216
20
25
33
37
0
1
8
9
3Slide20
Immutable HAMT
updates rewrite path from root to leaf
4
1216
20
25
33
37
0
1
8
9
3
4
12
8
9
11
insert(11)Slide21
Immutable HAMT
updates rewrite path from root to leaf
4
1216
20
25
33
37
0
1
8
9
3
4
12
8
9
11
insert(11)
efficient updates -
log
k
(n)Slide22
Node compression
48
57
4857
1
0
1
0
48
57
1
0
1
0
48
57
10
BITPOP(((1 << ((hc >> lev) & 1F)) – 1) & BMP)Slide23
Node compression
48
57
4857
1
0
1
0
48
57
1
0
1
0
48
57
10
48
57Slide24
Ctrie
Can mutable HAMT be modified to bethread-safe?Slide25
Ctrie insert
4
9
1216
20
25
33
37
0
1
3
48
57
17 = 01
00
01
2Slide26
Ctrie insert
4
9
1216
20
25
33
37
0
1
3
48
57
17 = 0100
01
2
16
17
1) allocateSlide27
Ctrie insert
4
9
12
20
25
33
37
0
1
3
48
57
17 = 010001
2
16
17
2) CASSlide28
Ctrie insert
4
9
12
20
25
33
37
0
1
3
48
57
17 = 010001
2
16
17Slide29
Ctrie insert
4
9
1233
37
0
1
3
48
57
18 = 0100
10
2
16
17
20
25Slide30
Ctrie insert
4
9
1233
37
0
1
3
48
57
18 = 0100
10
2
16
17
20
25
1) allocate
16
17
18Slide31
Ctrie insert
4
9
1233
37
0
1
3
48
57
18 = 010010
2
20
25
2) CAS
16
17
18Slide32
Ctrie insert
4
9
1233
37
0
1
3
48
57
18 = 010010
2
20
25
2) CAS
16
17
18
Unless…Slide33
Ctrie insert
4
9
1233
37
0
1
3
48
57
18 = 0100
10
2
16
17
20
25
T1-1) allocate
16
17
18
Unless…
28 = 01
11
00
2
T1
T2Slide34
Ctrie insert
4
9
120
1
3
18 = 0100
10
2
16
17
20
25
T1-1) allocate
16
17
18
Unless…
28 = 01
11
00
2
T1
T2
20
25
28
T2-1) allocateSlide35
Ctrie insert
4
9
120
1
3
18 = 0100
10
2
16
17
20
25
T1-1) allocate
16
17
18
28 = 01
11
00
2
T1
T2
20
25
28
T2-2) CASSlide36
Ctrie insert
4
9
120
1
3
18 = 0100
10
2
16
17
20
25
T1-2) CAS
16
17
18
28 = 01
11
00
2
T1
T2
20
25
28
T2-2) CASSlide37
Ctrie insert
4
9
120
1
3
18 = 0100
10
2
16
17
20
25
16
17
18
28 = 01
11
00
2
T1
T2
20
25
28
Lost insert!Slide38
Ctrie insert –
2nd attempt
4
9120
1
3
16
17
20
25
Solution: I-nodesSlide39
Ctrie insert –
2nd attempt
4
9120
1
3
16
17
20
25
18 = 0100
10
2
28 = 01
11
00
2
T1
T2Slide40
Ctrie insert –
2nd attempt
4
9120
1
3
16
17
T1
T2
20
25
18 = 0100
10
2
28 = 01
11
00
2
16
17
18
20
25
28
T2-1) allocate
T1-1) allocateSlide41
Ctrie insert –
2nd attempt
4
9120
1
3
16
17
T1
T2
20
25
16
17
18
20
25
28
T2-2) CAS
T1-2) CASSlide42
Ctrie insert –
2nd attempt
4
9120
1
3
16
17
18
20
25
28Slide43
Ctrie insert –
2nd attempt
4
9120
1
3
16
17
18
20
25
28
Idea: once added to the
Ctrie
, I-nodes remain present.Slide44
Ctrie insert –
2nd attempt
4
9120
1
3
16
17
18
20
25
28
Remove operation supported as well - details in the paper.Slide45
Ctrie size
4
9
1201
3
16
17
18
20
25
28Slide46
Ctrie size
4
9
1201
3
16
17
18
20
25
28
size = 0Slide47
Ctrie size
4
9
1201
3
16
17
18
20
25
28
size = 0Slide48
Ctrie size
4
9
1201
3
16
17
18
20
25
28
size = 0Slide49
Ctrie size
4
9
1201
3
16
17
18
20
25
28
size = 0Slide50
Ctrie size
4
9
1201
3
16
17
18
20
25
28
size = 1Slide51
Ctrie size
4
9
1201
3
16
17
18
20
25
28
size = 2Slide52
Ctrie size
4
9
1201
3
16
17
18
20
25
28
size = 3Slide53
Ctrie size
4
9
1201
3
16
17
18
20
25
28
size = 5Slide54
Ctrie size
4
9
1201
3
16
17
18
20
25
28
size = 5
actual size = 12Slide55
Ctrie size
4
9
1201
3
16
17
18
20
25
28
size = 5
0
1
actual size = 12Slide56
Ctrie size
4
9
1201
3
16
17
18
20
25
28
size = 5
0
1
CAS
actual size = 11Slide57
Ctrie size
4
9
12
16
17
18
20
25
28
size = 5
0
1
actual size = 11Slide58
Ctrie size
4
9
12
16
17
18
20
25
28
size = 6
0
1
actual size = 11Slide59
Ctrie size
4
9
12
16
17
18
20
25
28
size
= 6
0
1
actual size = 11
19Slide60
Ctrie size
4
9
12
16
17
18
20
25
28
size
= 6
0
1
actual size = 11
16
17
18
19Slide61
Ctrie size
4
9
12
16
17
18
20
25
28
size
= 6
0
1
actual size = 12
16
17
18
19
CASSlide62
Ctrie size
4
9
12
20
25
28
size
= 6
0
1
actual size = 12
16
17
18
19Slide63
Ctrie size
4
9
12
20
25
28
size
= 6
0
1
actual size = 12
16
17
18
19Slide64
Ctrie size
4
9
12
20
25
28
size = 7
0
1
actual size = 9
16
17
18
19Slide65
Ctrie size
4
9
12
20
25
28
size = 8
0
1
actual size = 12
16
17
18
19Slide66
Ctrie size
4
9
12
20
25
28
size = 9
0
1
actual size = 12
16
17
18
19Slide67
Ctrie size
4
9
12
20
25
28
size = 10
0
1
actual size = 12
16
17
18
19Slide68
Ctrie size
4
9
12
20
25
28
size = 11
0
1
actual size = 12
16
17
18
19Slide69
Ctrie size
4
9
12
20
25
28
size = 12
0
1
actual size = 12
16
17
18
19Slide70
Ctrie size
4
9
12
20
25
28
size = 13
0
1
actual size = 12
16
17
18
19Slide71
Ctrie size
4
9
12
20
25
28
size = 13
0
1
actual size = 12
16
17
18
19
But the size
was never 13!Slide72
Global state information
4
9
12
20
25
28
0
1
16
17
18
19
size
find
filter
iteratorSlide73
Global state information
4
9
12
20
25
28
0
1
16
17
18
19
size
find
filter
iterator
snapshotSlide74
Snapshot using locks
4
9
12
20
25
28
0
1
16
17
18
19Slide75
Snapshot using locks
4
9
12
20
25
28
0
1
16
17
18
19
copy expensiveSlide76
Snapshot using locks
4
9
12
20
25
28
0
1
16
17
18
19
copy expensive
not lock-freeSlide77
Snapshot using locks
4
9
12
20
25
28
0
1
16
17
18
19
copy expensive
not lock-free
can insert or remove remain lock-free?
0
1
2
CASSlide78
Snapshot using locks
4
9
12
20
25
28
0
1
16
17
18
19
copy expensive
not lock-free
can insert or remove remain lock-free?
0
1
2
CASSlide79
Snapshot using logs
4
9
12
20
25
28
0
1
16
17
18
19
keep a linked list of previous values in each I-nodeSlide80
Snapshot using logs
4
9
12
20
25
28
0
1
16
17
18
19
0
1
2
keep a linked list of previous values in each I-nodeSlide81
Snapshot using logs
4
9
12
20
25
28
0
1
16
17
18
19
keep a linked list of previous values in each I-node
when is it safe to delete old entries?
0
1
2Slide82
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
rootSlide83
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
rootSlide84
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
snapshot!
rootSlide85
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
snapshot!
#2
root
1) create new I-node at #2Slide86
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
snapshot!
#2
root
2) set snapshot
snapshot #1Slide87
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
snapshot!
#2
root
3) CAS root to new I-node
snapshot #1Slide88
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
subsequent insert
#2
root
snapshot #1
2Slide89
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
subsequent insert
#2
root
snapshot #1
2
generation #2 - ok!Slide90
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
subsequent insert
#2
root
snapshot #1
2
generation #1
not ok, too old!Slide91
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
subsequent insert
#2
root
1) create updated node at #2
snapshot #1
2
#2
#2Slide92
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
subsequent insert
#2
root
2) CAS to the updated node
snapshot #1
2
#2
#2Slide93
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
subsequent insert
#2
root
snapshot #1
2
#2
#2
#1 too old!Slide94
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
subsequent insert
#2
root
snapshot #1
2
#2
#2
4
9
12
#2
1) create updated node at #2Slide95
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
subsequent insert
#2
root
snapshot #1
2
#2
#2
4
9
12
#2
2) CASSlide96
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
subsequent insert
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
finally, create a new leaf
and CASSlide97
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
another insert
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
3Slide98
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
another insert
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
0
1
2
3Slide99
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
But... this won't really work... why?
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
0
1
2
3Slide100
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
0
1
2
3
T2: remove 19
16
17
18Slide101
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
0
1
2
3
T2: remove 19
16
17
18
CASSlide102
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
0
1
2
3
T2: remove 19
16
17
18
CAS
How to fail this last CAS? Slide103
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
0
1
2
3
T2: remove 19
16
17
18
DCAS
How to fail this last CAS?
DCAS Slide104
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
0
1
2
3
T2: remove 19
16
17
18
How to fail this last CAS?
DCAS - software based
DCASSlide105
Snapshot using immutability
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
0
1
2
3
T2: remove 19
16
17
18
How to fail this last CAS?
DCAS - software based
...creates intermediate objects
DCASSlide106
GCAS - generation-compare-and-swap
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
3
T2: remove 19
16
17
18
prev
1) set
prev
fieldSlide107
GCAS - generation-compare-and-swap
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
3
T2: remove 19
16
17
18
prev
2) CASSlide108
GCAS - generation-compare-and-swap
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
3
T2: remove 19
16
17
18
prev
3) read root generationSlide109
GCAS - generation-compare-and-swap
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
3
16
17
18
prev
4) if root generation
changed
CAS
prev
to
FailedNode
(
prev
)
FNSlide110
GCAS - generation-compare-and-swap
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
3
16
17
18
prev
4) if root generation
changed
CAS
prev
to
FailedNode
(
prev
)
FNSlide111
GCAS - generation-compare-and-swap
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
3
16
17
18
prev
5) CAS to previous value
FNSlide112
GCAS - generation-compare-and-swap
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
3
16
17
18
prev
4) if root generation
unchanged
CAS
prev
to nullSlide113
GCAS - generation-compare-and-swap
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
3
16
17
18
4) if root generation
unchanged
CAS
prev
to nullSlide114
GCAS - generation-compare-and-swap
4
9
12
20
25
28
0
1
16
17
18
19
#1
#1
#1
#1
#1
#2
root
snapshot #1
#2
#2
4
9
12
#2
0
1
2
3
1) Replace all CAS with GCAS
2) Replace all READ with GCAS_READ
(which checks if
prev
field is null)Slide115
Snapshot-based iterator
def iterator = if (
isSnapshot) new Iterator(root) else snapshot().iterator()Slide116
Snapshot-based size
def size = { val
sz = 0 val it = iterator
while (it.hasNext) sz += 1 sz}Slide117
Snapshot-based size
def size = { val
sz = 0 val it = iterator
while (it.hasNext) sz += 1 sz}Above is O(n).But, by caching size in nodes - amortized O(logkn)!(see source code)Slide118
Snapshot-based atomic clear
def clear() = { val
or = READ(root) val nr = new
INode(new Gen) if (!CAS(root, or, nr)) clear()}(roughly)Slide119
Evaluation - quad core i7Slide120
Evaluation – UltraSPARC T2Slide121
Evaluation – 4x 8-core i7Slide122
Evaluation – snapshotSlide123
Conclusion
snapshots
are
linearizable and lock-freesnapshots take constant timesnapshots are horizontally scalablesnapshots add a non-significant overhead to the algorithm if they aren't usedthe approach may be applicable to tree-based lock-free data-structures in general (intuition)Slide124
Thank you!