CONCURRENCY PATTERNS IN RUBYMOTION

6641139fefa2b21b452b284de32a3806?s=47 .mateus
March 30, 2013

CONCURRENCY PATTERNS IN RUBYMOTION

my #inspect2013 Talk on iOS Concurrency patterns
using Grand Central Dispatch and/or NSOperationQueue

6641139fefa2b21b452b284de32a3806?s=128

.mateus

March 30, 2013
Tweet

Transcript

  1. CONCURRENCY PATTERNS IN RUBYMOTION use the multicore Luke! 1 Samstag,

    30. März 13
  2. #inspect Mateus Armando MacRuby enthusiastic Rubymotion early adopter Mobile OS

    Obsessed Deutsche Telekom AG Who Am I? 2 Samstag, 30. März 13
  3. #inspect 3 Samstag, 30. März 13

  4. #inspect iOS CONCURRENCY NSOperationQueue Grand Central Dispatch (GCD) 4 Samstag,

    30. März 13
  5. #inspect y u no thread?... 5 Samstag, 30. März 13

  6. #inspect y u no thread?... 5 Samstag, 30. März 13

  7. #inspect Deadlocks 6 Samstag, 30. März 13

  8. #inspect Race Conditions if has_due == true pay_my_dues() has_due =

    false end 7 Samstag, 30. März 13
  9. #inspect Race Conditions if has_due == true pay_my_dues() has_due =

    false end 7 Samstag, 30. März 13
  10. #inspect Race Conditions if has_due == true pay_my_dues() has_due =

    false end 7 Samstag, 30. März 13
  11. #inspect Race Conditions if has_due == true pay_my_dues() has_due =

    false end 7 Samstag, 30. März 13
  12. #inspect Race Conditions if has_due == true pay_my_dues() has_due =

    false end 7 Samstag, 30. März 13
  13. #inspect Terminology Parallelism: making programs run faster by using more

    hardware like multiple CPU or GPU cores Concurrency: ways of structuring programs into independent activities that can communicate and synchronise with each other Parallelism ≠ Concurrency 8 Samstag, 30. März 13
  14. #inspect Design Approaches for Concurrent Systems 9 Samstag, 30. März

    13
  15. #inspect Shared Mutability Isolated Mutability Pure Immutability 10 Samstag, 30.

    März 13
  16. #inspect Grand Central Dispatch 11 Samstag, 30. März 13

  17. #inspect Dispatch::Queue lambda {...} lambda {...} lambda {...} lambda {...}

    12 Samstag, 30. März 13
  18. #inspect GCD-How does it work 13 Samstag, 30. März 13

  19. #inspect GCD-How does it work Task Thread 13 Samstag, 30.

    März 13
  20. #inspect GCD-How does it work Task Task Thread 13 Samstag,

    30. März 13
  21. #inspect GCD-How does it work Task Task Task Thread Thread

    13 Samstag, 30. März 13
  22. #inspect GCD-How does it work Task Task Task Task Thread

    Thread Thread 13 Samstag, 30. März 13
  23. #inspect GCD-How does it work Task Task Task Task Thread

    Thread Thread 13 Samstag, 30. März 13
  24. #inspect GCD-How does it work Task Task Task Task Thread

    Thread Thread 13 Samstag, 30. März 13
  25. #inspect Queue Task Task Task Task Execute tasks one at

    a time First-in, First-out (FIFO) order very lightweight (~160 bytes) can replace lock and mutexes Serial Queues 14 Samstag, 30. März 13
  26. #inspect Queue Task Task Task Task Execute tasks one at

    a time First-in, First-out (FIFO) order very lightweight (~160 bytes) can replace lock and mutexes Serial Queues 14 Samstag, 30. März 13
  27. #inspect Queue Task Task Task Task Execute tasks one at

    a time First-in, First-out (FIFO) order very lightweight (~160 bytes) can replace lock and mutexes Serial Queues 14 Samstag, 30. März 13
  28. #inspect Serial Queues queue = Dispatch::Queue.new(“org.comp.app.task”) 15 Samstag, 30. März

    13
  29. #inspect Serial Queues queue = Dispatch::Queue.new(“org.comp.app.task”) def status=(new_status) @queue.sync {

    @status = new_status } end def status @queue.sync { return @status } end 16 Samstag, 30. März 13
  30. #inspect @queue.sync do Race Conditions if has_due == true pay_my_dues()

    has_due = false end end 17 Samstag, 30. März 13
  31. #inspect Queue Concurrent Queues Task Task Task Task ๏ may

    execute tasks simultaneously ๏ no guarantee for the execution order ๏ magic! 18 Samstag, 30. März 13
  32. #inspect Queue Concurrent Queues Task Task Task Task ๏ may

    execute tasks simultaneously ๏ no guarantee for the execution order ๏ magic! 18 Samstag, 30. März 13
  33. #inspect Queue Concurrent Queues Task Task Task Task ๏ may

    execute tasks simultaneously ๏ no guarantee for the execution order ๏ magic! 18 Samstag, 30. März 13
  34. #inspect Concurrent Queues 19 Samstag, 30. März 13

  35. #inspect queue = Dispatch::Queue.concurrent(:background) Concurrent Queues 19 Samstag, 30. März

    13
  36. #inspect queue = Dispatch::Queue.concurrent(:background) queue = Dispatch::Queue.concurrent(:low) Concurrent Queues 19

    Samstag, 30. März 13
  37. #inspect queue = Dispatch::Queue.concurrent(:background) queue = Dispatch::Queue.concurrent(:low) queue = Dispatch::Queue.concurrent(:default)

    Concurrent Queues 19 Samstag, 30. März 13
  38. #inspect queue = Dispatch::Queue.concurrent(:background) queue = Dispatch::Queue.concurrent(:low) queue = Dispatch::Queue.concurrent(:default)

    queue = Dispatch::Queue.concurrent(:high) Concurrent Queues 19 Samstag, 30. März 13
  39. #inspect queue = Dispatch::Queue.concurrent(:background) queue = Dispatch::Queue.concurrent(:low) queue = Dispatch::Queue.concurrent(:default)

    queue = Dispatch::Queue.concurrent(:high) Concurrent Queues 19 Samstag, 30. März 13
  40. #inspect queue = Dispatch::Queue.concurrent(:background) queue = Dispatch::Queue.concurrent(:low) queue = Dispatch::Queue.concurrent(:default)

    queue = Dispatch::Queue.concurrent(:high) Concurrent Queues 19 Samstag, 30. März 13
  41. #inspect queue = Dispatch::Queue.concurrent(“org.task”) queue = Dispatch::Queue.concurrent(:background) queue = Dispatch::Queue.concurrent(:low)

    queue = Dispatch::Queue.concurrent(:default) queue = Dispatch::Queue.concurrent(:high) Concurrent Queues 19 Samstag, 30. März 13
  42. #inspect Concurrent Queues queue = Dispatch::Queue.concurrent('de.mateus.example') queue.async do puts "Hi

    There!" end queue.async do puts "Good Bye" end 20 Samstag, 30. März 13
  43. #inspect Concurrent Queues 20 Samstag, 30. März 13

  44. #inspect Synchronization Barriers Dispatch::Group 21 Samstag, 30. März 13

  45. #inspect Barriers queue = Dispatch::Queue.concurrent('de.mateus.example') queue.async do puts "Hi There!"

    end queue.barrier_async do puts "Good Bye" end 22 Samstag, 30. März 13
  46. #inspect Dispatch::Groups queue = Dispatch::Queue.concurrent('de.mateus.example') group = Dispatch::Group.new queue.async(group) do

    time = Time.now puts "Hi There! #{time}" end group.wait queue.async do puts "Good Bye" end 23 Samstag, 30. März 13
  47. #inspect Dispatch.once Upon A Time - Executes a block object

    once and only once in your app lifetime please don’t use it for UITableView cell layout :-) at least in Rubymotion 24 Samstag, 30. März 13
  48. #inspect Dispatch.once Upon A Time - Executes a block object

    once and only once in your app lifetime please don’t use it for UITableView cell layout :-) at least in Rubymotion 24 Samstag, 30. März 13
  49. #inspect NSOperationQueue 25 Samstag, 30. März 13

  50. #inspect NSOperationQueue NSOperation NSOperation NSOperation NSOperation N SO perationQ ueue

    26 Samstag, 30. März 13
  51. #inspect NSOperationQueue queue.addOperationWithBlock(->{ // ... do your long task })

    queue = NSOperationQueue.alloc.init queue.name = “com.company.app.task” 27 Samstag, 30. März 13
  52. #inspect task = NSBlockOperation.blockOperationWithBlock(->{ // ... do your long task

    }) queue.addOperation(task) NSOperationQueue queue = NSOperationQueue.alloc.init queue.name = “com.company.app.task” 27 Samstag, 30. März 13
  53. #inspect NSOperationQueue queue = NSOperationQueue.alloc.init queue.name = “com.company.app.task” task1 =

    NSInvocationOperation.alloc.initWithTarget(self, selector:‘task1:’, object:”obj”) task2 = NSInvocationOperation.alloc.initWithTarget(self, selector:‘task2’, object:nil) queue.addOperations([task1, task2], waitUntilFinished:false) 27 Samstag, 30. März 13
  54. #inspect NSOperation 28 Samstag, 30. März 13

  55. #inspect NSOperation PRIORITIES 28 Samstag, 30. März 13

  56. #inspect NSOperation DEPENDENCIES PRIORITIES 28 Samstag, 30. März 13

  57. #inspect NSOperation DEPENDENCIES KVO PRIORITIES 28 Samstag, 30. März 13

  58. #inspect NSOperation DEPENDENCIES KVO PRIORITIES SUSPEND/RESUME 28 Samstag, 30. März

    13
  59. #inspect Embrace Immutability 29 Samstag, 30. März 13

  60. #inspect Embrace Immutability NSString => String # => NSString.stringWithString("") 29

    Samstag, 30. März 13
  61. #inspect Embrace Immutability NSString => String # => NSString.stringWithString("") NSArray

    => Array # => NSArray.arrayWithArray([]) 29 Samstag, 30. März 13
  62. #inspect Embrace Immutability NSString => String # => NSString.stringWithString("") NSArray

    => Array # => NSArray.arrayWithArray([]) NSDictionary => Hash # => NSDictionary.dictionaryWithDictionary({}) 29 Samstag, 30. März 13
  63. #inspect GCD Gotchas Thread safety Variable Scope Queue INCEPTION 30

    Samstag, 30. März 13
  64. #inspect Don’t be clever! 31 Samstag, 30. März 13

  65. #inspect •Don't be afraid spawn Queues •Update UI only in

    the Main Queue •Dispatch::Queue.main is your Friend Working with Graphics It's A trap! 32 Samstag, 30. März 13
  66. #inspect What should I use? 33 Samstag, 30. März 13

  67. #inspect GCD NSOperation Work Unit Block NSOperation Can cancel? No

    Yes Dependencies? No Yes Concurrent execution? Yes Yes Change Queue? No Yes NSOperationQueue vs GCD 34 Samstag, 30. März 13
  68. #inspect much more!!! you can get so much more from

    GCD. e.g: you can replace your NSTimer with Dispatch::Source 35 Samstag, 30. März 13
  69. #inspect much more!!! Dispatch::Semaphore you can get so much more

    from GCD. e.g: you can replace your NSTimer with Dispatch::Source 35 Samstag, 30. März 13
  70. #inspect much more!!! Dispatch::Semaphore Dispatch::Source you can get so much

    more from GCD. e.g: you can replace your NSTimer with Dispatch::Source 35 Samstag, 30. März 13
  71. #inspect Create your own Abstraction 36 Samstag, 30. März 13

  72. #inspect def fibonacci2(n) return n if n < 2 fib1

    = fibonacci(n-1) fib2 = fibonacci(n-2) fib1 + fib2 end def fibonacci(n) return n if n < 2 fib1 = Dispatch::Promise.new { fibonacci(n-1) } fib2 = Dispatch::Promise.new { fibonacci(n-2) } fib1 + fib2 end n = 100 Benchmark.bm do |x| x.report("Parallel") { n.times do ; fibonacci(10); end } x.report("Sequential") { n.times do ; fibonacci2(10);end } end 37 Samstag, 30. März 13
  73. #inspect n 0 5 100 200 300 400 500 Parallel

    Sequential 0,000000 0,159890 3,394287 8,568163 15,042915 29,275532 40,513081 0,000000 0,123077 4,513412 18,685437 40,315345 96,669930 174,162173 0 50 100 150 200 0 5 100 200 300 400 500 Naïve Fibonacci sequence Parallel Sequential 37 Samstag, 30. März 13
  74. #inspect Question ? 38 Samstag, 30. März 13

  75. #inspect http://seanlilmateus.github.com/ https://github.com/seanlilmateus/futuristic Threading Programming Guide 39 Samstag, 30. März

    13
  76. #inspect Things That Can Be Slow • Memory allocation •

    View creation • Drawing • Questionable algorithms • Questionable data structures • I/O • Blocking on information • Unnecessary work 40 Samstag, 30. März 13
  77. #inspect “We should forget about small efficiencies, say abou...t 97%

    of the time: premature optimization is the root of all evil.” Donald Knuth ... 41 Samstag, 30. März 13
  78. #inspect Queues Dispatch::Queue.new(“com.company.app.task”) Dispatch::Queue.concurrent(“com.company.app”) Dispatch::Queue.concurrent(priority=:high) Dispatch::Queue.main queue#current queue#label queue#sync queue#async

    queue#after queue#apply queue#dispatch_object queue#suspended? queue#suspend! queue#resume! Groups Dispatch::Group.new group#wait group#on_completion [DEPRECATED] group#notify Semaphore Dispatch::Semaphore.new(count=2) semaphore#signal semaphore#wait(time=Dispatch::TIME_NOW) Source Dispatch::Source.new(type, handle, mask, queue) Dispatch::Source.timer(delay, interval, leeway, queue) src#<< source#merge src#data src#mask src#cancel! src#cancelled? Constants Dispatch::TIME_NOW Dispatch::TIME_FOREVER 42 Samstag, 30. März 13