[Script Info] Title: [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: 0,0:00:24.81,0:00:25.86,Default,,0000,0000,0000,,HARY KRISHNAN: So, thank you very much Dialogue: 0,0:00:25.86,0:00:28.10,Default,,0000,0000,0000,,for being here on a Saturday evening, this\Nlate. Dialogue: 0,0:00:28.10,0:00:30.43,Default,,0000,0000,0000,,My talk got pushed to the last, but I Dialogue: 0,0:00:30.43,0:00:34.54,Default,,0000,0000,0000,,appreciate you being here, first. My name's\NHari. I Dialogue: 0,0:00:34.54,0:00:36.91,Default,,0000,0000,0000,,work at MavenHive. So this is a talk about Dialogue: 0,0:00:36.91,0:00:43.53,Default,,0000,0000,0000,,Ruby memory model. So before I start, how\Nmany Dialogue: 0,0:00:43.53,0:00:46.56,Default,,0000,0000,0000,,of you have heard about memory model and know Dialogue: 0,0:00:46.56,0:00:51.91,Default,,0000,0000,0000,,what it is? Show of hands, please. OK. Let's Dialogue: 0,0:00:51.91,0:00:55.15,Default,,0000,0000,0000,,see where this talk goes. So why I did Dialogue: 0,0:00:55.15,0:00:58.84,Default,,0000,0000,0000,,I come up with this talk topic. So I Dialogue: 0,0:00:58.84,0:01:01.81,Default,,0000,0000,0000,,started my career with Java, and I spent a Dialogue: 0,0:01:01.81,0:01:04.86,Default,,0000,0000,0000,,lot many years with Java, and Java has a Dialogue: 0,0:01:04.86,0:01:08.89,Default,,0000,0000,0000,,very clearly documented memory model. And\Nit kind of Dialogue: 0,0:01:08.89,0:01:10.50,Default,,0000,0000,0000,,gets to you because with all that, you don't Dialogue: 0,0:01:10.50,0:01:14.05,Default,,0000,0000,0000,,feel safe enough doing multi-threaded programming\Nat all. So Dialogue: 0,0:01:14.05,0:01:17.71,Default,,0000,0000,0000,,with Ruby, we've always been talking about,\Nyou know, Dialogue: 0,0:01:17.71,0:01:21.29,Default,,0000,0000,0000,,doing multi-process for multi-process parallelism, Dialogue: 0,0:01:21.29,0:01:24.45,Default,,0000,0000,0000,,rather than multi-threaded parallelism, Dialogue: 0,0:01:24.45,0:01:28.71,Default,,0000,0000,0000,,even though the language actually supports,\Nyou know, multi-threading Dialogue: 0,0:01:28.71,0:01:30.80,Default,,0000,0000,0000,,semantics. Of course we know it's called single-threaded\Nand Dialogue: 0,0:01:30.80,0:01:34.26,Default,,0000,0000,0000,,all that, but I just got curious, like, what Dialogue: 0,0:01:34.26,0:01:36.50,Default,,0000,0000,0000,,is the real memory model behind Ruby, and\NI Dialogue: 0,0:01:36.50,0:01:39.15,Default,,0000,0000,0000,,just wanted to figure that out. So this talk Dialogue: 0,0:01:39.15,0:01:42.44,Default,,0000,0000,0000,,is all about my learnings as I went through, Dialogue: 0,0:01:42.44,0:01:46.35,Default,,0000,0000,0000,,like, various literatures, and figured out,\Nand I tried Dialogue: 0,0:01:46.35,0:01:48.29,Default,,0000,0000,0000,,to combine, like, get a gist of the whole Dialogue: 0,0:01:48.29,0:01:50.51,Default,,0000,0000,0000,,thing. And cram it into some twenty minutes\Nso Dialogue: 0,0:01:50.51,0:01:52.34,Default,,0000,0000,0000,,that I could, like, probably give you a very Dialogue: 0,0:01:52.34,0:01:55.60,Default,,0000,0000,0000,,useful session, like, from which you can further\Ndo Dialogue: 0,0:01:55.60,0:02:01.07,Default,,0000,0000,0000,,more digging on this, right. So when I talked Dialogue: 0,0:02:01.07,0:02:03.42,Default,,0000,0000,0000,,to my friends about memory model, the first\Nthing Dialogue: 0,0:02:03.42,0:02:05.54,Default,,0000,0000,0000,,that comes up to their mind is probably this Dialogue: 0,0:02:05.54,0:02:10.14,Default,,0000,0000,0000,,- heap, heap, non-heap, stack, whatever. I'm\Nnot gonna Dialogue: 0,0:02:10.14,0:02:14.07,Default,,0000,0000,0000,,talk about that. I'm not gonna talk about\Nthis Dialogue: 0,0:02:14.07,0:02:17.45,Default,,0000,0000,0000,,either. It's not about, you know, optimizing\Nyour memory, Dialogue: 0,0:02:17.45,0:02:21.04,Default,,0000,0000,0000,,or search memory leeks, or garbage collection.\NThis talk Dialogue: 0,0:02:21.04,0:02:23.33,Default,,0000,0000,0000,,is not about that either. So what the hell Dialogue: 0,0:02:23.33,0:02:27.37,Default,,0000,0000,0000,,am I gonna talk about? First, a quick exercise. Dialogue: 0,0:02:27.37,0:02:31.36,Default,,0000,0000,0000,,So let's start with this and see where it Dialogue: 0,0:02:31.36,0:02:35.76,Default,,0000,0000,0000,,goes. Simple code. Not much to process late\Nin Dialogue: 0,0:02:35.76,0:02:38.89,Default,,0000,0000,0000,,the day. There's a shared variable called\N'n', and Dialogue: 0,0:02:38.89,0:02:42.03,Default,,0000,0000,0000,,there are thousand threads over that, and\Neach of Dialogue: 0,0:02:42.03,0:02:45.38,Default,,0000,0000,0000,,those threads want to increment that shared\Nvariable hundred Dialogue: 0,0:02:45.38,0:02:49.38,Default,,0000,0000,0000,,times, right. And what is the expected output?\NI'm Dialogue: 0,0:02:49.38,0:02:51.20,Default,,0000,0000,0000,,not gonna question you, I'm just gonna give\Nit Dialogue: 0,0:02:51.20,0:02:55.18,Default,,0000,0000,0000,,away. It's 100,000. It's fairly straightforward\Ncode. I'm sure Dialogue: 0,0:02:55.18,0:02:57.20,Default,,0000,0000,0000,,all of you have done this, and it's no Dialogue: 0,0:02:57.20,0:03:01.68,Default,,0000,0000,0000,,big deal. So what's the real output? MRI is Dialogue: 0,0:03:01.68,0:03:05.32,Default,,0000,0000,0000,,very faithful, it gives you what you expected.\N100,000, Dialogue: 0,0:03:05.32,0:03:08.72,Default,,0000,0000,0000,,right. So what happens next? I'm running it\Non Dialogue: 0,0:03:08.72,0:03:12.57,Default,,0000,0000,0000,,Rubinius. This is what you see. And it's always Dialogue: 0,0:03:12.57,0:03:15.76,Default,,0000,0000,0000,,going to be a different number every time\Nyou Dialogue: 0,0:03:15.76,0:03:19.14,Default,,0000,0000,0000,,run it. And that's JRuby. It gives you a Dialogue: 0,0:03:19.14,0:03:22.63,Default,,0000,0000,0000,,lower number. Some of you may be guessing\Nalready, Dialogue: 0,0:03:22.63,0:03:24.49,Default,,0000,0000,0000,,and you probably know it, why it gives you Dialogue: 0,0:03:24.49,0:03:28.16,Default,,0000,0000,0000,,a lower number. So why all this basic stupid Dialogue: 0,0:03:28.16,0:03:31.23,Default,,0000,0000,0000,,code and some stupid counter over here, right?\NSo Dialogue: 0,0:03:31.23,0:03:34.19,Default,,0000,0000,0000,,I just wanted to get a really basic example Dialogue: 0,0:03:34.19,0:03:36.30,Default,,0000,0000,0000,,to explain the concept of increment is not\Na Dialogue: 0,0:03:36.30,0:03:40.04,Default,,0000,0000,0000,,single instruction, right. The reason why\NI'm talking about Dialogue: 0,0:03:40.04,0:03:43.39,Default,,0000,0000,0000,,this is, I love Ruby because the syntax is Dialogue: 0,0:03:43.39,0:03:46.63,Default,,0000,0000,0000,,so terse, and it's so simple, it's so readable, Dialogue: 0,0:03:46.63,0:03:49.31,Default,,0000,0000,0000,,right. But it does not mean every single instruction Dialogue: 0,0:03:49.31,0:03:52.14,Default,,0000,0000,0000,,on the screen is going to be executed straight Dialogue: 0,0:03:52.14,0:03:54.81,Default,,0000,0000,0000,,away, right. So at least, to my junior self, Dialogue: 0,0:03:54.81,0:03:56.60,Default,,0000,0000,0000,,this is the first advice I would give, when Dialogue: 0,0:03:56.60,0:04:00.59,Default,,0000,0000,0000,,I started, you know, multi-threaded programming.\NSo at least Dialogue: 0,0:04:00.59,0:04:05.98,Default,,0000,0000,0000,,three steps. Lowered increments store, right.\NThat's, even further, Dialogue: 0,0:04:05.98,0:04:09.88,Default,,0000,0000,0000,,really simple piece of code like, you know,\Na Dialogue: 0,0:04:09.88,0:04:12.88,Default,,0000,0000,0000,,plus equals to, right. So this is what we Dialogue: 0,0:04:12.88,0:04:15.75,Default,,0000,0000,0000,,really want to happen. You have a count, you Dialogue: 0,0:04:15.75,0:04:18.40,Default,,0000,0000,0000,,lowered it, you increment it, you stored it.\NThen Dialogue: 0,0:04:18.40,0:04:21.02,Default,,0000,0000,0000,,the next thread comes along. It lowers it,\Nincrements Dialogue: 0,0:04:21.02,0:04:23.22,Default,,0000,0000,0000,,it, stores it. You have the next result which Dialogue: 0,0:04:23.22,0:04:25.75,Default,,0000,0000,0000,,is what you expect, right. But we live in Dialogue: 0,0:04:25.75,0:04:28.26,Default,,0000,0000,0000,,a world where threads don't want to be our Dialogue: 0,0:04:28.26,0:04:31.47,Default,,0000,0000,0000,,friend. They do this. One guy comes along,\Nreads Dialogue: 0,0:04:31.47,0:04:33.92,Default,,0000,0000,0000,,it, increments it. The other guy also reads\Nthe Dialogue: 0,0:04:33.92,0:04:37.44,Default,,0000,0000,0000,,older value, increments it. And both of them\Ngo Dialogue: 0,0:04:37.44,0:04:40.02,Default,,0000,0000,0000,,and save the same value, right. So this is Dialogue: 0,0:04:40.02,0:04:42.12,Default,,0000,0000,0000,,a classic case of lost update. I'm sure most Dialogue: 0,0:04:42.12,0:04:44.06,Default,,0000,0000,0000,,of you have seen it in the database world. Dialogue: 0,0:04:44.06,0:04:46.77,Default,,0000,0000,0000,,But this pretty much happens a lot in the Dialogue: 0,0:04:46.77,0:04:48.86,Default,,0000,0000,0000,,multi-threading world, right. But why did\Nit not happen Dialogue: 0,0:04:48.86,0:04:51.62,Default,,0000,0000,0000,,with MRI? And what did you see the right Dialogue: 0,0:04:51.62,0:04:53.19,Default,,0000,0000,0000,,result?? [00:04:52]? That, I'm sure a lot\Nof you Dialogue: 0,0:04:53.19,0:04:55.58,Default,,0000,0000,0000,,know, but let's step, let's part that question\Nand Dialogue: 0,0:04:55.58,0:05:00.50,Default,,0000,0000,0000,,just move a little ahead. So, as you observed Dialogue: 0,0:05:00.50,0:05:03.77,Default,,0000,0000,0000,,earlier, a lot of reordoring happening in\Ninstructions, right. Dialogue: 0,0:05:03.77,0:05:07.21,Default,,0000,0000,0000,,Like, the threads were context-switching,\Nand they were reordering Dialogue: 0,0:05:07.21,0:05:11.14,Default,,0000,0000,0000,,statements. So where does this reordering\Nhappen? Reordering can Dialogue: 0,0:05:11.14,0:05:14.74,Default,,0000,0000,0000,,happen at multiple levels. So start from the\Ntop. Dialogue: 0,0:05:14.74,0:05:18.15,Default,,0000,0000,0000,,You have the compiler, which can do simple\Noptimizations Dialogue: 0,0:05:18.15,0:05:20.78,Default,,0000,0000,0000,,like look closer?? [00:05:20]. Even that can\Nchange the Dialogue: 0,0:05:20.78,0:05:23.99,Default,,0000,0000,0000,,order of your statements in your code, right.\NNext, Dialogue: 0,0:05:23.99,0:05:27.68,Default,,0000,0000,0000,,when the code gets translated to, you know,\Nmachine-level Dialogue: 0,0:05:27.68,0:05:30.64,Default,,0000,0000,0000,,language, goes to core, and your CP cores\Nare Dialogue: 0,0:05:30.64,0:05:34.43,Default,,0000,0000,0000,,at liberty, again, to reorder them for performance.\NAnd Dialogue: 0,0:05:34.43,0:05:37.02,Default,,0000,0000,0000,,next comes the memory system, right. The memory\Nsystem Dialogue: 0,0:05:37.02,0:05:39.67,Default,,0000,0000,0000,,is like the combined global memory, which\Nall the Dialogue: 0,0:05:39.67,0:05:42.49,Default,,0000,0000,0000,,CPUs can read, and also they're individual\Ncaches. But Dialogue: 0,0:05:42.49,0:05:45.84,Default,,0000,0000,0000,,why do CPUs have caches? They want to, memory Dialogue: 0,0:05:45.84,0:05:47.71,Default,,0000,0000,0000,,is slow, so they want to load, reload all Dialogue: 0,0:05:47.71,0:05:50.08,Default,,0000,0000,0000,,the values, refactor it, keep it in the cache, Dialogue: 0,0:05:50.08,0:05:52.71,Default,,0000,0000,0000,,again improve performance. So even the memory\Nsystem can Dialogue: 0,0:05:52.71,0:05:55.94,Default,,0000,0000,0000,,conspire against you and reorder the loads\Nand stores Dialogue: 0,0:05:55.94,0:05:59.38,Default,,0000,0000,0000,,after the memory registers. And that can cause\Nreordering, Dialogue: 0,0:05:59.38,0:06:03.32,Default,,0000,0000,0000,,right. So this is really, really crazy. Like,\NI'm Dialogue: 0,0:06:03.32,0:06:07.55,Default,,0000,0000,0000,,a very stupid programmer, who works at the\Nprogramming Dialogue: 0,0:06:07.55,0:06:10.60,Default,,0000,0000,0000,,language level. I don't really understand\Nthe structure of Dialogue: 0,0:06:10.60,0:06:13.17,Default,,0000,0000,0000,,the hardware and things like that. So how\Ndo Dialogue: 0,0:06:13.17,0:06:15.55,Default,,0000,0000,0000,,I keep myself abstracted from all this, you\Nknow, Dialogue: 0,0:06:15.55,0:06:21.55,Default,,0000,0000,0000,,really crazy stuff? So that's essentially\Na memory model. Dialogue: 0,0:06:21.55,0:06:23.93,Default,,0000,0000,0000,,So what, what is a memory model? A memory Dialogue: 0,0:06:23.93,0:06:27.18,Default,,0000,0000,0000,,model describes the interactions of threads\Nthrough memory and Dialogue: 0,0:06:27.18,0:06:28.97,Default,,0000,0000,0000,,their shared use of data. So this is straight Dialogue: 0,0:06:28.97,0:06:30.92,Default,,0000,0000,0000,,out of Wikipedia, right. So if you just read Dialogue: 0,0:06:30.92,0:06:34.61,Default,,0000,0000,0000,,it first, either you're gonna think it's really\Nsimple, Dialogue: 0,0:06:34.61,0:06:38.07,Default,,0000,0000,0000,,and probably even looks stupid, but otherwise\Nyou might Dialogue: 0,0:06:38.07,0:06:40.79,Default,,0000,0000,0000,,not even understand. So I was the second category. Dialogue: 0,0:06:40.79,0:06:43.88,Default,,0000,0000,0000,,So what does this all mean? So when there Dialogue: 0,0:06:43.88,0:06:48.58,Default,,0000,0000,0000,,are so many complications with the reordering,\Nthe reads Dialogue: 0,0:06:48.58,0:06:51.13,Default,,0000,0000,0000,,and writes of memory and things like that,\Nas Dialogue: 0,0:06:51.13,0:06:54.76,Default,,0000,0000,0000,,a programmer you need certain guarantees from\Nthe programming Dialogue: 0,0:06:54.76,0:06:56.84,Default,,0000,0000,0000,,language, and the virtual machine you're working\Non top Dialogue: 0,0:06:56.84,0:07:01.04,Default,,0000,0000,0000,,of, to say this is how multi-threaded shared,\NI Dialogue: 0,0:07:01.04,0:07:03.98,Default,,0000,0000,0000,,mean, multi-threaded access to shared memory\Nis going to Dialogue: 0,0:07:03.98,0:07:05.94,Default,,0000,0000,0000,,work. These are the basic guarantees and these\Nare Dialogue: 0,0:07:05.94,0:07:09.31,Default,,0000,0000,0000,,the simple rules of how the system works.\NSo Dialogue: 0,0:07:09.31,0:07:13.16,Default,,0000,0000,0000,,you can reliably work code against that, right.\NSo Dialogue: 0,0:07:13.16,0:07:15.14,Default,,0000,0000,0000,,in, in effect, a memory model is just a Dialogue: 0,0:07:15.14,0:07:21.48,Default,,0000,0000,0000,,specification. Any Java programmers here,\Nin the house? Great. Dialogue: 0,0:07:21.48,0:07:25.86,Default,,0000,0000,0000,,So how many of you know about JSR 133? Dialogue: 0,0:07:25.86,0:07:31.27,Default,,0000,0000,0000,,The memory model, double check locking - OK.\NSome Dialogue: 0,0:07:31.27,0:07:37.28,Default,,0000,0000,0000,,people. Single term issue? OK - some more\Nhands. Dialogue: 0,0:07:37.28,0:07:39.62,Default,,0000,0000,0000,,So Java was the first programming language\Nwhich came Dialogue: 0,0:07:39.62,0:07:43.36,Default,,0000,0000,0000,,up with a concept called memory model, right.\NBecause, Dialogue: 0,0:07:43.36,0:07:45.61,Default,,0000,0000,0000,,the first thing is, right ones?? [00:07:45]\Nwon't run Dialogue: 0,0:07:45.61,0:07:48.11,Default,,0000,0000,0000,,anywhere. It had to be predictable across\Nplatforms, across Dialogue: 0,0:07:48.11,0:07:51.74,Default,,0000,0000,0000,,reimplementations, and things like that. So\Nthe, there had Dialogue: 0,0:07:51.74,0:07:54.65,Default,,0000,0000,0000,,to be a JSR which specified what is the Dialogue: 0,0:07:54.65,0:07:56.86,Default,,0000,0000,0000,,memory model that it can code against so that Dialogue: 0,0:07:56.86,0:08:02.13,Default,,0000,0000,0000,,your multi-threaded code works predictably,\Nand deterministically across platforms Dialogue: 0,0:08:02.13,0:08:08.52,Default,,0000,0000,0000,,and across virtual machines. Right? So essentially\Nthat's where Dialogue: 0,0:08:08.52,0:08:11.28,Default,,0000,0000,0000,,my, you know, whole thing started. I had gone Dialogue: 0,0:08:11.28,0:08:14.51,Default,,0000,0000,0000,,through the Java memory model, and was pretty\Nmuch Dialogue: 0,0:08:14.51,0:08:16.96,Default,,0000,0000,0000,,really happy that someone had taken the pain\Nto Dialogue: 0,0:08:16.96,0:08:18.59,Default,,0000,0000,0000,,write it down in clear terms so that you Dialogue: 0,0:08:18.59,0:08:25.59,Default,,0000,0000,0000,,don't have to worry about multi-threading.\NHold on, sorry. Dialogue: 0,0:08:28.02,0:08:34.67,Default,,0000,0000,0000,,Sorry about that. Cool. So. Memory model gives\Nyou Dialogue: 0,0:08:34.67,0:08:40.61,Default,,0000,0000,0000,,rules at three broad levels. Atomicity, visibility\Nand ordering. Dialogue: 0,0:08:40.61,0:08:43.04,Default,,0000,0000,0000,,So atomicity is as simple as, you know, variable Dialogue: 0,0:08:43.04,0:08:47.03,Default,,0000,0000,0000,,assignment. Is a variable assignment an indivisible\Nunit of Dialogue: 0,0:08:47.03,0:08:49.52,Default,,0000,0000,0000,,work, or not? The rules around that, and it Dialogue: 0,0:08:49.52,0:08:52.37,Default,,0000,0000,0000,,also talks about rules around, can you assign\Nhashes, Dialogue: 0,0:08:52.37,0:08:55.07,Default,,0000,0000,0000,,send arrays indivisibly and things like that.\NThese rules Dialogue: 0,0:08:55.07,0:08:57.67,Default,,0000,0000,0000,,can change based on every alligned version,\Nand things Dialogue: 0,0:08:57.67,0:09:01.94,Default,,0000,0000,0000,,like that. Next is visibility. So in that\Nexample Dialogue: 0,0:09:01.94,0:09:05.04,Default,,0000,0000,0000,,which you talked about, I mean, we saw two Dialogue: 0,0:09:05.04,0:09:07.31,Default,,0000,0000,0000,,threads trying to read the same value. Essentially\Nthey Dialogue: 0,0:09:07.31,0:09:09.39,Default,,0000,0000,0000,,are spying on each other. And it was not Dialogue: 0,0:09:09.39,0:09:11.53,Default,,0000,0000,0000,,clear at what point the data had to become Dialogue: 0,0:09:11.53,0:09:14.86,Default,,0000,0000,0000,,visible to each of those threads. So essentially\Nvisibility Dialogue: 0,0:09:14.86,0:09:18.24,Default,,0000,0000,0000,,is about that. And that is ensured through\Nmemory Dialogue: 0,0:09:18.24,0:09:21.80,Default,,0000,0000,0000,,barriers and ordering, which is the next thing.\NSo Dialogue: 0,0:09:21.80,0:09:25.12,Default,,0000,0000,0000,,ordering is about how the loads and stores\Nare Dialogue: 0,0:09:25.12,0:09:28.60,Default,,0000,0000,0000,,sequenced, or, you know, let's say you want\Nto Dialogue: 0,0:09:28.60,0:09:30.72,Default,,0000,0000,0000,,write a piece of code, critical section as\Nyou Dialogue: 0,0:09:30.72,0:09:32.88,Default,,0000,0000,0000,,call it. And you don't want the compiler to Dialogue: 0,0:09:32.88,0:09:35.51,Default,,0000,0000,0000,,do any crazy things to improve performance.\NSo you Dialogue: 0,0:09:35.51,0:09:38.14,Default,,0000,0000,0000,,say, I make it synchronized, and it has to Dialogue: 0,0:09:38.14,0:09:40.40,Default,,0000,0000,0000,,behave in a, behave in a nice serial?? [00:09:40] Dialogue: 0,0:09:40.40,0:09:44.73,Default,,0000,0000,0000,,manner. So that ?? manner is ensured by ordering. Dialogue: 0,0:09:44.73,0:09:47.94,Default,,0000,0000,0000,,Ordering is a really complex area. It talks\Nabout Dialogue: 0,0:09:47.94,0:09:50.85,Default,,0000,0000,0000,,causality, logical clocks and all that. I\Nwon't go Dialogue: 0,0:09:50.85,0:09:54.25,Default,,0000,0000,0000,,into those details. But I've been worrying\Nyou with Dialogue: 0,0:09:54.25,0:09:58.07,Default,,0000,0000,0000,,all this, you know, computer science basics\Nand all Dialogue: 0,0:09:58.07,0:10:00.01,Default,,0000,0000,0000,,this. Why the hell am I talking about it Dialogue: 0,0:10:00.01,0:10:02.43,Default,,0000,0000,0000,,in a Ruby conference? Ruby is single-threaded,\Nanyway. Why Dialogue: 0,0:10:02.43,0:10:05.64,Default,,0000,0000,0000,,the hell should I care about it, right? OK. Dialogue: 0,0:10:05.64,0:10:09.12,Default,,0000,0000,0000,,Do you really think languages like Ruby are\Nthread Dialogue: 0,0:10:09.12,0:10:14.94,Default,,0000,0000,0000,,safe? Show of hands, anyone? So thread safety,\NI'm Dialogue: 0,0:10:14.94,0:10:18.60,Default,,0000,0000,0000,,talking only about Ruby - maybe Python. GIL\Nbased Dialogue: 0,0:10:18.60,0:10:25.60,Default,,0000,0000,0000,,languages. Are they thread safe? No? OK. In\Nfact Dialogue: 0,0:10:25.70,0:10:30.65,Default,,0000,0000,0000,,they're not. Having single-threaded does not\Nmean it's thread-safe, Dialogue: 0,0:10:30.65,0:10:33.67,Default,,0000,0000,0000,,right. Threads can switch context, and based\Non how Dialogue: 0,0:10:33.67,0:10:36.08,Default,,0000,0000,0000,,the language has been implemented and how\Noften the Dialogue: 0,0:10:36.08,0:10:38.53,Default,,0000,0000,0000,,threads can switch context, and at what point\Nthey Dialogue: 0,0:10:38.53,0:10:44.01,Default,,0000,0000,0000,,can switch, things can go wrong, right. And\Nanother Dialogue: 0,0:10:44.01,0:10:46.04,Default,,0000,0000,0000,,pretty popular myth - I don't think many people Dialogue: 0,0:10:46.04,0:10:49.39,Default,,0000,0000,0000,,believe it here, in this audience at least.\NI Dialogue: 0,0:10:49.39,0:10:52.44,Default,,0000,0000,0000,,don't have concurrency problems because I'm\Nrunning on single Dialogue: 0,0:10:52.44,0:10:55.69,Default,,0000,0000,0000,,core. Not true. Again, threads can switch\Ncontext and Dialogue: 0,0:10:55.69,0:10:58.63,Default,,0000,0000,0000,,run on the same core and still have dirty Dialogue: 0,0:10:58.63,0:11:02.80,Default,,0000,0000,0000,,reads and things like that. So concurrency\Nis all Dialogue: 0,0:11:02.80,0:11:05.55,Default,,0000,0000,0000,,about interleavings, right. Again, goes back\Nto reordering. I Dialogue: 0,0:11:05.55,0:11:07.87,Default,,0000,0000,0000,,think I've been talking about this too often.\NAnd Dialogue: 0,0:11:07.87,0:11:11.95,Default,,0000,0000,0000,,let's not, again, worry with that. It's about\Ninterleavings. Dialogue: 0,0:11:11.95,0:11:15.62,Default,,0000,0000,0000,,We'll leave it at that. So let's, before we Dialogue: 0,0:11:15.62,0:11:19.24,Default,,0000,0000,0000,,understand more about, you know, the memory\Nmodel and Dialogue: 0,0:11:19.24,0:11:21.02,Default,,0000,0000,0000,,what it has to do with Ruby, let's just Dialogue: 0,0:11:21.02,0:11:25.06,Default,,0000,0000,0000,,understand a little bit about threading in\NRuby. So Dialogue: 0,0:11:25.06,0:11:28.10,Default,,0000,0000,0000,,all of you know, green threads, as of 1.8, Dialogue: 0,0:11:28.10,0:11:31.43,Default,,0000,0000,0000,,there was only one worse thread, which was\Nbeing Dialogue: 0,0:11:31.43,0:11:35.22,Default,,0000,0000,0000,,multiplexed with multiple Ruby threads, which\Nwere being scheduled Dialogue: 0,0:11:35.22,0:11:38.98,Default,,0000,0000,0000,,on it through global interpreter lock. 1.9\Ncomes along, Dialogue: 0,0:11:38.98,0:11:41.20,Default,,0000,0000,0000,,there is a one to one mapping between the Dialogue: 0,0:11:41.20,0:11:43.66,Default,,0000,0000,0000,,Ruby thread and OS thread, but still the Ruby Dialogue: 0,0:11:43.66,0:11:46.62,Default,,0000,0000,0000,,thread cannot use the OS thread unless it\Nhas Dialogue: 0,0:11:46.62,0:11:50.98,Default,,0000,0000,0000,,the global VM lock as its call now. The Dialogue: 0,0:11:50.98,0:11:55.75,Default,,0000,0000,0000,,JVL acquire. So does having a Global Interpreter\NLock Dialogue: 0,0:11:55.75,0:12:00.71,Default,,0000,0000,0000,,make you thread safe? It depends. It does\Nmake Dialogue: 0,0:12:00.71,0:12:03.26,Default,,0000,0000,0000,,you thread safe in a way, but let's see. Dialogue: 0,0:12:03.26,0:12:05.33,Default,,0000,0000,0000,,So how does GIL work? This is a very Dialogue: 0,0:12:05.33,0:12:08.51,Default,,0000,0000,0000,,simplistic representation of how GIL works.\NSo you have Dialogue: 0,0:12:08.51,0:12:12.12,Default,,0000,0000,0000,,two threads here. One is already holding the\NGIL. Dialogue: 0,0:12:12.12,0:12:15.52,Default,,0000,0000,0000,,So it's, it's working with the OS thread.\NAnd Dialogue: 0,0:12:15.52,0:12:18.82,Default,,0000,0000,0000,,now when there is another thread waiting on\Nit, Dialogue: 0,0:12:18.82,0:12:21.19,Default,,0000,0000,0000,,waiting on the GIL to do its work, it Dialogue: 0,0:12:21.19,0:12:22.51,Default,,0000,0000,0000,,sends a, it wakes up the timer thread. Time Dialogue: 0,0:12:22.51,0:12:26.79,Default,,0000,0000,0000,,thread is, again, another Ruby thread. The\Ntimer thread Dialogue: 0,0:12:26.79,0:12:30.41,Default,,0000,0000,0000,,now goes and interrupts the thread holding\Nthe GIL, Dialogue: 0,0:12:30.41,0:12:32.04,Default,,0000,0000,0000,,and if the GIL, if the thread holding the Dialogue: 0,0:12:32.04,0:12:34.89,Default,,0000,0000,0000,,GIL is done with whatever it's doing - I'll Dialogue: 0,0:12:34.89,0:12:36.55,Default,,0000,0000,0000,,get to it in a bit - it just Dialogue: 0,0:12:36.55,0:12:40.32,Default,,0000,0000,0000,,releases the lock, and now thread two can\Ntake Dialogue: 0,0:12:40.32,0:12:42.83,Default,,0000,0000,0000,,over and do its thing. Well this is the Dialogue: 0,0:12:42.83,0:12:48.33,Default,,0000,0000,0000,,basic working that at least I understood about\NGIL. Dialogue: 0,0:12:48.33,0:12:50.30,Default,,0000,0000,0000,,But there are details to this, right. It's\Nnot Dialogue: 0,0:12:50.30,0:12:57.30,Default,,0000,0000,0000,,as simple as what we saw. So, when you Dialogue: 0,0:12:57.78,0:13:00.93,Default,,0000,0000,0000,,initialize a thread, or create a thread in\NRuby, Dialogue: 0,0:13:00.93,0:13:03.10,Default,,0000,0000,0000,,you pass it a block of code. So how Dialogue: 0,0:13:03.10,0:13:06.24,Default,,0000,0000,0000,,does that work? You take a block of code, Dialogue: 0,0:13:06.24,0:13:07.77,Default,,0000,0000,0000,,you put it inside the thread. What the thread Dialogue: 0,0:13:07.77,0:13:10.48,Default,,0000,0000,0000,,does is usually it acquires a JVL and a Dialogue: 0,0:13:10.48,0:13:14.02,Default,,0000,0000,0000,,block?? [00:13:11]. It executes the block\Nof code. It Dialogue: 0,0:13:14.02,0:13:17.09,Default,,0000,0000,0000,,releases the, returns and releases the lock,\Nright. So Dialogue: 0,0:13:17.09,0:13:19.47,Default,,0000,0000,0000,,essentially this is how it works. So during\Nthat Dialogue: 0,0:13:19.47,0:13:21.90,Default,,0000,0000,0000,,period of executation of the block, no other\Nthread Dialogue: 0,0:13:21.90,0:13:24.38,Default,,0000,0000,0000,,is allowed to work. So that makes you almost Dialogue: 0,0:13:24.38,0:13:28.11,Default,,0000,0000,0000,,thread safe, right? But not really. If that's\Nhow Dialogue: 0,0:13:28.11,0:13:30.60,Default,,0000,0000,0000,,it's going to work, what if that thread is Dialogue: 0,0:13:30.60,0:13:33.90,Default,,0000,0000,0000,,going to hog the GIL, and not allow any Dialogue: 0,0:13:33.90,0:13:35.76,Default,,0000,0000,0000,,other thread to work? So there has to be Dialogue: 0,0:13:35.76,0:13:38.43,Default,,0000,0000,0000,,some kind of lock fairness, right. So that's\Nwhere Dialogue: 0,0:13:38.43,0:13:41.18,Default,,0000,0000,0000,,the timer thread comes in and interrupts it.\NOK. Dialogue: 0,0:13:41.18,0:13:43.13,Default,,0000,0000,0000,,Does that mean the thread holding the GIL\Nimmediately Dialogue: 0,0:13:43.13,0:13:45.19,Default,,0000,0000,0000,,gives it up, and says here you go, you Dialogue: 0,0:13:45.19,0:13:48.74,Default,,0000,0000,0000,,can start and work with it? Not really. Again Dialogue: 0,0:13:48.74,0:13:51.39,Default,,0000,0000,0000,,the thread holding the GIL will only release\Nthe Dialogue: 0,0:13:51.39,0:13:53.92,Default,,0000,0000,0000,,GIL if it is at a context to its Dialogue: 0,0:13:53.92,0:13:57.02,Default,,0000,0000,0000,,boundary. What that is, is fairly complicated.\NI don't Dialogue: 0,0:13:57.02,0:13:59.92,Default,,0000,0000,0000,,want to go into the details. I think people Dialogue: 0,0:13:59.92,0:14:02.54,Default,,0000,0000,0000,,who here know a lot better C than me, Dialogue: 0,0:14:02.54,0:14:05.11,Default,,0000,0000,0000,,and are deep C divers really, they can probably Dialogue: 0,0:14:05.11,0:14:08.67,Default,,0000,0000,0000,,tell you, you know, how, at what the GIL Dialogue: 0,0:14:08.67,0:14:11.04,Default,,0000,0000,0000,,can get released. If a C thread, a C Dialogue: 0,0:14:11.04,0:14:13.27,Default,,0000,0000,0000,,code makes a call to Ruby code, can it Dialogue: 0,0:14:13.27,0:14:15.45,Default,,0000,0000,0000,,or can it not release the GIL? All those Dialogue: 0,0:14:15.45,0:14:18.40,Default,,0000,0000,0000,,things are there, right. So all these complexities\Nare Dialogue: 0,0:14:18.40,0:14:21.36,Default,,0000,0000,0000,,really, really hard to deal with. I came across Dialogue: 0,0:14:21.36,0:14:25.14,Default,,0000,0000,0000,,this blog by Jesse Storimer. It's excellent\Nand I Dialogue: 0,0:14:25.14,0:14:27.44,Default,,0000,0000,0000,,strongly encourage you to go through the two-part\Nblog Dialogue: 0,0:14:27.44,0:14:30.99,Default,,0000,0000,0000,,about, you know, nobody understands GIL. It's\Nreally, really Dialogue: 0,0:14:30.99,0:14:33.55,Default,,0000,0000,0000,,important, if you're trying to do any sort\Nof Dialogue: 0,0:14:33.55,0:14:39.74,Default,,0000,0000,0000,,multi-threaded programming in Ruby. So do\Nyou still think Dialogue: 0,0:14:39.74,0:14:42.74,Default,,0000,0000,0000,,Ruby is thread safe because it's got GIL?\NI'm Dialogue: 0,0:14:42.74,0:14:48.74,Default,,0000,0000,0000,,talking about MRI, essentially. So the thing\Nis, we Dialogue: 0,0:14:48.74,0:14:51.63,Default,,0000,0000,0000,,can't depend on GIL, right. GIL is not documented Dialogue: 0,0:14:51.63,0:14:54.05,Default,,0000,0000,0000,,anywhere that this is exactly how it works.\NThis Dialogue: 0,0:14:54.05,0:14:56.08,Default,,0000,0000,0000,,is when the timer thread wakes up. These are Dialogue: 0,0:14:56.08,0:14:59.31,Default,,0000,0000,0000,,the time slices alotted to the thread acquiring\Nthe Dialogue: 0,0:14:59.31,0:15:03.19,Default,,0000,0000,0000,,JVL. There is no documentation around at what\Npoint Dialogue: 0,0:15:03.19,0:15:04.86,Default,,0000,0000,0000,,the GIL can be released, can it not be Dialogue: 0,0:15:04.86,0:15:07.01,Default,,0000,0000,0000,,released, and things like that. There's no,\Nit's not Dialogue: 0,0:15:07.01,0:15:10.26,Default,,0000,0000,0000,,predictable, and if you depend on it, what\Ncould Dialogue: 0,0:15:10.26,0:15:13.14,Default,,0000,0000,0000,,also happen is even within MRI, when you're\Nmoving Dialogue: 0,0:15:13.14,0:15:15.92,Default,,0000,0000,0000,,from version to version, if something changes\Nin GIL, Dialogue: 0,0:15:15.92,0:15:22.22,Default,,0000,0000,0000,,your code with behave nondeterministically.\NAnd what about language Dialogue: 0,0:15:22.22,0:15:25.21,Default,,0000,0000,0000,,in Ruby implementations that don't even have\Na GIL? Dialogue: 0,0:15:25.21,0:15:27.01,Default,,0000,0000,0000,,So obviously that's the big problem, right.\NIf you Dialogue: 0,0:15:27.01,0:15:29.61,Default,,0000,0000,0000,,write a gem or something which has to be Dialogue: 0,0:15:29.61,0:15:32.08,Default,,0000,0000,0000,,multi-threaded, and if you're depending on\Nthe GIL to Dialogue: 0,0:15:32.08,0:15:34.77,Default,,0000,0000,0000,,do its thing to keep you safe, then obviously Dialogue: 0,0:15:34.77,0:15:38.55,Default,,0000,0000,0000,,it cannot work on Rubinius and JRuby. Let\Nthat Dialogue: 0,0:15:38.55,0:15:41.31,Default,,0000,0000,0000,,alone, even, even if you give that up, even Dialogue: 0,0:15:41.31,0:15:44.36,Default,,0000,0000,0000,,with MRI, it's not entirely correct to say\Nthat Dialogue: 0,0:15:44.36,0:15:47.49,Default,,0000,0000,0000,,you're thread safe, because there is a GIL\Nthat Dialogue: 0,0:15:47.49,0:15:52.66,Default,,0000,0000,0000,,will ensure that only one thread is running.\NSo Dialogue: 0,0:15:52.66,0:15:54.61,Default,,0000,0000,0000,,what did I find out? Ruby really does not Dialogue: 0,0:15:54.61,0:15:57.35,Default,,0000,0000,0000,,have a documented memory model. It's pretty\Nmuch similar Dialogue: 0,0:15:57.35,0:16:00.48,Default,,0000,0000,0000,,to Python. It doesn't have a clearly documented\Nmemory Dialogue: 0,0:16:00.48,0:16:05.28,Default,,0000,0000,0000,,model. What is the implication of that? So\Nas Dialogue: 0,0:16:05.28,0:16:07.54,Default,,0000,0000,0000,,I mentioned previously, a memory model is\Nlike a Dialogue: 0,0:16:07.54,0:16:10.77,Default,,0000,0000,0000,,specification. This is exactly how the system\Nhas to Dialogue: 0,0:16:10.77,0:16:14.60,Default,,0000,0000,0000,,provide a certain minimum guarantee to the\Nusers of Dialogue: 0,0:16:14.60,0:16:17.73,Default,,0000,0000,0000,,the language, right, regarding multi threaded\Naccess to shared Dialogue: 0,0:16:17.73,0:16:22.50,Default,,0000,0000,0000,,memory. Now, basically if I don't have a written Dialogue: 0,0:16:22.50,0:16:23.72,Default,,0000,0000,0000,,down memory model, and I am going to write Dialogue: 0,0:16:23.72,0:16:26.54,Default,,0000,0000,0000,,a Ruby implementation to model, I have the\Nliberty Dialogue: 0,0:16:26.54,0:16:29.51,Default,,0000,0000,0000,,to choose whatever memory model I want. So\Nthe Dialogue: 0,0:16:29.51,0:16:32.89,Default,,0000,0000,0000,,code, if you're writing against MRI, may not\Nessentially Dialogue: 0,0:16:32.89,0:16:36.72,Default,,0000,0000,0000,,work right on my, you know, my implementation\Nof Dialogue: 0,0:16:36.72,0:16:41.34,Default,,0000,0000,0000,,Ruby. That's the big implication, right. So\NRuby right Dialogue: 0,0:16:41.34,0:16:45.77,Default,,0000,0000,0000,,now depends on underlying virtual machines.\NEven after ER, Dialogue: 0,0:16:45.77,0:16:47.70,Default,,0000,0000,0000,,you have bad code compilations, so even MRI\Nis Dialogue: 0,0:16:47.70,0:16:50.84,Default,,0000,0000,0000,,almost like a VM. So that has no specification Dialogue: 0,0:16:50.84,0:16:52.96,Default,,0000,0000,0000,,for a memory model, but it does have something, Dialogue: 0,0:16:52.96,0:16:55.28,Default,,0000,0000,0000,,right, internally. If you have to go through\Nthe Dialogue: 0,0:16:55.28,0:16:58.13,Default,,0000,0000,0000,,C code and understand. It's not guaranteed\Nto remain Dialogue: 0,0:16:58.13,0:17:01.08,Default,,0000,0000,0000,,the same from version to version, as I understand, Dialogue: 0,0:17:01.08,0:17:05.07,Default,,0000,0000,0000,,right. And obviously JRuby and Rubinius, they\Ndepend on Dialogue: 0,0:17:05.07,0:17:08.26,Default,,0000,0000,0000,,JVM and LLVM respectively. And they all have\Na Dialogue: 0,0:17:08.26,0:17:11.82,Default,,0000,0000,0000,,clearly documented memory model. You could\Nhave a read Dialogue: 0,0:17:11.82,0:17:15.26,Default,,0000,0000,0000,,at it. And the only thing is, if Ruby Dialogue: 0,0:17:15.26,0:17:18.08,Default,,0000,0000,0000,,had an implementation - sorry, a specification\Nfor a Dialogue: 0,0:17:18.08,0:17:22.22,Default,,0000,0000,0000,,memory model, it could be, you know, implemented\Nusing Dialogue: 0,0:17:22.22,0:17:27.60,Default,,0000,0000,0000,,the constructs available on JVM and LLVM.\NBut this Dialogue: 0,0:17:27.60,0:17:29.45,Default,,0000,0000,0000,,is what we have. We don't have much to Dialogue: 0,0:17:29.45,0:17:33.20,Default,,0000,0000,0000,,do. What do we do under the circumstances?\NWe Dialogue: 0,0:17:33.20,0:17:36.64,Default,,0000,0000,0000,,have to engineer our code for thread safety.\NWe Dialogue: 0,0:17:36.64,0:17:40.12,Default,,0000,0000,0000,,can't bask under the safety that, there is\Na Dialogue: 0,0:17:40.12,0:17:42.41,Default,,0000,0000,0000,,GIL and so it's going to help me keep Dialogue: 0,0:17:42.41,0:17:44.53,Default,,0000,0000,0000,,my code thread safe. So even I can write Dialogue: 0,0:17:44.53,0:17:47.69,Default,,0000,0000,0000,,multiple, you know, multi threaded code without\Nactually worrying Dialogue: 0,0:17:47.69,0:17:51.29,Default,,0000,0000,0000,,about serious synchronization issues and things\Nlike that. It's Dialogue: 0,0:17:51.29,0:17:54.50,Default,,0000,0000,0000,,totally not the right thing to do. I think Dialogue: 0,0:17:54.50,0:17:57.37,Default,,0000,0000,0000,,any which way, Ruby is a language I love, Dialogue: 0,0:17:57.37,0:17:59.71,Default,,0000,0000,0000,,and I'm sure all of you love, so. And Dialogue: 0,0:17:59.71,0:18:02.67,Default,,0000,0000,0000,,it's progressing my leaps and bounds, and\Neventually we're Dialogue: 0,0:18:02.67,0:18:04.84,Default,,0000,0000,0000,,going to write more and more complex systems\Nwith Dialogue: 0,0:18:04.84,0:18:09.39,Default,,0000,0000,0000,,Ruby. And who knows, we might have true parallelism Dialogue: 0,0:18:09.39,0:18:13.98,Default,,0000,0000,0000,,very soon, right. So why, still, stay in the Dialogue: 0,0:18:13.98,0:18:17.21,Default,,0000,0000,0000,,same mental block that we don't want to write, Dialogue: 0,0:18:17.21,0:18:20.48,Default,,0000,0000,0000,,you know, thread safe code that's anyway single\Nthreaded. Dialogue: 0,0:18:20.48,0:18:22.15,Default,,0000,0000,0000,,We might as well get into the mindset of Dialogue: 0,0:18:22.15,0:18:26.13,Default,,0000,0000,0000,,writing proper thread safe code, and try and\Nprobably Dialogue: 0,0:18:26.13,0:18:29.50,Default,,0000,0000,0000,,come up with a memory model, right. But I Dialogue: 0,0:18:29.50,0:18:31.70,Default,,0000,0000,0000,,think for now we just start engineering code\Nfor Dialogue: 0,0:18:31.70,0:18:36.86,Default,,0000,0000,0000,,thread safety. Simple Mutex, I'm sure all\Nof you Dialogue: 0,0:18:36.86,0:18:39.58,Default,,0000,0000,0000,,know, but it's really, really important for\Neven a Dialogue: 0,0:18:39.58,0:18:44.09,Default,,0000,0000,0000,,stupid operation like a plus equals two. So\Nsimple Dialogue: 0,0:18:44.09,0:18:46.97,Default,,0000,0000,0000,,things which are noticed in Ruby code bases\Nand Dialogue: 0,0:18:46.97,0:18:50.53,Default,,0000,0000,0000,,Rails code bases as well, like generally,\Nis, there Dialogue: 0,0:18:50.53,0:18:52.92,Default,,0000,0000,0000,,is like a synchronized, you know, a section\Nof Dialogue: 0,0:18:52.92,0:18:56.26,Default,,0000,0000,0000,,the code has lots of synchronization and everything.\NIt's Dialogue: 0,0:18:56.26,0:18:58.53,Default,,0000,0000,0000,,really safe. But we leave an innocent accessor\Nlying Dialogue: 0,0:18:58.53,0:19:00.76,Default,,0000,0000,0000,,around, and that causes a lot of, you know, Dialogue: 0,0:19:00.76,0:19:04.36,Default,,0000,0000,0000,,pain, like debugging those issues. And general\Nissues like, Dialogue: 0,0:19:04.36,0:19:08.02,Default,,0000,0000,0000,,you know, state mutations, inside methods\Nis really a Dialogue: 0,0:19:08.02,0:19:10.27,Default,,0000,0000,0000,,bad idea. So if you're looking for issues\Naround Dialogue: 0,0:19:10.27,0:19:12.20,Default,,0000,0000,0000,,multi threading, this might be a good place\Nto Dialogue: 0,0:19:12.20,0:19:14.35,Default,,0000,0000,0000,,start. So I just listed a few of them Dialogue: 0,0:19:14.35,0:19:16.31,Default,,0000,0000,0000,,here. I didn't want to make a really dense Dialogue: 0,0:19:16.31,0:19:19.21,Default,,0000,0000,0000,,talk with all the details. You can always\Ncatch Dialogue: 0,0:19:19.21,0:19:20.94,Default,,0000,0000,0000,,me offline and I can tell you some of Dialogue: 0,0:19:20.94,0:19:23.60,Default,,0000,0000,0000,,my experiences and probably even listen to\Nyou and Dialogue: 0,0:19:23.60,0:19:25.98,Default,,0000,0000,0000,,learn from you about some of the issues that Dialogue: 0,0:19:25.98,0:19:28.82,Default,,0000,0000,0000,,we can solve by actually writing proper thread\Nsafe Dialogue: 0,0:19:28.82,0:19:33.08,Default,,0000,0000,0000,,code in Ruby. I came across a few gems Dialogue: 0,0:19:33.08,0:19:35.09,Default,,0000,0000,0000,,which were really, really nice. Both of them\Nhappen Dialogue: 0,0:19:35.09,0:19:38.68,Default,,0000,0000,0000,,to be written by headius. The first one is Dialogue: 0,0:19:38.68,0:19:40.73,Default,,0000,0000,0000,,atomic. Atomic is almost trying to give you\Nthe Dialogue: 0,0:19:40.73,0:19:44.97,Default,,0000,0000,0000,,similar constructs like the Java utility concurrent\Npackage. It Dialogue: 0,0:19:44.97,0:19:51.30,Default,,0000,0000,0000,,tries to, it's kind of compatible across MRI,\NJRuby, Dialogue: 0,0:19:51.30,0:19:53.80,Default,,0000,0000,0000,,and Rubinius, which is also a really nice\Nthing. Dialogue: 0,0:19:53.80,0:19:56.56,Default,,0000,0000,0000,,So you have atomic integers and atomic floats,\Nwhich Dialogue: 0,0:19:56.56,0:19:59.90,Default,,0000,0000,0000,,do increments actually in an atomic way, which\Nis Dialogue: 0,0:19:59.90,0:20:02.46,Default,,0000,0000,0000,,excellent. And then there is thread_safe library,\Nwhich also Dialogue: 0,0:20:02.46,0:20:04.59,Default,,0000,0000,0000,,has a few thread safe data structures. I'm\Ntrying Dialogue: 0,0:20:04.59,0:20:06.57,Default,,0000,0000,0000,,to play around with these libraries right\Nnow, but Dialogue: 0,0:20:06.57,0:20:09.15,Default,,0000,0000,0000,,they may be a good, you know, starting point Dialogue: 0,0:20:09.15,0:20:10.78,Default,,0000,0000,0000,,if you are trying to do higher level constructs Dialogue: 0,0:20:10.78,0:20:15.62,Default,,0000,0000,0000,,for concurrency. And that's pretty much it.\NI'm open Dialogue: 0,0:20:15.62,0:20:21.82,Default,,0000,0000,0000,,to take questions. Thank you. And before anything\NI Dialogue: 0,0:20:21.82,0:20:23.42,Default,,0000,0000,0000,,really would like to thank you all, again\Nfor Dialogue: 0,0:20:23.42,0:20:27.14,Default,,0000,0000,0000,,being here for the talk, and thank the GCRC Dialogue: 0,0:20:27.14,0:20:31.41,Default,,0000,0000,0000,,organizers, you know, they've done a great\Njob with Dialogue: 0,0:20:31.41,0:20:38.41,Default,,0000,0000,0000,,this conference. A big shout out to them. Dialogue: 0,0:20:46.47,0:20:46.51,Default,,0000,0000,0000,,V.O.: Any questions? Dialogue: 0,0:20:46.51,0:20:46.54,Default,,0000,0000,0000,,H.K.: Yeah? Dialogue: 0,0:20:46.54,0:20:46.56,Default,,0000,0000,0000,,QUESTION: Hey. Dialogue: 0,0:20:46.56,0:20:46.59,Default,,0000,0000,0000,,H.K.: Hi. Dialogue: 0,0:20:46.59,0:20:47.52,Default,,0000,0000,0000,,QUESTION: If, for example, if a Ruby code\Nis running Dialogue: 0,0:20:47.52,0:20:51.53,Default,,0000,0000,0000,,in the JVM, in JRuby, how does, because none Dialogue: 0,0:20:51.53,0:20:53.81,Default,,0000,0000,0000,,of the Ruby code is written in a thread Dialogue: 0,0:20:53.81,0:20:56.58,Default,,0000,0000,0000,,safe way. How do, how does it internally manage Dialogue: 0,0:20:56.58,0:20:58.75,Default,,0000,0000,0000,,- does it actually, yeah, yesterday Yogi talked\Nabout Dialogue: 0,0:20:58.75,0:21:00.94,Default,,0000,0000,0000,,the point that ActiveRecord is not actually\Nthread safe. Dialogue: 0,0:21:00.94,0:21:03.52,Default,,0000,0000,0000,,Can you explain it in detail like in a Dialogue: 0,0:21:03.52,0:21:04.46,Default,,0000,0000,0000,,theoretical way? Dialogue: 0,0:21:04.46,0:21:06.56,Default,,0000,0000,0000,,H.K.: OK. What is thread safety in Dialogue: 0,0:21:06.56,0:21:09.01,Default,,0000,0000,0000,,general, right? Thread safety is about how\Nthe data Dialogue: 0,0:21:09.01,0:21:13.28,Default,,0000,0000,0000,,is consistently maintained after multi-threaded\Naccess to that shared Dialogue: 0,0:21:13.28,0:21:17.13,Default,,0000,0000,0000,,data, right. So Ruby essentially has a GIL\Nbecause Dialogue: 0,0:21:17.13,0:21:19.62,Default,,0000,0000,0000,,internal implementations are not thread safe,\Nright. That's why Dialogue: 0,0:21:19.62,0:21:22.11,Default,,0000,0000,0000,,you want to have a GIL to protect you Dialogue: 0,0:21:22.11,0:21:25.84,Default,,0000,0000,0000,,from those problems. But as far as JRuby is Dialogue: 0,0:21:25.84,0:21:29.28,Default,,0000,0000,0000,,concerned, or Rubinius is concerned, the implementation\Nitself is Dialogue: 0,0:21:29.28,0:21:31.93,Default,,0000,0000,0000,,not written in C. JRuby is written in Ruby Dialogue: 0,0:21:31.93,0:21:34.40,Default,,0000,0000,0000,,again, I mean JRuby itself, and Rubinius is\Nwritten Dialogue: 0,0:21:34.40,0:21:37.66,Default,,0000,0000,0000,,in Ruby. And some of these actual internal\Nconstructs Dialogue: 0,0:21:37.66,0:21:40.58,Default,,0000,0000,0000,,are thread safe when compared to MRI. I haven't Dialogue: 0,0:21:40.58,0:21:43.19,Default,,0000,0000,0000,,actually taken a look in detail into the code Dialogue: 0,0:21:43.19,0:21:47.52,Default,,0000,0000,0000,,of these code bases, but if they are implemented Dialogue: 0,0:21:47.52,0:21:50.00,Default,,0000,0000,0000,,properly, you can be thread safe - internally,\Nat Dialogue: 0,0:21:50.00,0:21:53.34,Default,,0000,0000,0000,,least - so, which means, the base code of Dialogue: 0,0:21:53.34,0:21:55.72,Default,,0000,0000,0000,,JRuby itself might be thread safe. It's only\Nnot Dialogue: 0,0:21:55.72,0:21:58.20,Default,,0000,0000,0000,,thread safe because the gems on top of it, Dialogue: 0,0:21:58.20,0:22:01.05,Default,,0000,0000,0000,,which are trying to run. They may have, like, Dialogue: 0,0:22:01.05,0:22:04.89,Default,,0000,0000,0000,,thread safety issues, right. Does that answer\Nyour question, Dialogue: 0,0:22:04.89,0:22:05.84,Default,,0000,0000,0000,,like, or- ? Dialogue: 0,0:22:05.84,0:22:08.20,Default,,0000,0000,0000,,QUESTION: About thread safety?? [00:22:09]. Dialogue: 0,0:22:08.20,0:22:11.72,Default,,0000,0000,0000,,H.K.: Sure, sure. So those gems will not work.\NThat's Dialogue: 0,0:22:11.72,0:22:13.84,Default,,0000,0000,0000,,the point. Like what I want to convey here, Dialogue: 0,0:22:13.84,0:22:16.91,Default,,0000,0000,0000,,is whatever gems we are offering, and whatever\Ncode Dialogue: 0,0:22:16.91,0:22:18.78,Default,,0000,0000,0000,,we are writing, we might get it - it's Dialogue: 0,0:22:18.78,0:22:20.24,Default,,0000,0000,0000,,a good idea to get into the habit of Dialogue: 0,0:22:20.24,0:22:22.86,Default,,0000,0000,0000,,writing thread safe code, so that we can actually Dialogue: 0,0:22:22.86,0:22:25.46,Default,,0000,0000,0000,,encourage a truly parallel Ruby, right. We\Ndon't, we Dialogue: 0,0:22:25.46,0:22:27.53,Default,,0000,0000,0000,,don't have to stay in the same paradigm of Dialogue: 0,0:22:27.53,0:22:31.52,Default,,0000,0000,0000,,OK we have to be single threaded. Dialogue: 0,0:22:31.52,0:22:37.01,Default,,0000,0000,0000,,QUESTION: So Mutex based thread management\Nis one way. Dialogue: 0,0:22:37.01,0:22:40.06,Default,,0000,0000,0000,,There's also like actors and futures and things\Nlike that. Dialogue: 0,0:22:40.06,0:22:41.89,Default,,0000,0000,0000,,And there's a gem called cellulite- Dialogue: 0,0:22:41.89,0:22:42.68,Default,,0000,0000,0000,,H.K.: Yup. Dialogue: 0,0:22:42.68,0:22:45.04,Default,,0000,0000,0000,,QUESTION: That, combined with something called\NHamster, Dialogue: 0,0:22:45.04,0:22:46.39,Default,,0000,0000,0000,,which makes everything immutable- Dialogue: 0,0:22:46.39,0:22:46.84,Default,,0000,0000,0000,,H.K.: Yup. Dialogue: 0,0:22:46.84,0:22:47.96,Default,,0000,0000,0000,,QUESTION: Is another way to do it. Dialogue: 0,0:22:47.96,0:22:48.16,Default,,0000,0000,0000,,H.K.: Yup. Dialogue: 0,0:22:48.16,0:22:49.07,Default,,0000,0000,0000,,QUESTION: Have you done it or like, Dialogue: 0,0:22:49.07,0:22:49.95,Default,,0000,0000,0000,,what's your experience with that? Dialogue: 0,0:22:49.95,0:22:53.13,Default,,0000,0000,0000,,H.K.: Yeah, I have tried out actors, with\Nrevactor, Dialogue: 0,0:22:53.13,0:22:54.33,Default,,0000,0000,0000,,and lockless concurrency is Dialogue: 0,0:22:54.33,0:22:56.83,Default,,0000,0000,0000,,something I definitely agree is a good idea.\NBut Dialogue: 0,0:22:56.83,0:23:01.44,Default,,0000,0000,0000,,I'm specifically talking about, you know,\Nlock-based concurrency, like, Dialogue: 0,0:23:01.44,0:23:04.53,Default,,0000,0000,0000,,Mutex-based concurrency. This area is also\Nimportant because it's Dialogue: 0,0:23:04.53,0:23:07.96,Default,,0000,0000,0000,,not like thread mutable state is bad. It is, Dialogue: 0,0:23:07.96,0:23:10.77,Default,,0000,0000,0000,,it is actually applicable in certain scenarios.\NWhen we Dialogue: 0,0:23:10.77,0:23:13.36,Default,,0000,0000,0000,,are working in this particular paradigm, we\Nstill need Dialogue: 0,0:23:13.36,0:23:19.17,Default,,0000,0000,0000,,the safety of a memory model. Any other questions? Dialogue: 0,0:23:19.17,0:23:26.17,Default,,0000,0000,0000,,QUESTION: Thanks for the talk Hari. It was\Nreally Dialogue: 0,0:23:28.20,0:23:28.65,Default,,0000,0000,0000,,good. Dialogue: 0,0:23:28.65,0:23:29.55,Default,,0000,0000,0000,,H.K.: Thanks. Dialogue: 0,0:23:29.55,0:23:31.14,Default,,0000,0000,0000,,QUESTION: Is there a way that Dialogue: 0,0:23:31.14,0:23:35.05,Default,,0000,0000,0000,,you would recommend to test if you have done Dialogue: 0,0:23:35.05,0:23:37.85,Default,,0000,0000,0000,,threading properly or not? I mean, I know,\Nbugs Dialogue: 0,0:23:37.85,0:23:38.42,Default,,0000,0000,0000,,that come out- Dialogue: 0,0:23:38.42,0:23:38.61,Default,,0000,0000,0000,,H.K.: Right. Dialogue: 0,0:23:38.61,0:23:38.98,Default,,0000,0000,0000,,QUESTION: Like I have Dialogue: 0,0:23:38.98,0:23:41.68,Default,,0000,0000,0000,,written bugs that come out of badly written,\Nyou Dialogue: 0,0:23:41.68,0:23:43.75,Default,,0000,0000,0000,,know, not thread safe code, as. Dialogue: 0,0:23:43.75,0:23:44.51,Default,,0000,0000,0000,,H.K.: So- Dialogue: 0,0:23:44.51,0:23:47.19,Default,,0000,0000,0000,,QUESTION: Like, ?? [00:23:46] so, you catch\Nthem. Dialogue: 0,0:23:47.19,0:23:51.51,Default,,0000,0000,0000,,H.K.: At least, my opinion, and a lot of people\Nhave Dialogue: 0,0:23:51.51,0:23:53.96,Default,,0000,0000,0000,,done research in this area, their opinion\Nalso is Dialogue: 0,0:23:53.96,0:23:57.60,Default,,0000,0000,0000,,that it's not possible to write tests against\Nmulti Dialogue: 0,0:23:57.60,0:24:00.48,Default,,0000,0000,0000,,threaded code where there is shared data.\NBecause it's Dialogue: 0,0:24:00.48,0:24:04.23,Default,,0000,0000,0000,,nondeterministic and nonrepeatable. The kind\Nof results you get, Dialogue: 0,0:24:04.23,0:24:06.92,Default,,0000,0000,0000,,you can only test it against a heuristic.\NFor Dialogue: 0,0:24:06.92,0:24:09.43,Default,,0000,0000,0000,,example, if you have a deterministic use case\Nat Dialogue: 0,0:24:09.43,0:24:11.62,Default,,0000,0000,0000,,the top level, you can probably test it against Dialogue: 0,0:24:11.62,0:24:14.49,Default,,0000,0000,0000,,that. But exact test cases can never be written Dialogue: 0,0:24:14.49,0:24:16.07,Default,,0000,0000,0000,,for this. Dialogue: 0,0:24:16.07,0:24:19.24,Default,,0000,0000,0000,,V.O.: Any more questions? Dialogue: 0,0:24:19.24,0:24:26.24,Default,,0000,0000,0000,,H.K.: Cool. All right. Thank you so much.