 We'll be giving us this talk and there will be time for questions at the end We are delivering this talk together with Stefan So we just thought that instead of having two standard talks that we give why don't do something special this year Why don't bring you some fresh material? so we tried our best to give you some New use cases new examples of the tools that you might already heard of many times So we are really happy to present you today How can we use a sink a yo and site on together to make more efficient software? so Let's start. We will just begin with the introduction because we see people are still coming So Stefan. Yeah, why don't you introduce yourself? I'm Stefan Minu One of the core developers of site on also known from from the AXML project I've been a Python developer since 2002 Kind of an active member of the Python community, especially the one in Deutschland Germany Yeah, and I'm working for Scooby together with Anton. Yeah, so I'm Anton. You see I'm also a Python developers That's my main job I'm also organizing Python DE so I'm using this as another chance to remind everyone that yes It does exist this year. It's in October. So go on by condo DE and see and come We are so happy to have everyone there And let me give a credit to the cool company where we're working on right now So Scooby is an ebook flat right ebook subscription service that operates for quite a while It has a coolest deal in Germany and it's available not only in Germany But worldwide we have a lot of books We have a decent Price of 999 per month and people love it because they put five star ratings to it That's of course Advertising but what is even more relevant today is that the stuff that we are showing you today is used in Scooby At least partially so we are Python based back-end we are developing it from Day-to-day on daily basis and the stuff that we are presenting you is tested in production. So yes Let's start About this talk, how will it be structured? So we start with the introduction to a sink. I owe just to have everyone on the same track What what is it about and what will be the examples about today? Then we will go to site on topic and have a brief examples of what is it about and how it does work? Then we will show you how to use that together and how you can benefit from them from that and we'll show you some practical examples Easy ones more more complicated ones, and then of course we will have cool questions from you. I hope so Good. So first a sink. I owe Hope you guys use the sink. I Think that yeah, we do not need to stop too much on that because it's such a busy topic, you know It's represented very great on this conference. So I Think we just have to go very briefly about it. So everyone is on the same track. So a sink. I owe It's finally finally a default tool in Python starting from 3.4, but back ported to 3.3 That we can use for the asynchronous network Communication it gives us tools that have been already available in different libraries. It was there forever and twisted It was there in tornado And there and there was a sink or as well, but they think here is sort of a common tool to do this sort of work I'll just switch to another notebook quickly to show you some Graphics at the background Just a very very brief recap. Why do we need this tool today? Why I was speaking about it. So Let's take a simple case of a synchronous processing of some requests. So Request on the left processing. So our back end is in the middle responses on the right. This is a time scale So time is going down. This is a traditional stuff that everyone was taught in the universities So we get the request. We are processing it. We throw the response out then we get the next request We process it. We throw the response out synchronous standard and simple More realistic cases though that we have more than one request coming During the processing of the of the first one and they just have to wait We receive through requests, but we can do just one task at a time. So we do it with our responses As we are completing our tasks time is going the same thing Then the deal about this thing is that most of the time at least in the iobound applications like most of the websites most of the web services most of the database Applications are just idling waiting for IO. So this time is something that our CPUs are wasting and we could save that If we could do other stuff in the meanwhile while we are waiting on the blocking resource So I mark here this blocks as waiting. Let's say the database some other external API whatever and The asynchronous execution model lets us to save this time by a switching between tasks So we have same three tasks one task two and tasks three But in this scenario we work on task one then we do blocking requests to the database and We can work on the other things in the meanwhile So we jump to the task two right away when task two is done It's a short one then we go back to task one because we got a reply from the database and we work on that And so on so we jump between tasks. That's how we can cut the idling and waiting on the IO And that's how we basically in most of the internet related applications can save on the total execution time of some tasks So what is the deal about I think your with this is first of all? It's an event loop known as reactor from twisted like 12 years ago was already there So again, it's nothing new. It's just a standard way to do that. What IO loop does is essentially it's It's a tool that is managing the network events and it knows which event is related to which code in our application So it will be remembering when data available on particular socket which piece of code should it call and then when the piece of code Gives the control back to the IO loop Then it decides also which piece of code should be executed next so it does this jumping between blocks of code And it does the callbacks Then another thing it finally gives us a common future class It's the same interface basically almost same interface as concurrent futures that we had before It's also pretty similar to tornado futures that we had and there are libraries that can convert one future into another So you can mix the frameworks And what is a future just a quick reminder? It's so it's called deferred and twisted the placeholder for some results of Probably network operation that is not available yet, but we'll be available soon We're using it as a link to the future result of some operation to not block and wait, but to do other things meanwhile and Finally a coroutines again, it's quite similar to coroutines that we had in tornado, but Not only the coroutine mechanic mechanics itself is updated, but also the declaration of coroutine is updated Starting from 3.5. So we can use a sink await. Oops a sink await syntax Instead of yield from syntax That is sort of pensier way to do that and Sight and supports it will have Deeper review of that How can we use that together soon? Let me just quickly finish with a single introduction first Yes, so coroutines as I said is based on the generators can be declared with the yield from syntax or with a sink depth syntax it's a Function or a generator that can be suspended and give the control to other coroutines in the meanwhile And very simple example that they show you just to get started is we use a new fancy Icing depth syntax we do some processing then we want to do the blocking operations. So we use a sink HTTP Clients to fetch something for us fetching is a blocking operation. So I think it should be client when we'll Return us a future not the real results. So we don't wait then we use a wait syntax or yield from syntax to Point the I loop that okay. This is something that we don't want to wait give control to other coroutines and just Resume this coroutine at this place when the result is ready on the socket And then when we have it we do more processing and return the result easy so finally we are getting closer to the To the thing that we will be showing you today about How can we go even further in optimizing our async your tasks? So on this graph what we are showing you is some front-end server that we have front-end Let's say it's just some piece of the software that accepts network connections and It gives the tasks to back-end Part that is doing some background processing for us I think you is running here on the front server It's getting request number one. It does some processing and then okay. We need Some data from the back-end. So we do request to back-end back-end does some processing Meanwhile, we have request to that is going to the front-end server It is started it is executed Then I think it gives control again to the request number one because this result is already available here What we see here is that even though request one has begun before request two it will only get response Afterwards so it was waiting longer than it could be waiting because the result from the back-end that we need Is already available here at this point But because there was request two coming in in the meanwhile and we have just one thread in which we execute everything We had to delay the processing of the request one even further It can get even worse if we have a request three So I think here decides which task should be done next and if at this point it decides, okay we have The request number three and we have data available from the back-end here which one should we do next it could decide Okay, let's work on the request three and then request one is delayed even further so even though coming in first it will be served last and This and some applications can be quite critical because we are not fair in the way. We are dealing client requests here and The most straightforward thing obviously what we can do is to make this time shorter So the shorter are the times that we need for processing some data The faster we can give responses and also The more flexible we are in switching between the tasks that we are currently executing So at this case by asserting the processing time on the I think your site twice We see that even even though the back-end could take the same time to give those data that we need even though we still are way better in Serving the front-end request because we are more efficient in switching between them and so our responses will be available faster and As you probably already guessed How can we reduce the latency how can we how can we process a sinker your tasks more efficiently is only only if we reduce the Task the time it takes to process every piece of the code that is there on a sinker your site It's not database because databases probably the blocking response that will be processed in some other place it is some Usually Python code that is taking time to be executed and here's the site and comes in Now let's step on give you introduction about site on and then we talk about how can we optimize a sinker your tasks with that Then give you ten minutes intro to sit on as a compiler in this language Well, sit on is a compiler. It's actually the most widely used static Python compiler out there It's been to the early days of site on when it was still called pyrex We're back in 2000 and sit on project itself started in 2007. So it's actually a very old piece of code It's nowadays it's a major part of the scientific Python ecosystem. So People are writing tools with it that allow you to do lots of number crunching Numbers I have sit on codes in a new code in it pandas for example Many many run our tools and data crunching tools are written in sit on and what it gives you is it's takes a piece of Python code or also a piece of Sight on code with which has an extended syntax and outputs the code from it generates the code which is compilable And this is the CPyton C API. So you get an extension module which you can import And then just use any other module in Python and said it sends the Python language whenever you want to do optimization optimize your code and Interact with external C code external C++ code It gives you that entirely for free because you know it compiles on to see if we're talking to see code is native and That's one of the cool features. It's open source. You can find it on site on word We are in GitHub. So if you have any cool ideas working better, just talk to us there So sit on in 10 minutes So I can see it all. That's cool Here's an ipython notebook or drip download book how you want to call it The first thing you would do is you would say a lot excited on that Adds the site on magic to the ipython notebook And allows it to execute the site on code directly. So it's a very interactive way to get a compiled code into your IPython notebook What am I using here? So I'm using Python 3.5 and the latest site on release Which I released a couple of days ago just for conference, so Then what you can do is you can take an ipython cell and say Actually, what I'm doing up to here is and This is just plain Python and I could just use a plain Python code and say please compile it for me But here I'm already using the extended site on syntax for this head for optimization for using C data types in Python code With siphon allows me to do So what's this doing? I have a little function at one which is you know takes a value at one to it I Do the same With two values some add two values x and y and here is already part of the syntax that you can see it allows you to allows me to declare the to declare C data types use C data types for my variables and Then what siphon will do is it's going to optimize the code for me Okay, so it sees this variable is actually a C integer so I can use native C operations on it And that's as fast as your processor goes As opposed to as fast as Python can deal with objects, which is way faster Okay So this is how the syntax looks like I can declare argument types I can declare variables with this C def statement So I have a global variable a here Which is also just a C and and then I'm using it in my function here adding it to very good x and since both x and a are C integers The ad operation will be run by a simple processor CPU ad operation. So that's You know add them to C and can be done directly in C Okay The nice thing is you don't have to care about these things like you just to carry variables and Siphon will generate efficiency code for you, which usually does the right thing There's a way for Helping you understand what Siphon makes of your code I'm not just saying your Siphon the Siphon cell I'm saying Siphon minus a which means annotate take my code and annotate it for me tell me what you think about it And this is what Siphon gives me Outputs a little piece of HTML and tells me okay This is what I've seen in your code and when I click on it. This is what I'm doing here So there are a couple of operations and here I'm seeing x is an object variable so the operation it does here is actually An operation a Python object operation and down here as I said It's taking two variables in C plus sign in here. So that's a direct C operation So you can click through the code see what gives you and then take that as a hint Way you have to touch your code. We have to optimize it What can change about it? Okay, so executing it some All works as expected I'm just getting the the functions as I would get them get them in Python I can just call them as they are and they get the right result Okay Functions so up to now I've only defined Python functions Python has a couple of more function types because when I'm interacting with C code is often necessary to Define C functions directly And so it allows you to that by saying C def in front of function sort of deaf and then what you get is a Plain C function a static C function, which can also pass around into C code as a call that for example Which is usually callable and so on so forth. So that's some it doesn't use Python call semantics anymore It's not an object. It's just a fancy That allows you to that but just you know in an exchange in death by C Okay, a couple more things So You can all do all this Also from a Python module you can just write plain Python code Instead of writing a set of module and you can say I take this function Compiled for me and then the compilation will actually have occur at import time It's gonna take the function Analyze the code for you compile for you and replace the function by a compile function Okay, so it's just Just decorated you can use it. It's kind of like did compilation in the sense that it's the compiling state of the body import time nice future Okay, how do you interact with C code so far you've only seen that you can use C see data types see variables in your code I'm here's an example for Using external C code what I'm doing here is I'm taking the math functions from lip see and I'm using them in my code So I'm taking the sign function for example. I'm using the declaration for pie Dividing pi by two taking the sign of it and printing it Okay, and this is often how a Python code actually looks like So there's some C code being involved some Python code some Python objects being there and you can really mix them freely as you see fit Okay, this is just you know use this use that it's it's all there for you at the commutates This is how Memory education next example you can use milk and free in in Scython They're just the usual The usual lip see functions that you can use here often people prefer to use Python memory allocation Instead because then you know the Python runtime knows about it understands it this is how you would do a memory education in Scython modules and It's it's just plain see functions. You can use them for me site encode The nice thing about it is that you can also pass C functions around you can obviously pass them around into C code And that you can also auto rep them to pass them into Python And this is what I'm doing here. I'm taking the mass sign function for example I'm just assigning it to a Python variable and then Scython goes. Okay. That's the C function In order to turn it into an object. I have to wrap it. So it wraps it for me And then makes it part of my my module API. Okay, so That's that means that I can now Call it directly from from my Python notebook so I can take that function here and Call directly into the lip see sign function through an object wrapper that Scython generated for me, but just, you know, doing an assignment Really nice feature Okay, here's a more involved example. He's a bit of Lua Lua integration. So Lua is a C implement runtime Program language if you don't know it And what I'm doing here is I'm taking a piece of code a piece of Lua code and Here in my Scython code, I'm You know, it started with a couple of declarations in order to use the Lua C API and then here I'm instantiating Lua runtime compiling the code I get Calling the code converting the The result arguments and then cleaning everything up One thing you can see here is I'm using try finally So this is exception base whenever something goes wrong. I just raise a Python exception Even though I'm you know, I'm beating to calling C code. I can do that at any time doesn't matter Even if you the trading the Lua runtime goes wrong I can just raise a memory error because the reason why that would go wrong is, you know, no memory And That's all I have to do so just a couple of functions I can call I can call them directly from my Scython code It looks a lot like Python except they're what I'm calling C code Okay, my Lua code I'm passing it into the function and It gives me the right results. It's just recursive for human achieve Calculation here. I can use timely to benchmark it Well, it looks kind of fast enough Okay So this is this is how I can talk to external C libraries Scython has wonderful integration with C data structures C data types It makes things a lot easier than if you know, if you were writing August and then see Who of you has been have been using C before in program and see Quite a number of people Do you love it? Yeah, okay So just a tiny bit more here So this is how Scython deals with C arrays You can do slice assignments. You can copy by value You can loop over them. So it's everything you would expect from Python just you know using C data structures and One last thing using C++ who's been using C++ a bit less than both you can see Now C++ has a reputation of being Kind of difficult to use language It's not from Scython. So if you look from Scython, it's actually very beautiful because you know, it's also object oriented So it feels a lot like Python When it's done the right way. So I really recommend using C++ from Scython rather than, you know, writing your application in C++ which is Which you can do but I wouldn't recommend that And this is an example of how you use a C++ vector from the standard library So I'm getting a couple of values in here as a tuple Assigning it to the C++ vector. Just copy over then I can do Indexing here normal Python indexing as you would expect. I can iterate over the vector Do intests? Pass the vector into some external C++ function and pass it back And the passing back a vector into Python Basically what it does is it just copies it into, you know, the obvious Python representation Which in this case is this. Okay, so it automatically copies it over so that you can pass it back as the expected Python result value. And this is how you use it. It has an arguments get in the back of this Okay, so that's like, well, Scython in 11 minutes. Okay Finally finally we have 15 minutes more to show you how it actually works together Let's get right into the code so First we just have a little little helper function that will run something for us with a sync.io We get the instance of the IO loop. We run a coroutine with that IO loop We return the result using just a helper method So to show you that coroutines that will be made with Scython are totally compatible with one that you would do in native normal Python Let's show me you let me show you the following example. So we use the fancy async depth syntax now and This is just a very very basic function that will add one to Something whatever you feed it in so you give the future in it will await for that future It will have result then it will say that It will print that result and just for us leave a remark that this was done with Scython And then it will return this result plus one then a Sync depth one will just return us one obviously, but we want it to be a coroutine. That's why we define it like this Showing you that it runs we Generate one then we add one and then we add one more. This is a The result that we see we printed one two and the output at the end is three. This is Scython the same thing but Now it's done in pure Python. The only difference in the is that I say here Python ads so that you see It's actually run with just Python Then you see that here in this example What I do is I generate number one Then I use the Python function add one and then I use the Scython function function add one And then I run it all on the IO loop and from prints We also see that the first one was executed with just Python the second one with Scython Which we could even not notice so it's totally easy to integrate. It's easy to mix You can write Scython then you can write in Python then you can call it one from another and it still works Next example just a simple ping-pong game. So we will make a function Coroutine in Python that will do ping and then we will do similar in Scython that brings Pong We will call them the Scython version so we use We do the first definition with Scython It's decrement by one function. We will have a map of coroutines. It's just some simple dictionaries that will say that First we have the Scython version then we have a Python version. It's actually a typo We pass this mapping in This condition is just not to print too much so to switch printing on and off based on the show variable We print Pong if it's a Scython coroutine and we print ping if it's a Python coroutine Let me just show you the second one then it's easier. Yes The same thing But now it prints ping Because it's the Python version the code is simple. You see we just pick the right Coroutine based on the current value and division by two if it's odds Then we do then we call one coroutine if it's even then another one Here you have the result ping-pong ping-pong ping-pong Scython Python Scython Python Scython Python easy But what for we did this talk at all is to see if it actually makes sense to mix them if it gives us any Advantage in the speed so now we will finally time it we Recall the same thing first. It's just a Python version. We see that The result is three four three ms Then we call the Scython version It's 183 ms, which is like double faster with no effort at all Let me just remind you what is the difference between two two functions Scython? Python difference is just this and we'd make it double as fast and then just to have it the third example is We mix it. So we use For odds numbers Scython for event numbers Python We time it and the result is somewhere in the middle. So it's It's actually not yeah, it's actually it's actually worse. Yes, let's just run it again Yeah, you also see that it's live. So now it's sort of in the middle now now. It's better. Yes Okay, now I have to run them all Otherwise you can think that we made it up Yeah, no, it's fast It's hell fast. Yeah. Yes. Yes. So you see it's still double faster It makes sense if it all all you need is just to put percent percent Scython and you get it double as fast Then it was it I guess his buzz example. I'm not sure if we have time for that We do okay, then go Does everyone know what the fifth bus game is? It's actually pretty simple. So it's just kind of a children game teaches division And you say number and if it's visible by three you say fizz if it's visible by five you say buzz and If it's visible by both then you say fizz was okay So that's what we implemented here Yeah, here is okay So what we get in is a stream of numbers. It's actually binary encoded numbers. So four bytes per integer As a network stream and so I'm just unpacking those Going through the numbers collecting my fizz bus values and then Okay, so a bit of overhead because I'm packing stuff here That's a Python implementation of the whole thing and what you can see down here is I'm running through the values I'm using the array object for I'm taking everything run through the values here Depending fizz bus fizz or the you know, if it's nothing not a fizz no bus then I just Take the original integer value and then I've called back which allows me to pass on the values Here you can see an async for loop which You know, it just continues running whenever there's data Really nifty feature of the new 492 pep the new async Async await pep The last to do data async data processing you just follow. Okay, really nice. So Next thing I'm going to do is I'm taking this code verbatim Lee Copying it into a Python into a Python cell. That was Python code. Just taking it. They are renaming it to you know, have two functions So I just run the Python version run the Python version and get compiled And then I'm setting up my my data stream here. It's just kind of a fake data stream that chunks Long long into the stream your chunks so that I can do You know loops processing Running that here I'm building my data stream. This is what I'm expecting for the first 18 values one two and then there's fizz buzz and so on and Yes, just to show you that it works works in both versions and Then here's a Performance comparison between the two and Calling the Python function calling the Python function and you can see what the performance difference is On the second version runs in seven milliseconds Pat version takes twice as long and then depending on chunk size The timing stiffer, but it's usually something like twice as fast just by compiling it. Okay Then the next thing I did was I rewrote the whole thing in a more, you know, see-ish way I'm iterating. I'm running through just the data buffer at a, you know, c-character level Here doing the same thing in a more see-ish way by just casting You know four bytes to an integer which is faster than During the array and the Python array conversion Yeah, so let's piece it up and when I run that thing Then What are getting comparison is? It's another I think it's another 40 times 40 percent faster here. Okay, so what again overall is Close to three times faster For the inversion, okay? Yep, and then we throw in the talk Yep, I think that it's a good time for questions. No, don't run Can you hear me? Oh, yeah, I was just wondering if you're using this at work and what you're doing with it If you're doing this technique at work and what you are actually doing with it You mean the using siton together with a sink I oh exactly Oh, we are using a sink. I oh there. We did not compile. I think yet siton pieces there, but We played with it to make this talk and it works That was more the idea of the talk right to convey that, you know speed is important when a marriage you can use Thanks Yeah question Am I right in thinking that this also works with Python 2.7? I mean if you use siton, yeah so the problem is the The as in depth syntax was only added in in Python 3.5 So it won't work with Python code, but inside of siton that she works. Yeah, that's the major selling point for me Maybe you didn't So just one more question Can you tell me about numpy integration? Can I use this to cast a numpy arrays? How well does that work with siton? So the question was how well numpy is integrated with siton Extremely well like everyone uses it I said siton is used a lot in scientific Python And we have special syntax in siton that allows you to say this You know data buffer, this is how it looks like and then you can just iterate over it run through it as fast as Your processor can and so it's yeah, it's one of the main use cases for siton. Yes All right Are these I think our features in siton already ready for production or is it like experimental features? Like in beta or something So the async async await support in siton was developed at the same time as the Python support for async in the wait There were a couple of changes recently which we followed But they're at the same level now so they work equally well and The fun thing is they actually influence each other So while the Python support was being developed we developed our siton support And so we had an impact on how they did it and they Changed how we did it and so that both Improved by by working together I Have a little final note that if you have any interest in getting more Into detail of siton or of async you separately you are very welcome to the trainings That are tomorrow and the day after tomorrow that will cover these two topics really in detail Time for one last question Thanks Thanks for the talk. I was just wondering if if siton could take advantage of the Python 3 type hints in order to compile Yeah, so that's a big topic. We were actually so I discussed that with You know a couple of times and the intention of the Python type hints is Not really something that's meant for steady compilation and it doesn't really help us So it's it's meant for type checking for annotating API's for making them machine understandable basically But it does not help in compilation and that's why we're not currently using making any use of it Thank you very much. That's the last of the questions