On Deny Capabilities for Safe, Fast Actors

On Deny Capabilities for Safe, Fast Actors

“Deny Capabilities for Safe, Fast Actors (2015)” by Sylvan Clebsch et al. lays out the core novel idea behind the Pony programming language: deny capabilities. Deny capabilities take object capabilities, turn them on their head and then apply them to variable aliases.

In this talk, Sean T. Allen (member of the Pony core team) explains Deny Capabilities and how Pony combines them with an actor-based model – to provide a programming environment that allows for data-race freedom and fearless concurrency.

3c53e91d2a6ceb1b7f202d709f638b1b?s=128

Sean T Allen

January 08, 2020
Tweet

Transcript

  1. On Deny Capabilities for Safe, Fast Actors 1/39

  2. Sean T. Allen Member of the Pony core team @SeanTAllen

    www.seantallen.com 2/39
  3. This is a talk about concurrency. 3/39

  4. This is a talk about going fast. 4/39

  5. This talk is about Pony and Deny Capabilities. 5/39

  6. About the paper 6/39

  7. Actor model 7/39

  8. Actor model basics 8/39

  9. Actor model basics Actors communicate with other actors via messaging

    8/39
  10. Actor model basics Actors communicate with other actors via messaging

    Actors process messages 8/39
  11. Actor model basics Actors communicate with other actors via messaging

    Actors process messages Actors "protect resources" 8/39
  12. Safe 9/39

  13. Data race freedom 10/39

  14. Data race Two memory accesses attempts where both: 11/39

  15. Data race Two memory accesses attempts where both: Target the

    same location 11/39
  16. Data race Two memory accesses attempts where both: Target the

    same location Are performed concurrently by two threads 11/39
  17. Data race Two memory accesses attempts where both: Target the

    same location Are performed concurrently by two threads Are not reads 11/39
  18. Data race Two memory accesses attempts where both: Target the

    same location Are performed concurrently by two threads Are not reads Are not synchronization operations 11/39
  19. The actor model can help prevent data races 12/39

  20. The actor model can help prevent data races All variables

    are "protected" by an actor - no global variables 12/39
  21. The actor model can help prevent data races All variables

    are "protected" by an actor - no global variables Actors are processed sequentially 1 message a time by a single thread 12/39
  22. The actor model can help prevent data races All variables

    are "protected" by an actor - no global variables Actors are processed sequentially 1 message a time by a single thread Actors are "synchronization operations" 12/39
  23. The actor model can help prevent data races All variables

    are "protected" by an actor - no global variables Actors are processed sequentially 1 message a time by a single thread But sending data from one actor to another can cause problems... 12/39
  24. Fast 13/39

  25. How to go fast 14/39

  26. How to go fast Avoid coordination 14/39

  27. How to go fast Avoid coordination Avoid contention 14/39

  28. How to go fast Avoid coordination Avoid contention Measure it

    14/39
  29. How actors can help with fast 15/39

  30. How actors can help with fast make coordination explicit 15/39

  31. How actors can help with fast make coordination explicit make

    contention explicit 15/39
  32. How actors can hurt fast 16/39

  33. How actors can hurt fast naive implementations can be very

    slow 16/39
  34. How actors can hurt fast naive implementations can be very

    slow message queues are points of contention 16/39
  35. How actors can hurt fast naive implementations can be very

    slow message queues are points of contention locks are usually faster than a large memory copy 16/39
  36. Deny capabilities for safe, fast actors 17/39

  37. Deny capabilities doing unsafe fast things safely 18/39

  38. Deny capabilities statically con rm you aren't doing something unsafe

    19/39
  39. Alias control 20/39

  40. What is an alias? 21/39

  41. What is an alias? Aliases are "names" for things in

    memory 21/39
  42. What is an alias? Aliases are "names" for things in

    memory Aliases allow you to access a thing at a location 21/39
  43. Aliases in Pony 22/39

  44. Aliases in Pony When you assign a value to a

    variable or a eld. 22/39
  45. Aliases in Pony When you assign a value to a

    variable or a eld. When you pass a value as an argument to a method. 22/39
  46. Aliases in Pony When you assign a value to a

    variable or a eld. When you pass a value as an argument to a method. When you call a method, an alias of the receiver of the call is created. It is accessible as this within the method body. 22/39
  47. Count the aliases primitive Say fun say(msg: String, out: OutStream)

    => let x = "We say '" + msg + "'" out.print(x) 23/39
  48. Count the aliases fun say(msg: String, out: OutStream) => primitive

    Say let x = "We say '" + msg + "'" out.print(x) msg and out are aliases 23/39
  49. Count the aliases let x = "We say '" +

    msg + "'" primitive Say fun say(msg: String, out: OutStream) => out.print(x) x is an alias 23/39
  50. Count the aliases out.print(x) primitive Say fun say(msg: String, out:

    OutStream) => let x = "We say '" + msg + "'" x is aliased when passed to print 23/39
  51. Count the aliases primitive Say fun say(msg: String, out: OutStream)

    => let x = "We say '" + msg + "'" out.print(x) 23/39
  52. Capabilities Annotations on code that can be used to statically

    con rm some property 24/39
  53. actor Main new create(env: Env) => let msg: String val

    = "Hello World!" env.out.print(msg) 25/39
  54. let msg: String val = "Hello World!" actor Main new

    create(env: Env) => env.out.print(msg) val is a capability 25/39
  55. let msg: String val = "Hello World!" actor Main new

    create(env: Env) => env.out.print(msg) val is part of the type at compile-time 25/39
  56. let msg: String val = "Hello World!" actor Main new

    create(env: Env) => env.out.print(msg) val says "the alias msg to the String Hello World is immutable" 25/39
  57. What can you deny? 26/39

  58. What can you deny? Reading 26/39

  59. What can you deny? Reading Mutating 26/39

  60. What can you deny? Reading Mutating Aliasing 26/39

  61. What can you deny? Reading Mutating Aliasing Sending 26/39

  62. What can you deny? Reading Mutating Aliasing Sending Sharing 26/39

  63. Some capabilities 27/39

  64. Some capabilities ref 27/39

  65. Some capabilities ref val 27/39

  66. Some capabilities ref val iso 27/39

  67. Some capabilities ref val iso tag 27/39

  68. ref 28/39

  69. ref allows reading 28/39

  70. ref allows reading allows mutation 28/39

  71. ref allows reading allows mutation denies sending 28/39

  72. ref allows reading allows mutation denies sending allows unlimited aliases

    28/39
  73. ref allows reading allows mutation denies sending allows unlimited aliases

    denies sharing 28/39
  74. iso 29/39

  75. iso allows reading 29/39

  76. iso allows reading allows mutation 29/39

  77. iso allows reading allows mutation allows sending 29/39

  78. iso allows reading allows mutation allows sending denies aliasing 29/39

  79. iso allows reading allows mutation allows sending denies aliasing denies

    sharing 29/39
  80. val 30/39

  81. val allows reading 30/39

  82. val allows reading denies mutation 30/39

  83. val allows reading denies mutation allows sending 30/39

  84. val allows reading denies mutation allows sending allows unlimited aliases

    30/39
  85. val allows reading denies mutation allows sending allows unlimited aliases

    allows sharing 30/39
  86. tag 31/39

  87. tag denies reading 31/39

  88. tag denies reading denies mutation 31/39

  89. tag denies reading denies mutation allows aliasing 31/39

  90. tag denies reading denies mutation allows aliasing allows sharing 31/39

  91. tag denies reading denies mutation allows aliasing allows sharing allows

    sending 31/39
  92. Readable 32/39

  93. Readable ref 32/39

  94. Readable ref iso 32/39

  95. Readable ref iso val 32/39

  96. Readable ref iso val Mutable 32/39

  97. Readable ref iso val Mutable ref 32/39

  98. Readable ref iso val Mutable ref iso 32/39

  99. Readable ref iso val Mutable ref iso Aliasable 32/39

  100. Readable ref iso val Mutable ref iso Aliasable ref 32/39

  101. Readable ref iso val Mutable ref iso Aliasable ref val

    32/39
  102. Readable ref iso val Mutable ref iso Aliasable ref val

    tag 32/39
  103. Readable ref iso val Mutable ref iso Aliasable ref val

    tag Sendable 32/39
  104. Readable ref iso val Mutable ref iso Aliasable ref val

    tag Sendable val 32/39
  105. Readable ref iso val Mutable ref iso Aliasable ref val

    tag Sendable val tag 32/39
  106. Readable ref iso val Mutable ref iso Aliasable ref val

    tag Sendable val tag iso 32/39
  107. Readable ref iso val Mutable ref iso Aliasable ref val

    tag Sendable val tag iso Shareable 32/39
  108. Readable ref iso val Mutable ref iso Aliasable ref val

    tag Sendable val tag iso Shareable val 32/39
  109. Readable ref iso val Mutable ref iso Aliasable ref val

    tag Sendable val tag iso Shareable val tag 32/39
  110. There's no platonic ideal for deny capabilities. 33/39

  111. Code (and errors!) 34/39

  112. actor Main new create(env: Env) => let msg: String ref

    = "Hello World!".clone() env.out.print(msg) 35/39
  113. let msg: String ref = "Hello World!".clone() actor Main new

    create(env: Env) => env.out.print(msg) Hello World String is mutable 35/39
  114. env.out.print(msg) actor Main new create(env: Env) => let msg: String

    ref = "Hello World!".clone() send msg to actor out 35/39
  115. let msg: String ref = "Hello World!".clone() actor Main new

    create(env: Env) => env.out.print(msg) ref isn't sendable 35/39
  116. env.out.print(msg) actor Main new create(env: Env) => let msg: String

    ref = "Hello World!".clone() which will result in an error here 35/39
  117. Error: main.pony:4:19: argument not a subtype of parameter env.out.print(msg) ^

    Info: main.pony:4:19: argument type is String ref env.out.print(msg) ^ (...):13:12: parameter type is (String val | Array[U8 val] val) be print(data: ByteSeq) ^ main.pony:3:14: String ref is not a subtype of String val: ref is not a subcap of val let msg: String ref = "Hello World!".clone() ^ main.pony:3:14: String ref is not a subtype of Array[U8 val] val 36/39
  118. main.pony:4:19: argument not a subtype of paramete env.out.print(msg) Error: ^

    Info: main.pony:4:19: argument type is String ref env.out.print(msg) ^ (...):13:12: parameter type is (String val | Array[U8 val] val) be print(data: ByteSeq) ^ main.pony:3:14: String ref is not a subtype of String val: ref is not a subcap of val let msg: String ref = "Hello World!".clone() ^ msg isn't the correct type 36/39
  119. main.pony:4:19: argument type is String ref env.out.print(msg) Error: main.pony:4:19: argument

    not a subtype of parameter env.out.print(msg) ^ Info: ^ (...):13:12: parameter type is (String val | Array[U8 val] val) be print(data: ByteSeq) ^ main.pony:3:14: String ref is not a subtype of String val: ref is not a subcap of val let msg: String ref = "Hello World!".clone() ^ msg is String ref 36/39
  120. (...):13:12: parameter type is (String val | Array[U8 val] val)

    be print(data: ByteSeq) main.pony:4:19: argument not a subtype of parameter env.out.print(msg) ^ Info: main.pony:4:19: argument type is String ref env.out.print(msg) ^ ^ main.pony:3:14: String ref is not a subtype of String val: ref is not a subcap of val let msg: String ref = "Hello World!".clone() ^ main.pony:3:14: String ref is not a subtype of Array[U8 val] val l S i f "H ll W ld!" l () print requires String val or Array[U8] val 36/39
  121. The compiler just statically checked our data sharing. 37/39

  122. The compiler just statically checked our data sharing. Let's x

    it 37/39
  123. actor Main new create(env: Env) => let msg: String val

    = "Hello World!" env.out.print(msg) 38/39
  124. let msg: String val = "Hello World!" actor Main new

    create(env: Env) => env.out.print(msg) Hello World String is immutable 38/39
  125. env.out.print(msg) actor Main new create(env: Env) => let msg: String

    val = "Hello World!" send msg to actor out 38/39
  126. let msg: String val = "Hello World!" actor Main new

    create(env: Env) => env.out.print(msg) val is sendable 38/39
  127. env.out.print(msg) actor Main new create(env: Env) => let msg: String

    val = "Hello World!" no error here 38/39
  128. Learn more https:/ /www.seantallen.com/talks/deny- capabilities/ 39/39