 What I am saying is that VetaFM is one usage model which works with people like me, but there is a lot of application, especially if it is written in Belgian rules, then you want to be streaming. I am going to talk about MySQL.jl. MySQL.jl is a Julia package which lets you execute SQL commands from Julia. So the objective here is to talk about three things. MySQL.jl usage. It is a really simple API. It is not much to talk about it. So I thought of adding a little bit about a simplification and some things that might not be really talked about in the Julia world. So the second thing I am going to talk about is the Julia C interface. And the last thing I am going to close with is the Pro-In performance. So you might think why you would want to bother with the Julia C interface as, say, a data scientist or someone working at the high level. I think there is a lot of code written in, already written in C over the decades. And this Julia C interface lets you call Julia or get data from Julia and I am going to talk about how to get it as a Julia data structure, like, say, and add it. So I think that is a useful thing to know because you can write packages in a few lines of code and do a lot of things by just calling Julia. This is a basic API of MySQL.jl. There are some more functions which are not going to talk about this for the interest of time. So you include the package by, say, using MySQL and you connect by saying MySQL connect followed by the APIs. The usual thing, username, password and dvname. And it returns to you a MySQL context which you can use in your other MySQL function. So this is a wrapper, a handy wrapper called MySQL execute query. It pretty much does everything that you need. If you pass it a select statement, it returns data frame. If you pass it some, say, an update statement, it will tell you how many affected rows you have affected. Suppose you don't want the output to be a data frame, you can specify it with the third argument, saying MySQL array and you get it as an array of arrays like this. You can also go through each row of the table using an iterator, using a first loop like this. So you say MySQL row iterator and you pass it the results and you will print. I'm printing each row here. I'm iterating through each row and printing. The MySQL APIs that I've written have not really put an error check because that would be an overhead, if you're calling it, say, 10,000 times or something. But if you want to check for error, you call MySQL display error and you pass it the response that is given back by any of the MySQL APIs. And this error you see here, that's from MySQL, not from Julia. The rest is a status or whatever from Julia, but that is from MySQL, saying that some table doesn't exist. And you disconnect by saying MySQL disconnect. So that's the basic API. Okay, so now I'm going to talk about the Julia C interface. I think the Julia C interface is really simple and easy to use. So we'll see. Suppose you have a C function. This is MySQL query in C and I had to write a wrapper for this in Julia. So a function has three parts. It has a name. It has a return type and it has some arguments. So how do I write this in Julia? How do I call this in Julia? It's real simple. So there's a C function there and the Julia code is here. So if you keep looking back and forth, you'll see this is a return type here. The arguments are here and the function here is here. But you have to also tell from which wrapper you got that function here. So there's a string here. This is actually a string. It's assigned to a variable. And it's basically my SQL. And then you pass it to the arguments. So this becomes a wrapper. So now you're... Yeah, let me see what happens. Okay. This isn't the most simplest and best example. I should have just made sure and printed it out for something. But I want to do something from the MySQL code itself. So that's about functions. Now how do you deal with C data types? Like you have C data and you want to read it as a Julia area. You want Julia to understand it or you want the other way around. You have some Julia data and you want C to understand it. So let's say you have something like this. It's a simple pointer to a pointer in C. So it's basically saying this name here should represent this. Cache star star. And that's my SQL role. That's how each row in MySQL is written actually. So in Julia, that would be simple. Just replace the stars with pointer. And title becomes title is and you have MySQL row, pointer, pointer, and C cache. It's as simple as that. If you have a struct like this, what do you do? Okay, we'll just see. So if you keep looking back and forth, you'll see a pattern, right? So you'll see that a star becomes pointer and it's a pointer to itself. So you have the same thing there. And then we've just declared this in that type in this thing. And then unsigned long becomes Cu long. So the same way float becomes Cu, double becomes C, double becomes C, and unsigned becomes Cu, and so on. So I have a bunch of question and answer kind of things, so we'll just see them quickly. So let's see, now, a C function give me a pointer, how do I get a Julia array from it? It's a pointer, right? An array in C is a pointer, how do I get a Julia array from it? So I have a pointer here, that's a C pointer there, a 64 bit integer. So all I have to do is say pointer to array, and then I have to give the length. So the C just gives you a pointer and usually the C appears to give you a length. And then you're getting a string which is null terminated. If you're getting a bunch of numbers, you need to know that. So this pointer give me back a Julia array and it's one, two, three. It's just an array of one, two, three. Another question, how do I do this? How do I go from, how do I get a C pointer from a Julia array? I have a Julia array, how do I get C pointer? This is really simple, all you have to do is call pointer under array, that's it. Pointer A, that's it. So this is just an example from the MySQL code. So this C call here, this has a C call inside of it. And it requires a pointer to the MySQL bind. It's going to bind the results there, it's going to put the results there. So this is how the prepared statements work. So what I'm doing is I'm just calling pointer, that's it. Just pass it there, and it works. Okay, another question, C gave me a pointer of type wide. How do I get a floating point value from it? So C uses wide for its genericness or whatever, point to anything. So this is a wide pointer. All you have to say is reinterpret, that's a very well-named function. Say reinterpret pointer float and I get a float pointer. Okay, so I now have a float pointer, how do I get a float value from it? I say unsafe float. I say float is like saying star variable in C, like dereferencing. So anything, any dereferencing in C is unsafe. So that's not like a limitation or anything, it's just saying that it's unsafe. Julia won't know about it in a way. Okay, this is something, I just want this interesting, so I'll just put this here. This is from the Modbus, while I was working on Modbus. So which is just all the device thing in the floating thing. So the API there, it gives you a floating point number. But it gives it to you like this, just gives you bits, just gives you an unsafe bit. How do you get that into a floating point number, right? So if I just say float of that, if this was 12, and if I say float of that, it's going to give me 12.0, that's it. I don't want that, I want it to be decoded into a floating point number. So how do I do that is Julia, it's really simple. All I say is reinterpret C float and that number and it gives me 3.14. And that's 3.14 in the IEEE format in binary, if you can't know the difference. Okay, the last one. So you know how C frees memory, right? So C frees memory, C doesn't frees memory, it doesn't have a GC, a garbage card, you have to free it yourself. So if a C call you call allocated some memory, Julia doesn't know about it. So how will Julia garbage query, it won't actually. But you can make a garbage query, you don't have to free it yourself. So the way you do it is it's really simple. Although this looks a little big, but it's really simple. You call finalizer and you pass it. This is available to which you assign whatever you've allocated. And you say, when Julia is going to garbage collect this, also call this. Also call this C call. So this is freeing this result. So I can't just wait C call because there will be a call instantly. I don't want to call it now. I want to call it, this is a basic syntax for an anonymous function. I don't think. So I want to call it when the GC kicks in. The GC kicks in and says, our result is out of scope, you don't know how we're using it, I'm going to clean it up. So while we're cleaning it up, also call this so that whatever memory C has allocated clears up. Okay, that's all. I'm just going to quickly go over the performance. Okay, why performance first of all? So what we usually do, what some software developers usually do is make a prototype in Ruby or Python, and then decide it's too slow and make the production version that says C++ because it's faster, the type is more static or whatever. So how to deal with performance? Okay, I'll just finish this here. So when you're dealing with performance, the first question you have to ask is what should I improve? What parts of my code are taking the most amount of time? How do you find out which part of the code is taking the most amount of time? So there are tools for doing this. There's the macro at time, there's profile view, and that is in. I'm just going to show some screenshots about that. So this MySQL is a good query. When you pass it like a small table like this, it actually does some work converting it into a data field. And that's the thing that takes time. And that's what we're trying to optimize. So what we do is we give it like a 10,000 UI because performance is most effective at scale. So at scale, we found it took some five seconds or something. And then we looked into where we could improve. And I'm going to show you how to improve that. I'm going to get to that. So basically at time, it gives you time. It gives you how much memory is allocated. And over here, it tells you how much GC has happened. Really, no GC is happening because we've removed all that. But if you have a 20% GC, then you're doing really bad. This is another tool called ProfileView. Each further represents a function. This function is calling. This function is calling. This function is calling that way, like a stack. And the horizontal length represents how much time it took. And if you hover your mouse over it, actually, it's a big image showing all the functions in your code. But I'll just show the screenshot so that you can see the mouse pointer and it's telling which function this thing represents. This is a tool. It just shows you how bad of a programmer you are, I guess. So if this tells you, like, if you see here, I'm assigning a 64-bit int value to an ascending int, which could potentially be a big bug. So it finds a problem like this. And this is typical of what GCC would send you. It would tell you, you have a variable, Iter, would not even use it that way. So OK, how do we code faster? Just say one minute on this. Similarly, just use constant in front of your global variables and you'll make it faster. OK, another difference. So Julia has concrete types and it has abstract types. Abstract types are polymorphisms, like decided-at-run type. And that takes more time. So if you know the type beforehand, you can mention it to Julia. You don't have to say, I could write any here. And I would say array of any. But if I give it a concrete type like this, it will work faster. Plus you can also initialize memory for the array. How long do you want the array to be? Instead of pushing to an array, as if it was a queue. And another thing, OK, what is this? So here I'm just saying assign to this a 0 of type this. But if I just say 0, assign a basic int 0 to it. And somewhere I assign a unit and the type changes. So one thing is avoid changing types in Julia. If you want avoid changing types, you have great things like this. I sort of think, you can just Google performance tips in Julia and I'll take you to the read the docs page. And then you can read more about this. We have a question. OK, I spoke about all that. OK, in conclusion, although this was a my secret talk, the conclusion is not related to this. The conclusion is, in Julia, you can do high-level programming. You can do data science and all that stuff. Everyone knows about that. But also what you can do is you can interact easily with C. And you can improve performance without having to re-implement your code in lower-level language. That's all. Thank you. We'll take one question where the next speaker sets up, who is not on the list. So you talked about specifying the type. So for functions that do multiple dispatch, is there a performance impact if you specify the type or not? When you do a bunch of dispatch, you usually mention the type. You've written the function once, and you want it to. When you write the function, if I don't declare the type of the arguments, when it does the multiple dispatch, it figures out the types that are given that it is compiled. If a difference happens, then it's compiled. I'd compile. So there is no, it's not slower. It's not slower. OK, great. Thank you, sir.