Welcome back, in the previous segment we looked at how to solve GCD using brute force search. We said that this is slower than Euclid's algorithm, but we said that brute force search will be useful if we do not have clever algorithms for some problem provided the number of possible candidate solutions that we need to consider are finite in number. Now we are going to take another example of this and this example is finding Pythagorean triples. So the problem as we discussed is find x, y, z such that x squared plus y squared equal to z squared and z is smaller than 20 and of course x, y, z are positive integers. The idea we mentioned was that let us try out all possible triples x, y, z where x, y, z lie between 1 and 20. So how do you generate such triples? That is the natural question and that is actually very easily done. So we are going to have a loop which is going to be, which is going to have a control variable or index variable x which will go between 1 and 20. Nested inside that will have a loop with control variable 1, control variable y which will go between 1 and 20 as well and then will have a loop with control variable z again ranging between 1 and 20. So now whatever we put over here we can use the variables x, y, z and in different iterations they will assume all the possible 8000 triples of the form x, y, z where x, y, z are integers between 1 and 20. So if you want to check for all possible triples the check has to be put over here and that is the check. We want to know whether x squared plus y squared is equal to z squared and if it is we want to print out that triple. So that is it, that is the program. So let me show you a demo of it. I have called it knife Pythagoras.cpp and you will see the reason for it. So this is our program exactly what we had written earlier. So let me compile and run it. So it has printed all the triples. Let me move it out a little. It has printed all the triples 3, 4, 5, 4, 3, 5, 5, 12, 13. These are all the triples that it found satisfied the property that the sum of the first number squared plus the second number squared equals the third number squared. You can check it out. So first of course we have the familiar triple 3 squared plus 4 squared equal to 5 squared. Now is this a satisfactory list? Well it is not. Why? Because this triple and this triple we would like to think of as the same triple.  I know I mean these numbers the order is not really important in these numbers. So and of course that has happened in many places. So 8, 15, 17 is there, 15, 8, 17 is there. So the question is can we avoid this and yes we can and we are going to do that in just a minute. So we are going to look at this problem again and make a modification which will allow us to generate similar triples only once. So this is our problem again and this was our idea and this was our problem. So we want 3, 4, 5 to be printed and not 4, 3, 5 or maybe the other way around but we could say that look why do not we print this in ascending order rather than this looks a little funny. So we only want one of these things to be printed. So how can we enforce that? Well here is the idea. So in addition to the constraints which are already there in the problem we will additionally assert that x should be less than y. What does this do? So this will allow this solution because this is x and this is y and x is indeed less than y but this solution will be avoided because this is not less than this. So that is the idea. So we are going to have the previous program but in the previous program we are somehow going to enforce the condition that x is less than y. There are various ways of enforcing this condition but we are going to pick a particularly nice one. And by the way note that x equal to y does not have to be considered. Why? Because if we look at x squared plus y squared then that if they are equal would be 2 times x squared and that cannot be a perfect square. So it cannot equal any z squared. So x equal to y does not have to be considered. We do not want x greater than y and therefore we should only be asserting x less than y. And in fact you can see that the conditions really could be something like this because we know we are asserting that y is bigger than x and of course z has to be bigger than y because its square is strictly more than the square of y and x. So let us see how we can assert these conditions somewhat indirectly. So let us look at the code. So here is the code. So the first loop is exactly as before. x goes from 1 to 20. The next loop however has y skipping all the values including whatever the value x is currently taking and smaller values. So x, so y only starts at x plus 1 and it goes on till 20. And z similarly skips all the even all the smaller values because we know that z has to be bigger than y and so it starts off at y plus 1 and goes on till 20. And the condition is still the same. If x squared plus y squared equal to z squared then we print it out. So let us see this. So let us compile it and run it. So that is it. It has indeed done the right thing. It has printed every triple just once and so 345 is printed as 345 but not as 435 which was happening earlier. So let us get back to our presentation. So I want to give you some exercises. So the first exercise is dealing with something called perfect numbers. A number is said to be perfect if it is the sum of all its divisors smaller than itself. So 6 for example has divisors 1, 2, 3 smaller than itself and 6 is indeed the sum of those divisors. So therefore 6 is said to be perfect. The problem that I am asking you to write a program for is to find or print all the perfect numbers between say 1 and 10,000. So you have to go through all the numbers between 1 and 10,000 and check if they are perfect and if you find that a particular number is perfect just print it. A harder exercise relates to something that the famous mathematician Raman Rishan is supposed to have said. So he said sometime that 1729 is the smallest number that can be expressed as sum of cubes of 2 integers in 2 ways. In particular 1 cube plus 12 cube is 1729 because 1 cube is 1, 12 cube is 1728, 9 cube is 729 and 10 cube is 1000 and therefore 9 cube plus 10 cube is also 1729. So this is an interesting fact and you may wonder, suppose I did not know this, could I have figured it out. So that is where whatever problem is going to be about. So I am going to assume that suppose you did not know this and you were told however that such a number exists and is smaller than 2000. Can you find it? And in fact you could ask look I want the smallest such number. So that is the problem. So write a program which finds the smallest number and you know and assume you are assuming that it is smaller than 2000. So the smallest numbers which can be expressed as sum of cubes of 2 integers in 2 different ways. So you are expected to do brute force search. So you will have to figure out exactly how to organize that brute force search. So you have to express it as a constraint satisfaction problem. So think about it, it will as I said it is a slightly harder exercise. So the number that you want to find is certainly one of the variables that you want but what about those numbers 1 cube, 12 cube, 9 cube, 10 cube. So how do we exactly get them into our constraints? So that is what you need to figure out. I want to list out an even harder exercise but which may challenge some of you and which some of you may like and this is the so called 8 queens problem. So this problem asks you to place 8 queens on a chessboard such that no queen captures another. So for those of you who do not know chess here is a quick explanation. A chessboard has 64 squares arranged in 8 rows and 8 columns. So it looks like this. So there are going to be 8 rows and 8 columns. Whatever, this is not 8 but there should be 8 rows and 8 columns. So how many is this? 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6. So if you had 7 and 8 and 7 and 8 then it would be a chessboard. Now that is what a chessboard is and this says if 2 queens are in the same row or in the same column then they will capture each other.  So if you place a queen over here then you should not be placing a queen over here. That is what the constraint tells you. And similarly if you place a queen over here you cannot be placing a queen in any square in the same row. So you cannot place a queen over here because they would capture each other and you want to place queens such that they do not capture each other. But this is not the only way queens capture each other. So queens capture each other even if they are sort of in the same diagonal or since the notion of diagonal only refers to the principal diagonal which is from corner to corner we can say the same thing in a different manner. So suppose there are two queens so these two queens and if you draw the line joining them then this line is at 45 degrees angle with respect to the rows and the columns. So even then they can capture each other. So this is also not allowed. So for example you could have placed if you want to place three queens you could place one over here, another one over here, a third one over here maybe. So now no queen is capturing each other maybe even a fourth one over here. So in this manner you could have placed the queens. And it turns out that in this case you can place the sixth queen over here. So you have placed six queens on a 6 by 6 chessboard. But you want to do this on an 8 by 8 chessboard. Well that is the original problem but we do not want to get carried away with having too many variables and writing too much code and in particular the spirit of the problem is still the same even if you are looking at a 4 by 4 board. So if you want to place four queens on a 4 by 4 board how will you do it? You want to write a program which will do it for you. So basically the idea is that you try out all possible placements of the queens on the board. So you will have to figure out how do you represent this problem using numbers. And suppose you say that this queen is placed on this square and this queen is other queen is placed on this square. What does it mean for the queens to not capture each other or capture each other? So the constraints here are expressed in terms of this geometry but you have to get them into arithmetic. So you want the constraints to be in terms of numbers. So that is what makes this exercise harder. But once you do that again after that you are not expected to be clever. After that you are just supposed to try out all possible ways of placing the queens. All right. So what did we discuss in this segment? Well these two segments actually. So what we discussed was that for many problems we may not know any clever ways of solving them. But if there are only a candidate, only a finite number of candidate solutions then we can go through them systematically. We can check which candidate solutions satisfy, candidate solution satisfies all constraints and we report that as the real solution. This can take very long but it is better than not having an algorithm. But of course there is room for cleverness.  And notice by the way that that actually also reduces the amount of searching we have to do. So any kind of cleverness that we are capable of in reducing the number of possibilities always helps. It allows you to solve bigger problems in the same amount of time. So that finishes this topic of brute force search and now I am going to take a break and after the break we will discuss how to write programs that model a physical system.


Okay, so I'm I'm Jordan Tigani. I'm software engineer working on on big query It's big query is a tool for for data analysis Some mode of map reduces a tool for for data processing It's based on some internal tools that we built over the years at at Google and So before I get too far into what what big query is I just want to talk for a second about you know, what what is big data? I assume that since Since we're at a big data conference everybody has some idea of what big data is But I think one of the things that I found is that for Everybody has a different opinion of what of what big data means at Google at Google, you know, we've got You know Gmail users in the hundreds of millions The metadata about those users Their emails etc. I mean that's a lot. That's a lot of data and we sort of Tend to talk about okay, it's starting to get big when you have a billion rows or when you have a terabyte of data For other people it's it means something different if you're doing machine learning and you've got a million rows You may you know that may be that may be big data that may be more more data than you can handle So I think big data is not really just about about the size of the data that you have It's more about do you have a problem with your data? Do you have a problem? Scaling is your is your is your architecture working with that with the size of data that you have and so You know, I think of big data also as as as problems and so you might have a big data problem if For example, you have data coming in faster than you can you can process it you may have 10 gigabytes 10 megabytes of data But it's coming in so fast that you can't you can't write it out to your to your data store fast enough or You know conversely or in a related related way if if you're growing 10% a week You may only have a small amount of data now But you want to plan for when you are two to three orders of magnitude larger Maybe you are waiting to sign a big customer and they're going to you know use You know cause you to go up by tours of magnitude the amount of the amount of data you're processing That's still a big data problem Or sometimes just data architectures make it hard to scale You know if you have a single monolithic database that you're relying on for all your all your your analysis It's it can be difficult to to to shard that into multiple pieces And if you shard it into multiple pieces then you can't do the same joins your that you had been doing before So You know architecture is very closely tied to to to to big data and what what big data means Sometimes it's just a question of cost if you if you've got a mysql instance or if you've got a sequel server instance And you need twice the capacity you might have to go away from commodity hardware And you might have to buy some big iron machine and and your costs will go up by by 10x and the cost could be Cost of physical machines cost of developer time cost of cloud time, etc And I think one of the big the goals of big data is that when you is that cost should be proportional If you double your data size you want to roughly double double your cost You don't want to have to go up go up 10x or come up with a different architecture and You know you think about sort of the old the old model where you had a single server and all your data Lived on that server and you're querying on that server and that was your database server, etc You know clearly that has that has has some scaling limitations and sort of the big data era is the era of You've got giant data centers with commodity machines You want to be able to just plug in a new machine plug in you know an additional node when When when your data size increases and maybe you're physically doing or maybe you're doing it via You know some some sort of cloud offering So big data I think is about scaling out and not not scaling up So for Google from a very early Very early on we recognize the the need to to scale out and all of our Algorithms and architectures are essentially scale out architectures the the the founders and the initial people at Google They didn't want to buy a million dollar database machine. They wanted to buy $25,000 database machines and You figure out in software how you can make the the 20 Inexpensive machines act like your your million dollar your million dollar machine because Then when you go from then when you need to scale again, you don't want to have to buy a $10 million machine You can just buy buy more of these Commodity machines And to give an idea of just some of the scale that we have, you know, Google Google gets 72 hours of YouTube videos every minute and the the Google search index is As of a couple of years ago the caffeine search index is a hundred million gigabytes. That's that's a lot of data if you're doing Analysis, you know, you're not going to be able to process that on a single machine no matter how big that machine is and so big query the product that I that I like to talk about it sort of and Based on the internal tool called Dremel and it came out of a need came out of a big data problem where we had a lot of data and We wanted to be able to ask questions of the data and some of those questions, you know Maybe this is the same question we ask every day It's like how how are things changing, but maybe it's a question We've never wanted to ask before like, you know, is our is our product strategy kicking ass or not and The other thing is we want to be able to get results back quickly We don't want to have to wait for, you know, 10 minutes for a for a map reduce to run We want to be able to just interactively ask ask questions about our data and You know as a sequel databases traditional sequel databases, especially ones that let you do analytics. They don't scale out, you know, they're they're sort of it's an open research problem and To make to make normal sequel architectures scale out But as you've seen, you know throughout some of these talks is is some of the traditional databases Don't do well when you start adding adding nodes and when and some of the no sequel databases I mean the the no sequel is you don't get you don't get sequel. You can't ask the same kind of sequel queries You can't ask the same kind of questions you can from a traditional relational database You know once you have big data Doing doing scans over all that data is going to is going to take a long time and we're we want to We want we want to be able to parallelize things So Google built a technology called Dremel and it scales to thousands of nodes the the VP of infrastructure at Google was recently quoted saying you can You can do non-trivial queries over a petabyte of data and you can get results back in order 10 seconds the the the particular clusters that we have Provision for big query are slightly smaller than that if you need that kind of performance You know, we'd be happy to have you come talk to us and we'll we'll build you that that cluster but Just to give you an idea of how how fast how fast it is Don't you don't have to just take my word for it So this is this is a data set that we have that's every Every page in Wikipedia Every every day it records the number of the number of hits the number of web hits that it got And so what I want to do is I'm going to do a query How well can you see this so a query? to find Which were the Which were the pages that got the most they got the most hits that were in Spanish And they have this they match this funky regular expression so this is the kind of thing you just can't do on a on a on a relational database because You know, you'd need an you'd need an index Of this data and to be able to do a regular expression over over every single entry in that in that In that database would just be prohibitively expensive and so we can we can do this. This is This is a lot of data and it's going to take It's going to take a few seconds And so by the way, this is this is the big query web web UI which is the our external version of Dremel that people can The third-party customer people like you hopefully can can can check out and try and and run over your data set so so this is 22 seconds and we just ran over ran this regular expression over over 611 gigabytes of data So hopefully you find that fast if you don't find that fast then Then you have a different idea of a fast so And a lot of people ask us well, why don't you just use MapReduce, you know MapReduce is a fantastic technology It's used Thousands of times a day at Google very very Google's very heavily heavy user of MapReduce they Arguably invented it Arguably discovered it For uses in big data, and so I just want to talk about why MapReduce doesn't doesn't work so well for these types of things So in a MapReduce, you generally have a master that's that sort of kicked off to to run Whatever processing you're doing and the master launches some some mappers and Allocates those mappers sometimes, you know may even boot additional machines and Then mappers will will read the data from read data from distributed storage process that data and write it back out There's a step that people don't usually talk about in MapReduce And it's often the kicker because it's the slowest which it's shuffle So it's map shuffle reduce and shuffle is how you know how to send the data to the to the reducers so it's essentially an on-disk sort and And finally there's a reducer Which is going to compute the the final the final outcome each of these things is going through through Distributive storage, which is essentially writing it writing it out to disk. There's a couple of you know map bar has a has sort of an in-memory very high performance Shuffle stage, but you know, it essentially these are tweaks around the edges You know MapReduce is is just designed for for batch processing And the next thing about about MapReduce is that many of the interesting questions that you want to ask Can't be done in a single map and reduce phase a map and reduces It's pretty limited and so you're often going to have to do multiple stages of these of these map maps and reduces So to compare the two you know MapReduce is for essentially for batch processing Dremel slash BigQuery You know, it's optimized the architecture is optimized to to get answers quickly With low latency for for sequel type queries and I'll show a little bit about how that how that works Dremel is built as a as a tree tree structured at the bottom you have the same distributed storage level that you did in in In for MapReduce is although it tends to be stored they just tend to be stored in column format and the column format is key because You know, you may have a very wide table. You may have a thousand columns in your table If you're only doing a query over two columns, then you don't you don't need to read read everything It has The bottom of the tree is is leaves and leaves are sort of like the MapReduce workers But it's a long search. It's a long live tree So you don't have to spin something up new every time and the the connections between The leaves and the and the sort of the next higher nodes, which we call mixers These are network very fast network connections. So you don't have to write things to disk You're sort of doing the the reducing and sorting by a By pre assigning them to to the leaves to mixers and if if that's a little bit hand-wavy I'll gonna go quickly into into one example of a Of a dremel query. So this we have a we have a public data set that has every baby born in the United States for 50 years and Has a bunch of sort of demographic information about about the the baby and and the and the parents, etc And so this is this is a query that will compute the the years when the most The most babies were born to mothers over 30 And so we see the same the same dremel the same dremel tree here and we'll start from the bottom because the query is sort of rewritten as it goes down and Usually usually simplified so at the very at the very base level. We're just going to Take the mother age and year so even though we have a lot of a lot of columns we only need to read read those those two and it's essentially just a sequel query Into the leaves then the leaves compute a compute the count Themselves and and the group by and so since we have a 50 years of data in this in this data set They're gonna return essentially 50 50 50 values back up the tree so the mixer is going to Is going to continue to aggregate those and notice it doesn't have to do the filtering anymore You know where the mother age is greater than 30 because that's already already been done and finally the root the root of the tree is going to apply our limit query and and And also sort we want to because we want to we want to find the ones that had the the highest number of Babies in that year so that's essentially how dremel works if anybody has any more questions about about specifics or things that I can You know, I can tell you a lot about it because we published a paper on it But I'd happy to talk to talk afterwards So this is great, you know big query is something that we can use that at Google But hopefully you may want to know how can how can you use big query? So it's just it's just a web API You can send it's a restful API restful as a buzzword for being able to do simple HTTP operations on it you know you can You know HTTP get to read a table HTTP post to insert a insert a query job or insert a load job And the way you generally get your data into big query is you have your data in multiple pieces It can be in CSV format and JSON format you upload it into Google Cloud storage Which has a very very fat pipe from the from the the internet And then you run an import job that'll run That'll import it into to big query And what does this look like? It's a it's a JSON post request to to a big query URL. You can see the first part is just sort of the the the big query endpoint projects so every Everything in big query sort of the root of all namespaces are projects and projects you might think of as your company Or maybe it's a sub project within that company You know say you're doing you're working on some some project And and your your namespace is it's sort of private within that within that project, but you can see that You give it the source URI where it came from and you give it You know the name of the table that you're creating and and some and the schema some some minor information and and that's all that's all you need to do and Kind of to show what that looks like So this is the the Chrome developer console you probably can't see that too well. I guess it's not so bad It's So everything the big query UI does actually goes through the public API So you can you can use the the Chrome developer console to actually see what gets what gets sent and here We can see the request payload Basically just sends the same the same data that I that I that I mentioned before and this is creating a table named You know food art bar with some with some simple simple fields that I imported from From a CSV file I had in my Google storage bucket Okay, so running a query is actually very similar similar A load is a job load is the type of job a query is also another type of job And so you just you give it a very similar payload although obviously instead of specifying the schema and And the the Google storage location you specify the the query that you that you want to actually run If that seems a little bit confusing or difficult Most people don't need to actually operate at that at that wire level. There's a bunch of of Public publicly available libraries for you know virtually any language that you you may want to be coding in That that makes it easy to to connect I'll show an example of so in in JavaScript You know you you basically just There's a query query object and then a request object and you can you can execute it It's pretty it's pretty straightforward a straightforward as JavaScript can be So I wanted to do a couple of quick demos to kind of show show big query in use and So the big query team uses big query a lot Just to understand or to understand our service and to to debug our service And so I thought this might be a good way to to show you okay, so we're actually we're running a production service And how can big query be be useful to to do that? So what we do is we we load We load the big query jobs table into Big query jobs database table into a big query table approximately every hour, so we snapshot it every hour and And you can see the schema here and a lot of these schema fields are the exact same fields as you saw in that in the In those those job Objects that I was that I was showing that are posted. So there's configuration query query And so this is a nested nested data structure and so from this we can run any big query queries that we that we would want to do over that and so one one thing that we often want to do is Is to debug problems that people are having so the the big query Health forum is on is on stack overflow and sometimes people will ask us questions and they'll only you don't need to read this This is just sort of a It's just and someone was hitting an error and the errors indicated that it was unexpected error turned translates into an internal error on our side and often the information that people give us is not always enough to Diagnose the problem easily Maybe they'll send us their query, but it'll be only part of the query or they'll send You know a reduced query, and we want to see what they're actually what they're actually running And so what we can do is So I want to run a query over our jobs that that basically has this sort of This phrase that I picked out of their out of their query Which is probably right even that even if they didn't even if they had redacted it a little bit And I want to say that the the result error was you know internal error And I want to capture a bunch of a bunch of fields so I get the job with a job ID I can look through our server logs the debug info captures our stack trace and I'm gonna I truncate the stack the stack trace because Because You know there's some sort of things that we don't necessarily want to show and we don't actually show our whole our whole stack trace But you can you can see that so these queries are very fast We call these sort of spearfishing you know you're looking for a particular particular thing and you know you know some information And you're looking for essentially one thing so we've also ordered these by time So so the most recent ones show up first and we can we see that the the debug info is you know unexpected Dremel error And that that gives us sort of if I show the rest of that debug info that that'll show a lot more information about About what actually happened and you can also see the query that was run We can see you know we capture a bunch of a bunch of interesting things So in addition to spearfishing there's often you just want to ask questions about the health of your data the health of your service So sometimes we want to know How long are these Dremel queries taking and so there's a quanta so Average is a bad is a bad number to use because Average is very heavy heavily dominated by large values you know if you get a hundred people in a room and one of those people is Bill Gates and you compute their average net worth then Then that's going to be a much higher number than then Possibly it should be and so big BigQuery has a quantiles function Which is essentially percentiles or it enables you to to compute the median is the 50th percentile You can compute like the 90th percentile and so we just want to see how long are these big query queries taking And you know so what's the what's the median? What's the 90th percentile and so we can see that okay, so 9% of them finish within these are in milliseconds so within 1.5 milliseconds And I've lost the edge of this Come on. There we go So if I keep scrolling through the 50th percentile so half of the query is finished in less than 777 milliseconds and previous so the 90th percentile is You know is on under 10 seconds so 90% of queries finished in under under 10 seconds There's a lot more interesting things that we can do of like counting users and counting jobs and counting revenue growth But you know some of those are sensitive internal things So I would probably get in trouble if I started if I started showing those to you So, you know once you Once you're able to to get these answers the next thing you might want to do is Is figure out you know is actually Visualize them or put them in a pretty Chart that you can that you can look at so You know Google's got a charting API and so actually in in the BigQuery team we built a Built a dashboard and this dashboard This is a stripped-down version of it, but it's you know, it's just a simple app engine app that calls into into big query and Hopefully we can get this to resize correctly And we add queries to this to this dashboard that are run that are run periodically so we can see So we can see this is average import size So we can see you know over time how does the The number of files that people are using the number of megabytes of of their import and average records How do those how do those change and if you look down here? We can actually see this is the actual big query query that that was run You could cut and paste this into the into the big query browser tool and and run that to get that in or to tweak it This is the this is the query. I just showed you the the query time quantiles percentiles you can see how how non-linear it is there's there's some you know some people run very very Complicated queries that are that are very expensive Whereas most of them happen in in under a second And again, here's the this is this is the exact query. I just I just ran And so this this app engine this app engine app is has been released publicly As a public sample so people can can try it and and and tweak it There are some other ways to use to use big query So big query via app script is is integrated with Google spreadsheets So I'm not going to show that here, but it's it's relatively straightforward. You just to you just say you're gonna you want to use the big query API and there's there's a built-in editor that that has autocomplete and and And that enables you to to write to write Big query queries and then you can you can use those to use Google spreadsheets to to graph Although perhaps, you know, you're not you haven't totally drunk all the Google Kool-Aid and you want to use Microsoft Excel There's also an Excel connector that allow you to to run run big query queries from within Excel and use Excel's graphing mechanisms to to understand that In addition, there's there's some third-party tools There's a French called company called beam and and they do some really interesting Interesting big query visualizations The other one here is click view That can show some other ways other ways of looking at your data and finally we just integrated announced integration with Tableau Which is another data visualization company Based out of Seattle So here's to to to wrap up, you know big big query And that enables you to get get your results back in in seconds. It does full table scans over your data so you can They figured out a way to make make a full table scan fast by running in parallel And so you can ask much more complex questions and you knew what I would be able to Is in addition to running aggregate queries It's an API that's simple to use on a scale invariant That's one of the last the last point that I want to leave you leave you leave you with is that if you're using big query You shouldn't necessarily need to worry about is my data big or how is my data big enough to use big queries? My data too big to use big query You can run you can run queries over 10 row tables You can run queries over over a trillion row tables and it's just the same. It's the same architecture If you use, you know 10 row tables, it's likely going to be less expensive but But it should just just continue to work and the costs scale proportionally To the to the size of the data that you're you're using So thanks, thanks very much And I'm happy to answer any any questions that the people have Yes, you in the end Yeah, that's you in the stripe shirt When you use a cloud to services to how to upload the data imagine that you have several terabytes or whatever of data in your Services, how does how that can be done to upload to Google? That's the scale So the that's a great question. You know, how do we how do you get the data in? especially if you have terabytes of data and The the thing is usually when you have terabytes of data, you didn't get terabytes of data all at once It's often that that you're that you're bringing in smaller pieces of data every day And and your you know data grows over time so you can run you can run a pens to the same table As you're as you're getting as you're getting the data in, you know, maybe you're doing, you know A gigabyte a day 10 gigabytes a day You can you can break that up into pieces and upload it upload it to Google and Also, if you know if you've got it, I mean so the the wiki media Example that was third so of all the tables that we have that was it's over three terabytes And that took 37 minutes to import and into BigQuery So if you it can be a pain to upload it into Google stores once you once you've done that You know and you can do that in parallel you can do that You know via a number of a number of mechanisms that once you do that it's it's you know getting it into to BigQuery can be Is is has been heavily optimized you can also compress the files Which should give you a little bit a little bit more bandwidth bandwidth improvement. Would you realize that it's you know, it's Four very large data data systems. It's it's it's a tough tough question and And it's but it's also one that we're working on on on improving I mean so Google Compute Engine will be should be available pretty soon for generating your data via, you know Hadoop job into Google Compute Engine You know, we'll have fast pipes to get that into to BigQuery You know if you're running an Amazon's cloud you should be able to to post it still to to Google Cloud storage Any other questions? Yes. Oh Okay, sure So since you don't have a microphone you want to just ask and I'll repeat your question I'm actually not not as familiar with with with Impala. I think there's there's significant differences There's also a an open source Project as part of it. It's an Apache incubator project called drill. That's attempt. That's trying to sort of replicate the The the dremel paper, but that's still in its infancy They don't yet have a working version yet. I'm sorry. I don't I don't know more about Impala Sure Yes one in the back What do you think is the best combination for this technology to? Combinate this with a business intelligence Classical approach or with a big data Hadoop approach How does it coexist with a Hadoop project with a stone and all these elements? What is the intersections and the value that each other gives to the other part? So that that's that's a good question. I think it's If you're if you're using if you're using Hadoop and you're storing your data in and Hadoop Hadoop FS or HDFS You know, you do have to run an export export mechanism to get it into to BigQuery and so it's a non it's non trivial to Integrate I mean that said if you if you are you know using Hadoop you should be able to as you're sort of final reduce and you in a reduced step Write write your data to the to the big query Table so I Guess the the It's a weasley answer the integration right now is not it's not great And that's something but it's something we're actively actively working on we want to we know that that the data analysis is only one portion of the big data story and And that what we need to do is we need to have a wider wider offering that's all I can tell you and tell you now, but Anything else? Okay Yes, so the so the question was is there a way to To query over your data. That's an App Engine data store and so App Engine So we just worked with App Engine to They released a beta beta backup version. So you Via App Engine you you can you can You can say you want to back up your data to a big query table That triggers a big query import job and then you can run you can run queries queries over that So that happens all sort of internally with Google and it's very It's very easy to use you can if you you know search for that You it's I think it's a public beta that you can sign up sign up for if you're interested Anything else? Thank you


Hello everyone. Good morning, good afternoon and good evening, depending on where you are located. Today I'm going to talk about Ballerina, the open source cloud native programming language. More specifically about its next version, so on there. I imagine seeing that currently working on the Ballerina project at WSO2, I'm also a member of the Apaches of Dev Foundation. Let's talk what's Ballerina in simple terms. Ballerina is an open source programming language built for the cloud to make it easier to use, combine and create network services. Before moving on, let's have a look at a little bit of history on Ballerina. Work on Ballerina programming language started in 2016 and the language was created by WSO2 and the first table release was done in 2019, which was 1.0 and we presented that question at Open Source Summit in Japan last year as well. The next major version of the language is named Swan Lake and it's a complete revamp compared to its predecessor and we have made a lot of use of built-in improvements and reliability improvements. We are planning to make it generally available in quarter one next year and right now beta versions are available and beta 4 is the latest version available. During this presentation, first I'll be talking about why we decided to develop Ballerina and then I'll take you to a tour around Ballerina's capabilities. Then we'll look at the roadmap and what to look forward to and finally how to learn Ballerina, how to interact with the community and the ecosystem. Let's start with why we decide to develop Ballerina. To answer that, let's consider this. How is it like to develop software for the cloud nowadays? Suppose your organization has several teams developing several microservices and you have to develop a new microservice. Most probably your microservice or your new API that you're going to develop will depend on third party APIs or services or APIs provided by other teams or in your same organization. That means writing code today means integrating or using capabilities provided by other services and APIs. Once you are done writing the code, the next step is to build and package it to Docker. Once that's done, the next phase will be to the deployment. You will have a different environment like pre-prod and dev like that and you will have to write deployment descriptors be it Kubernetes or serverlet and then you will have to deploy that into those clusters. Once you have done with the deployment, the next phase will be the scaling. Sometimes those two deployment descriptors, deployment and scaling both go hand in hand but the scaling part is the next fact that we have to consider. When the load varies, your service should scale horizontally accordingly. Then you will have to think about managing access when other teams or other external parties rely on your API. They start when they start using your APIs, security aspects and access controlling work. Then the next one will be continuously monitoring. Due to the distributed nature, you will have to have a full view of what's going on with your service at the operational level. At the same time, you need analytics to have an understanding of to get business insights and for growth thinking aspects. As you can see, developing software for cloud era involves a lot. It's not just writing code. It works with different areas you had to consider a lot of factors and these are not limited to the ones that we talked about. For example, we have concepts like dual fact-tap, then fallacies of distributed computing, different protocols, networking primitives and security best practices, different deployment technologies like Kubernetes and serverless. That way, the cloud data ecosystem or writing code for the cloud has become more and more complex. This made us think, how much time do you spend on non-functional recurring tasks in the name of cloud data? And how much time do you spend gaining expertise in cloud technologies? That's what we need out of Bellrita. That's how we got the idea of Bellrita. Then you may wonder, what's the problem with existing programming languages or like recent frameworks? First of all, that's good. It's a good way to keep on going. But we saw a few fundamental issues. First, almost all the popular programming languages create network as a new resource. But in Bellrita, we treat them the network as an inherent part of the language. And when talking about the cloud nativeness of existing programming languages, they have been repurposed with libraries and frameworks. So when you are to make your true cloud nativeness, you will have to use a stack of different libraries. And not that a library or a framework is another level of abstraction that's provided on top of the abstraction provided by programming language. What will happen if you want to go beyond discover the framework? Then at that point, you will no longer be in the comfortness of the framework. People usually go with libraries and frameworks because they are familiar with the underlying programming language. Considering all those facts, we thought of doing Bellrita. And when talking about Bellrita, instead of repurposing existing technologies, Bellrita addressed them from the first principles. And Bellrita is zero leakage. That means anything can program with Bellrita and everything that's in code is usual. Bellrita has a good low code aspect. We will see in the end of the presentation that part as well. And Bellrita abstracts the network interactions and saves the developers from fallacies of distributed computing. The most important thing is Bellrita let developers to focus on value addition into their business domain. Due to these reasons, we think Bellrita is an ideal candidate to be the programming language for the cloud dealer. To get more understanding, let's take a deep dive and have a look at what features capabilities Bellrita offers. First of all, before starting on that, to set up Bellrita, you will need to install you have to download the Bellrita installers from the website. You can visit our download page and download the installer matching your platform with Windows Linux or Mac OS or if required, you can build it from a zip. You can download it as a zip or build from the source as well. And once you have installed Bellrita, you can verify if the installation was successful using a command-like version. And the next one that comes to our mind is the IDE tooling. For that, Bellrita has a feature rich VS Code plugin and you can download it from the VS Code marketplace. Let me show that to you. So in the VS Code marketplace, when you search for Bellrita, the first one that comes up is the Bellrita VS Code plugin. You will see a deprecated Bellrita plugin which was for the Bellrita 1.x versions and this the one that we are using is a new one and targeting this one decrease. Download and install that one. I have already downloaded that and before getting our hands dirty, let's discuss a bit about how Bellrita looks like as an overview. So Bellrita is a flexibility type, relaxed language and it's reliable and maintainable. Bellrita is a statically type so that type compatibilities are validated at the compile time and it's structural. So Bellrita compares the shapes of types instead of the names to determine subparibs. And Bellrita has explicit error handling and Bellrita is concurrent set and it has a familiar and intuitive syntax. You will see that while we are doing the demo in the upcoming slides. Let's move. Bellrita is open by default. That means Bellrita tries to be conservative in what we are sending and be liberal in what we are accepting. This to demonstrate that this is an example. This is a closed record named product and if you look at that, it has fields called name, description, price and currency. These are required fields and it has a field name ID which is an optional field and then it has a rest field which is of type JSON. That means a product should have name, description, price and currency and optionally have an ID and there can be other fields which are subtypes of JSON like in float, string and JSON itself. Like that. You will see them in action in the upcoming demo. And Bellrita is data oriented. Bellrita has a rich language integrated SQL like query syntax which you can use to query, list tables and streams. Yes, Bellrita has streams and tables. Stream is a good way to process events or process large amount of amounts of data without worrying about the limitations and table syntax is to represent a table. That means a collection of records where a table has a key and a key can be a simple or a complex one. And if you take this query example, we have a products list and we are querying for the products which has a price higher than 50 and the currency is USD. And at the same time, we are converting the price of the product into GBP by applying a conversion ratio and then returning a new set of products whose currencies are in GBP. So you can use this language integrated queries in interesting ways and intuitive ways because SQL like clauses are familiar to us. We have the from clause, from let limit order by where those clauses and select clause like that. And Bellrita is good. Bellrita has a concept called strands which are like threads and Bellrita has workers which are the realization that means workers are the ones that are going to spawn strands and you can use futures in Bellrita to run functions synchronously. This is an example of using strands and workers. So here we have two workers worker one and worker two and you can see that worker one and worker two are passing messages across them using these arrow icons, arrow symbols, they are called synductions and at the end the main strand or the main the function is waiting for both worker one and worker two to finish. A thread in Bellrita can have multiple strands and only one strand belonging to a given thread can run at a given time. So it's cooperatively multitasking. Yeah, this is just how to run a function synchronously. You get a future and you can wait for the future to complete and do something else as well. And the other interesting thing about concurrency in Bellrita is asynchronous IU. Bellrita has a concept called remote methods and when you are unlocking a remote method Bellrita runtime make sure the call is not working and but I'll demonstrate that during the demo I said and this is really useful when you are handling a large number of connections and you don't have to use explicit callbacks or listeners to handle the asynchronous behavior. The other aspect is Bellrita is graphical. Bellrita has a graphical representation using flowcharts and sequence diagrams and it's leak-free that means anything you code in Bellrita language can be can be visualized and vice versa. It has a really good local recipe which you can use used to which is good for non-technical people or less technical people to understand code logic or to do coding it's local programming as well. And this is a simple example of such flowchart of a method. Now let's move on to the most important part of Bellrita. That's the cloud net in this. Let's get our hands dirty for this. Let's build a simple currency conversion service which will behave like this. So this is the request that we will be sending at the end. So it will have two part terms one is the base currency the other one is the target currency and an amount. What this means is the amount is in USD right now and we want to convert that to GBP and in this program we will be using an external service to get the exchange rates and do the conversion. Now let's go to VS Code. Okay. I have already created the Bellrita project and this is my Bellrita project. As you see the Bellrita project has this Bellrita automobile which is the main configuration file which specifies the package name and things like that and also the dependencies and main dot bell is the one that was generated automatically and dot bell is the extension of Bellrita's source file and let's try to our service. Now in Bellrita, I said that network imprimitives are built to the language itself. So Bellrita has a concept called services, listeners and clients. So in our case what we are going to write is an HTTP service specifically HTTP REST API and it will have a gate method. To represent that in Bellrita we can simply write a service on an HTTP list like this and we are going to listen on for NAPA 8080. What we created here is a service, the HTTP service because our listener is an HTTP listener and port is 8080. The listener is the one that's going to interact between the network and the service and listener will be taking the messages coming in through the network and passing them to the service and to the resource methods. The service has a set of resource methods and in our case it will be a gate method, a gate HTTP method and note that our request will be current slash then path parameters and the query parameter. We can write this in Bellrita like this. So our context path is slash we gave it here and from this point on that our request path is current then we have our first path parameter which is base currency and then we have the second path parameter which is the target currency and we have a query parameter which is a float for the amount and this will return a float. The float will be the return one will be the converted value. And within this resource function we have to invoke an external API to get the exchange rate. For that I'm going to use this API and to invoke that we have to create HTTP client. I'm going to name it DCC client since this is like dynamic currency conversion and you have to specify the base path of the when you're creating the client and yeah okay we create the client and now we have to invoke the external service to do that we are we are going to send a gate request and this is how we are going to send that gate request in Bellrita and as you can see this is the remote function call this is this is the remote function invocation in Bellrita. I'll talk about that later as well and we need to pass the base currency here to get the conversion rates and to do that I'm going to use the spring templates in Bellrita and so that I can pass the base currency as a parameter like this yeah just like this and now we need to get the response I'm going to get the response as a JSON like this and note that Bellrita has simple support for JSON and XML and here we are directly accessing the response as a JSON and note that in Bellrita you have to handle errors explicitly. So here what it reports is it says since this remote API call can fail it says it will return either a JSON or an error. So if there was an error we will use the check keyword to check that and if there was an error this will simply return the error and to symbolize that we will have to say this will return an error or a fault and let's log the response that we are getting first and let's say response and when you are logging you can use key value pairs like this and okay so we created this the basic implementation where we simply for now let's return zero here and yes let's run this program and see what's the response that we are getting so based on that we can do a lot of improvements to our service. I'm going to open another terminal and get our current command ready yeah I'm going to send a request to connect 100 US dollars to GVP and okay okay there's a typo here let's rerun the service it log the response and let's take it out and see how it looks like this is the response exchange rates response that we are getting and when formatted you can see it returns a success Boolean based the currency code of the base currency and the rates which is a map and each key is the currency code and in front of in front of the mother exchange rates let's represent this in barina using the record I'm going to create the record called conversion response and which will be an open record I'll tell you why and we know that there will be a Boolean called success and there'll be a string called base and a map of floors called rates and instead of yes and now we are going to say we will be receiving a conversion response now this is where the open by default principles come principle comes into play so in this response we saw it has a lot of fields but what we are interested in is the rates and whether the request was successful or not and the base currency code we can open that as well if required and by having an open record what you're saying is this is what we expect and if there are other fields that's fine you can have them but what you're saying is these are the ones that you're interested in and since now we have the response we have to take if the response was successful and if it wasn't we will have to return an error if it wasn't successful you'll have to return and say error saying exchange rates could be obtained and if it was successful we know that the rates contain our target currency which is GBP and this will return an optional slot because this key can be in the map or not and let's say right in Bellara you will I said that in Bellara you will have to handle errors explicitly and it's null set so because of that we will have to we get an optional slot and here we will have to check if rate is not there or rate is empty if it's empty that means we couldn't get the the exchange rate for the target currency and we will be printing that and we will add the target currency as a parameter to here as well so that when the if the error was locked it will be printed as well and from this point onwards after this checking Bellara compiler knows that rate rate is the flow so that we don't have to do any casting and Bellara compiler itself does the type narrowing and we just have to return the rate or the rate multiplied by the amount so this will be the the converted rate and I think we did the implementation let's set the log line here for us to see what's going on and in follow up converting currency and this currency is like this so as you can see when looking you can use key value pairs which is really helpful when you are doing log analysis using say log stash and elastic stack and the target currency and the amount and now what we have to do is let's just run this and see how it looks like now and let's send our request as expected we got somewhere around 75 100 USD is converted to GBP is around 75 GBP and similarly we can try another currency it's 136 Singapore dollars and like that and it's logging our request and right now we have done the implementation and probably yes we can do more policing to the service to the resource method by adding response codes there's a really nice way of doing that I'll just do that here you can say that it will be written in HTTP okay and then you can return it like this and the amount like this and yeah something like that this HTTP okay is an inbuilt record and instead of returning just a mirror you can do something like return bad request and HTTP internal server like that so as you can see this syntax is very intuitive it says we have a gate method like this and it expects it accepts base currency and path parameters and it has a query parameter and it will return an HTTP okay bad request to internal server like that but I'm not going to go deep into that part and I'll be revert it back and the next part is we have built we have created our code and the next part is building and packaging it into docker and also writing deployment in sweepers for that bellina has you can create the docker image using bell build minus minus cloud equals docker with this one it'll be just created in the docker image but in our case we want the docker image plus the Kubernetes deployment descriptors and for that I'm going to use minus minus cloud gates and with that it will output the Kubernetes deployment descriptors as well while it's running in the platform I'll demonstrate one more thing actually I want to demonstrate two more things first one is once once we have written this service like this you can generate the open APS specification using bell open API and give the source file where you have the service and it'll output the open APS specification and you can share that open APS specification with external parties so that they can generate clients and connect to your service easily okay the open APS specification was generated and this is that this is our request path then we have the base currency and target currency as required path parameters and then we have a query parameter called the mount and it's required as well and as responses we have 200 okay and 500 yeah so if you had used defined types here instead of float it'll have those schemas in the open APS specification as well and okay in the meantime our bell build was successful and it prints out the command to run to deploy your the generated deployment the generated artifact through a Kubernetes cluster and also it prints out the command to expose your deployment through your Kubernetes cluster as well I'm not going to demonstrate that due to the time limitations but let's have a look at the Kubernetes deployment descriptor and if you look at that you can see that you have a service and then you have the deployment and in the deployment you have the memory limits and the port not that these memory limits were configured in the cloud.toml file and I had done that done that previously and you can use the cloud.toml file to specify the container image name tag and those stuff as well you can do more fine tuning with the cloud.toml as well and finally it has a horizontal auto scale for you to scale okay now we are almost done with the deployment with our writing our service now we are left with the observability part and before that I'm going to show one more thing that's the configurables in bellina in bellina you have configurable variables I probably we will want the port to be configurable so for such cases you can create a configurable variable like this and pass that into the program using a config.toml file and here we can see to say the port is this and this config.toml can be passed during the runtime or can be mounted to your Docker image like that so that flexibility is there and you don't have to use environment variables anymore and yeah now let's go move on to the observability aspects bellina is fully observable with you can monitor metrics with prafana and from it just out of the box and you can do distributed tracing with open telemetry and we are using GA as the open telemetry implementation compatible implementation and then you can do log analysis using elk by feeding bellina logs to your to log stash or to log stack directed to the docker looking right as and if we are to enable observability to this our disservice we simply have to add two import one miss the jager import and the jager for tracing and then from it yes for metrics and then we will have to enable metrics like this in the config.toml and this is optional and using the config.toml you can specify the jager host and ports and those stuff as well and we have enabled observability for bellina and in the bellina.toml we specify observability included true that's by default true and once we are done we just have to run this and for this to send metrics we need jager and from it is running and to do that I already have a docker compost deployment prepared to create the jager grapana and comitius instances and I'm going to start that test with that I'm going to start from it yes grapana and open telemetry this jager with that and okay those services are up and let's go and look at let's first send the request and go and look at jager so I just sent this this needy request and another one let's set the same request again and let's go and look at the traces in jager okay so our service is belonging to the context path slash and our operation we are interested in the get method for carasecan version and let's find the traces yeah as expected there are traces for two requests and this is the first one as you can see it comes to the resource method and to the it goes to the gdb client and then it goes out to the external service and that's the call that has taken most time and yeah and this it's going to the external service like this and let's go back and see the next request and there's an interesting observation that the time taken for the second one is real low and that's because the client we are using is caching the response and it's returning a cache response instead of sending the request to the actual external endpoint and that's for the tracing you can bellona can trace across multiple services and I chose a very simple demonstration today the next part is with the Prometheus with metrics and for that let's go to grapana and let's look in and skip this one and let's say Prometheus has the data source and let's test it's successful the next thing is we have to import the bellona dashboard and bellona has a grapana dashboard already available in the grapana marketplace and its ids 5841 these are documented in the bellona website will document it and I'm going to import this dashboard and along with that we have to specify the data source it will be from it yes and here we go we got a full view of the our system right now the uptime and the true port number of requests we have sent free so far and the top five services the first one is the metrics endpoint that's used by grapana or Prometheus and these are our services and and remote services this is the remote endpoint that you are invoking and like the list and the request in the meantime so don't you press and let's wait for the stop date as well yeah the count went to five as expected and yeah you can monitor status codes errors and stuff with this and you can explore more through the bellona website and let's move on with the presentation and there's one last thing that I need to mention actually two one is this asynchronous remote method call this call is non-blocking even though it looks like it's blocking call it's non-blocking and it's really useful for even handling multiple a lot of active connections and the other one is the bellona low code view and let me open the bellona low code view for this and I'm going to open the local view for our git resource and at the same time I'm going to open the bellona sort sort side by side and here as you can see this is our service and this is the local diagram corresponding to our resource function and yeah let me yeah so meet like this and it's a it shows that we are sending a request to the external client bcc client using SQL diagrams and we have flow charts here the flow control and like that this is really good for non-technical people and to less technical people to do programming itself or to understand code like that and with that I think I demonstrated almost all the things that I want to show with bellona and not that we covered almost all the aspects regarding related to developing coding for the cloud from writing code to building docker and kuban dc images to scaling to observability and next let's move on with the presentation so we discussed these past listeners services and bellona has support for protocols like a ttp ttp2 that's grpc website you can look them up in that bellona website you can write this api graph ql apis or vrpc apis easily we saw the open api tool bellona htp client support fail or load balancing we see we try those aspects as well we saw how we can use configurables in bellona code and we saw xml and json being available as types in the language and we saw how the response was converter seamlessly to our user defined type and here as in this example you can navigate xml through syntax as well talk about security in bellona we have work to jwt and basic code in bill in bill and ssl mutual ssl and authorization aspects just to give you a sneak peek if you wanted to protect this using with jwt you just have to add this annotation on top of them and in this one we are protecting this service using an external authorization server and using jwt and you can even protect individual resource functions like this and you can access control based on scopes for different resource functions differently based on a custom claim if required like that and yes let's move we talked about the core to cloud aspect and bellona has function necessary aspect as well which we i don't have time to demonstrate but bellona has in-built support for aws lambda and aws assure functions and this is how you could write an aws lambda function you just have to add the aws lambda annotation on top of a function and you look at the aws lambda context and the payload similarly this is a similar assure function but this is doing the same thing that we did in our our service that we wrote this is to convert from one currency to another given the amount and it's calling the same api and the interesting part is once you have written the function when you build it it'll output the safe files that you need to upload to assure aws. Observe will respect we talked about that and for CICD bellona has bellona g-tub correction which you can use to get a development environment up and running within your workflows and overall as we we have talked a lot of about bellona's scalabilities we can say bellona is better is included platform it comes with the package management a good really good standard library and a test framework and ID supporting and structured documentation and like that talk about bellona roadmap right now what we have is j bellona that means we compile bellona to an intermediate representation called bellona intermediate representation or BIR and then we generate bytecode and run from JVM as of now there's a parallel we're going on to develop a native compiler to compile bellona intermediate representation into native code and that's in bellona with that that in mind so on like is the next graduation of J bellona and as I said we are planning to make it generally available in quarter one 2022 and that cracker will be the release after that that that's expected in 2022 and we are planning we are hoping to release the native compiler bellona compiler by 2024 because it's lot of work and a great milestone and talk about bellona community bellona has really good community helpful very interactive you can join our select channel and ask questions in the user channel and you can ask questions in stack overflow as well and you can visit our bellona platform organization and star representries or report issues if you find any and you can attend community calls we hold community calls every month and there's a meet-up group for bellona user group as well you can join them and you can follow bellona twitter handle to get updates continuous updates on bellona and finally to learn more about bellona the best place will be this best starting point will be the bellona website and they are you have a lot of pointers there's this learn page where it has a separate guide for to learn by examples or language workflows and apart from that we have a bellona tech block which is made by the community on medium and we have bellona central which is the place where you can push packages for others to be available and with that we are coming to the end of our presentation and I hope within the limited time I could give you some reasonable idea about the capabilities of bellona and I invite you to look further into bellona and if required get help from the community as I mentioned and to summarize what I discussed bellona is trying to address actually your true cloud nativeness from the first principles instead of free purpose index technologies and bellona is flexible type concurrent data oriented and cloud native reliable material and graphical so talking about cloud native I said that we have network communities inbuilt and we saw how services and listeners are used and we saw the local view for the graphical aspect and I couldn't show you but using the local data you can edit the code as well so simultaneously and well we saw how open by default policies operating with open records and how seamless it was to get responses and use those responses when calling external endpoints and bellona abstract abstracts network interactions and sales developers from the falling into fallacies of the distributed computing and let developers focus more on implemented value-added features for their core business domain and finally as we showed bellona batteries included platform which comes with a lot of package management tool testing framework good idea support good documentation and free rich standard library like that and thank you for following me through this presentation I hope that I could give you some understanding about bellona and if you have any further questions you can ask them now and I invite you to also have a look at bellona after this presentation as well and yeah let's go on with questions if you have any and thank you for following the presentation