Upgrade to Pro — share decks privately, control downloads, hide ads and more …

CONCURRENCY PATTERNS IN RUBYMOTION

.mateus
March 30, 2013

CONCURRENCY PATTERNS IN RUBYMOTION

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

.mateus

March 30, 2013
Tweet

More Decks by .mateus

Other Decks in Technology

Transcript

  1. #inspect Mateus Armando MacRuby enthusiastic Rubymotion early adopter Mobile OS

    Obsessed Deutsche Telekom AG Who Am I? 2 Samstag, 30. März 13
  2. #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
  3. #inspect GCD-How does it work Task Task Task Task Thread

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

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

    Thread Thread 13 Samstag, 30. März 13
  6. #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
  7. #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
  8. #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
  9. #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
  10. #inspect @queue.sync do Race Conditions if has_due == true pay_my_dues()

    has_due = false end end 17 Samstag, 30. März 13
  11. #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
  12. #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
  13. #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
  14. #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
  15. #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
  16. #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
  17. #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
  18. #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
  19. #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
  20. #inspect NSOperationQueue queue.addOperationWithBlock(->{ // ... do your long task })

    queue = NSOperationQueue.alloc.init queue.name = “com.company.app.task” 27 Samstag, 30. März 13
  21. #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
  22. #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
  23. #inspect Embrace Immutability NSString => String # => NSString.stringWithString("") NSArray

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

    => Array # => NSArray.arrayWithArray([]) NSDictionary => Hash # => NSDictionary.dictionaryWithDictionary({}) 29 Samstag, 30. März 13
  25. #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
  26. #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
  27. #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
  28. #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
  29. #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
  30. #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
  31. #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
  32. #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
  33. #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
  34. #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