Python for the .NET Developer Transcripts
Chapter: async and await in Python
Lecture: Async for speed
0:00 Maybe you don't care about scalability handling many requests the same speed you would handle one.
0:06 You care about raw speed, you want to take the one thing you're doing and make it go faster. And threading and parallelism
0:15 is definitely powerful for that, let's see why. Here is my MacBook, as viewed from the virtual machine
0:22 that I was running Windows 10 on, and if we ask it how many CPU's it has, it says I have 12 CPU's. By the way, how awesome is that?
0:31 It's actually a core I9 with six cores and then those cores are hyper threaded so the OS sees those as 12 CPU's.
0:39 Look in the background, I've launched Python the REPL, the read eval print loop. Here just type Python, and then I wrote a really simple program.
0:47 I said, x = 1 while true increment x. Look at the CPU level of the system. That program is absolutely pinned working as hard as it possibly can, right?
0:57 It's while true adding one just 'til you stop it. But if we look at the CPU level the CPU level given the recording of Camtasia
1:06 the entire operating system plus this is only 9.57%. This program at max can only do 1/12th of what the operating system believes that it could do.
1:18 That is not great, so how do we solve that problem? Well, we have to do more stuff concurrently. This algorithm obviously doesn't lend itself
1:27 to concurrency, but many algorithms do. So if we were able to write, break up our code our algorithm, into multiple concurrent steps
1:36 and run those say on threads, then we would be able to take advantage of all of these cores and make our code truly fly, that's the promise.
1:46 On Python, there's a limitation it's not as bad as it sounds, but there is this limitation that really effects thread performance
1:53 and computational speed. You probably have heard of this thing called the GIL or the Global Interpreter Lock.
1:59 And we talked about reference counting, right? When we create an object or we de-reference an object we increment or decrement that counter
2:06 that reference count. Now, Python had a choice to make. Could it support concurrent interaction with all of those objects where it would
2:15 have to lock on every one of those references? Or it could say, You know what, we're not going to allow more than one interpreter operation
2:22 to run at any given moment. In which case, we don't need to lock that because only one reference or de-reference could possibly be happening there.
2:31 That's the path they went, and it's really about protecting memory management consistency, not a threaded sort of thing.
2:38 But the effect is that Python can only run a single Python instruction at the byte level at a time no matter how many threads you have.
2:46 So that means for pure Python threads do not really do anything other than add overhead for computational speed, that's a bummer.
2:55 Well see, there's actually a couple ways that we can get around that and make our Python take advantage of all those twelve cores and fly, as well.
3:01 One of them is something called multiprocessing which is where you take what would be a thread and you kind of copy it into a separate copy of Python
3:09 along with the data it's using, run it over there and then just get the return value. That way it's a separate process which does not share
3:16 the GIL, right, the GIL is a per-process type of thing. So that's Python's main way of getting around this GIL situation and we'll see a little bit
3:24 about that right at the end, okay? But if you want to read more about this there's a great article over at realPython.com/Python-gil.
3:33 What you'll find is that even with this GIL in place if the two threads are working in Python and one of them is talking over, say a network
3:41 or doing certain types of C code down at a lower level it can actually release the GIL and regain some concurrency so it's not as bad as it sounds.
3:49 But it is something you definitely need to be aware of and it's something very different than C#.