A Journey Through Ruby Concurrency - RubyConf Brazil 2016

111
A Journey Through Ruby Concurrency RubyConf Brasil 2016 @jerrydantonio

Transcript of A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Page 1: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

A Journey Through Ruby Concurrency

RubyConf Brasil 2016@jerrydantonio

Page 2: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 3: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Jerry D’AntonioAkron, Ohio, USASoftware DeveloperTest Double

@jerrydantoniogithub.com/jdantonioconcurrent-ruby.com

Page 4: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 5: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Let’s get started.

Page 6: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

A few weeks ago Koichi Sasada, aka ko1, proposed a new concurrency model for Ruby 3.

Page 7: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

And now everyone is talking about concurrency.Even more than usual.

Including me.Especially me.

Page 8: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Which is good. It’s an important topic, and critical to Ruby’s future.

Page 9: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

But we need to have the right conversations.

Page 10: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

When discussing Ruby concurrency I frequently hear people say wrong things.

Page 11: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 12: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Although well meaning, comments like this can sometimes be unhelpful.

Page 13: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Ruby can’t necessarily do what Erlang does, or what Node does, or what language X does.

Nor should it.

Page 14: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Because Ruby isn’t Erlang or JavaScript or any other language.

Page 15: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Ruby is Ruby

Page 16: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Ruby is designed to solve different problems.

Page 17: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Ruby has a different runtime,different philosophies,

and different characteristics.

Page 18: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 19: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

makes me

Page 20: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Although Ruby can—and should—take inspiration from other languages.

Ruby must embrace Ruby.

Page 21: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

So, with respect to concurrency, what are Ruby’s most important characteristics?

Page 22: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Ruby is…

Shared memory Reference-based Object oriented

Page 23: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Everything in Ruby is an object.

Page 24: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Ruby has no value types, no true primitives.

Page 25: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Even booleans, symbols, and integers are objects.

Page 26: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

As most of you know…

Variables are not values.Variables are references to values.

References point to memory locationson the heap.

Page 27: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 28: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Objects can be modified from within a method by following the reference.

And this behavior exists when we pass variables across thread boundaries.

Page 29: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

So two or more threads can each have references to the same object, located in the

same memory on the heap.

Which means that, in theory, two threads on two processor cores can attempt to

simultaneously modify the same memory.

Page 30: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 31: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Not on MRI, of course, because it only uses one core and it has a global interpreter lock (GIL).

But that’s sort of a problem, too.

Page 32: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Shared memory, reference-based, object oriented languages offer many advantages.

Page 33: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

But they aren’t great for concurrency.

Page 34: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Full parallelism with shared-memory, reference-based languages can be very fast and efficient,

but is also very difficult to get right.

Locking is hard.

Page 35: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Shared memory, reference-based languages:Ruby

PythonC, C++JavaC#Go

Page 36: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Functional languages like Erlang, Clojure, and Haskell are generally considered better for

concurrency.

Page 37: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

But they are very different languages.

Page 38: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

They favor values over references,enforce immutability,

and in some cases offer memory isolation.

Page 39: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Erlang, for example...Has only values, not references.Has only immutable variables.

Has a very small set of value types.And enforces strict memory isolation.

Page 40: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

This is all very good for concurrency.But isn't necessarily all good.

Or necessarily better.

Page 41: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

!=

Page 42: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

=/=

Page 43: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Functional languages like Erlang require different paradigms and patterns, but also pose

different challenges.

Page 44: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Some people like programming in functional languages.

Page 45: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

I’ve worked professionally with functional languages and I’m quite fond of them.

Page 46: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 47: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Ruby cannot have the same concurrency model as most functional languages without becoming

a very different language.

Page 48: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

This is a very critical point.

Page 49: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Ruby simply cannot copy what Erlang, Clojure, or Haskell does without ceasing to be Ruby.

Page 50: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

So what do we do?

And by “we” I mean the Concurrent Ruby team.

Because we’ve been working on this problem for several years.

Page 51: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 52: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

We create concurrency abstractions that...

Encourage proven designs. Provide the strongest possible guarantees.

And embrace the Ruby language.

Page 53: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 54: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

We do three things…

Page 55: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 56: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Concurrent Ruby takes its inspiration from other languages.

Page 57: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

We leverage ideas from Erlang, Clojure, Java, JavaScript, and other languages.

As well as from academic research.

Page 58: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

We don't reinvent the wheel, or try to outsmart the experts.

Page 59: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

We create abstractions which enable Ruby programmers to easily implement those proven

patterns and practices.

Page 60: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

And when programmers follow the guidelines for what we provide, they create safe concurrent

systems.

Page 61: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 62: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Concurrent Ruby provides the strongest possible thread safety guarantees.

Emphasis on the word “possible.”

Page 63: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

We can’t provide stronger guarantees than what the runtime provides.

No concurrency library can.We use the runtime, we don’t replace it.

Page 64: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Unfortunately, Ruby does not have a formal memory model.

Page 65: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

So we do the best we can with what we have.

Page 66: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

What we cannot guarantee is that your code will be thread safe and free from errors.

Page 67: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 68: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

We can only guarantee that if you follow the guidelines and use our tools the way they were

intended that you'll probably be OK.

Page 69: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Which is the only guarantee any concurrency library can give you.

Page 70: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 71: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 72: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Even though we take inspiration from other languages, we don't directly copy them.

Page 73: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Instead, we interpret them in a uniquely Ruby way.

Page 74: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

optimized for programmer

Page 75: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

optimized for Rubyist

Page 76: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

And I think we do a pretty good job.

Page 77: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 78: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

A concurrency model called “guilds” was recently proposed.

Page 79: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

The core ideas are well-formed and will likely be the basis for concurrency in the next major

version of Ruby.

Page 80: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Not surprisingly, it does pretty much everything we've talked about so far.

But it does it in the language itself.

Page 81: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Quite simply, guilds...

Encourage proven designs.Provide the strongest possible guarantees.

Embrace the Ruby language.

Page 82: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

* Image totally stolen from ko1’s presentation.Thank you!

Page 83: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Like Erlang, guilds are isolated from one another.

Guilds cannot access references which are members of other guilds.

Page 84: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Guilds communicate exclusively through channels.

Channels are one-way, and each guild has one implicit channel.

References are passed between guilds through a channel.

Page 85: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

References can be passed two ways: deep copy or membership transfer.

Page 86: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Deep copy is similar to what functional languages do.

Deep copy can be expensive, and with complex objects can lead to odd situations.

Page 87: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

When we transfer membership the object reference is invalidated in the sending guild.

The object now belongs solely and fully to the receiving guild.

Page 88: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 89: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Nothing changes. We’ll just get harder, better, faster, stronger.

Page 90: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Guilds are a language-level concurrency model,not a high level abstraction.

Page 91: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Guilds provide a thread-safe, one-way communication mechanism between isolated

threads of execution.

That’s it.

Page 92: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

This is very important. Critically important. But it’s not enough for most programmers.

Page 93: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Guilds still require much work to be done by the application programmer.

Page 94: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Programmers must:Design the interactions between guilds

Handle message receipt, probably in a loop. Setup two-way communication for transferring

results.Handle exceptions

Communicate errors.

Page 95: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

This is why most “concurrent” programming languages provide high-level abstractions in the

standard library.

Page 96: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Erlang has gen_server, gen_event, gen_fsm, and supervisor.

Elixir has Agent and Task. Scala has Akka.

And there are many other examples.

Page 97: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 98: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Guilds do not replace concurrency libraries like Concurrent Ruby.

Guilds give us better tools to build these libraries with.

Page 99: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 100: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

You want to build concurrent applications now.

But you also want to be prepared for Ruby 3.

Page 101: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 102: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

“So, Jerry, what do you think about guilds in Ruby 3?”

Page 103: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 104: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Guilds encourage proven concurrency practices.

Page 105: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Guilds provide strong guarantees and a formal memory model.

Page 106: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Guilds allow today’s concurrency libraries, like Concurrent Ruby, to still exist.

Page 107: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

But they give us better tools for simplifying our internals and provide stronger guarantees.

Page 108: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Guilds are heavily influenced by languages that are considered good at concurrency.

Page 109: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

While embracing everything I love about Ruby.

Page 110: A Journey Through Ruby Concurrency - RubyConf Brazil 2016
Page 111: A Journey Through Ruby Concurrency - RubyConf Brazil 2016

Jerry D’AntonioAkron, OH, USA@jerrydantonio